]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/spirit/home/karma/detail/extract_from.hpp
bump version to 18.2.4-pve3
[ceph.git] / ceph / src / boost / boost / spirit / home / karma / detail / extract_from.hpp
1 // Copyright (c) 2001-2011 Hartmut Kaiser
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6 #if !defined(BOOST_SPIRIT_KARMA_EXTRACT_FROM_SEP_30_2009_0732AM)
7 #define BOOST_SPIRIT_KARMA_EXTRACT_FROM_SEP_30_2009_0732AM
8
9 #if defined(_MSC_VER)
10 #pragma once
11 #endif
12
13 #include <boost/spirit/home/support/unused.hpp>
14 #include <boost/spirit/home/support/attributes_fwd.hpp>
15 #include <boost/spirit/home/karma/detail/attributes.hpp>
16 #include <boost/spirit/home/support/container.hpp>
17
18 #include <boost/ref.hpp>
19 #include <boost/optional.hpp>
20
21 ///////////////////////////////////////////////////////////////////////////////
22 namespace boost { namespace spirit { namespace traits
23 {
24 ///////////////////////////////////////////////////////////////////////////
25 // This file contains attribute extraction utilities. The utilities
26 // provided also accept spirit's unused_type; all no-ops. Compiler
27 // optimization will easily strip these away.
28 ///////////////////////////////////////////////////////////////////////////
29
30 namespace detail
31 {
32 ///////////////////////////////////////////////////////////////////////
33 // extract first and second element of a fusion sequence
34 template <typename T>
35 struct add_const_ref
36 : add_reference<typename add_const<T>::type>
37 {};
38
39 template <typename T, int N>
40 struct value_at_c
41 : add_const_ref<typename fusion::result_of::value_at_c<T, N>::type>
42 {};
43 }
44
45 // This is the default case: the plain attribute values
46 template <typename Attribute, typename Exposed
47 , bool IsOneElemSeq = traits::one_element_sequence<Attribute>::value>
48 struct extract_from_attribute_base
49 {
50 typedef Attribute const& type;
51
52 template <typename Context>
53 static type call(Attribute const& attr, Context&)
54 {
55 return attr;
56 }
57 };
58
59 // This handles the case where the attribute is a single element fusion
60 // sequence. We silently extract the only element and treat it as the
61 // attribute to generate output from.
62 template <typename Attribute, typename Exposed>
63 struct extract_from_attribute_base<Attribute, Exposed, true>
64 {
65 typedef typename remove_const<
66 typename remove_reference<
67 typename fusion::result_of::at_c<Attribute, 0>::type
68 >::type
69 >::type elem_type;
70
71 typedef typename result_of::extract_from<Exposed, elem_type>::type type;
72
73 template <typename Context>
74 static type call(Attribute const& attr, Context& ctx)
75 {
76 return extract_from<Exposed>(fusion::at_c<0>(attr), ctx);
77 }
78 };
79
80 template <typename Attribute, typename Exposed, typename Enable/*= void*/>
81 struct extract_from_attribute
82 : extract_from_attribute_base<Attribute, Exposed>
83 {};
84
85 // This handles optional attributes.
86 template <typename Attribute, typename Exposed>
87 struct extract_from_attribute<boost::optional<Attribute>, Exposed>
88 {
89 typedef Attribute const& type;
90
91 template <typename Context>
92 static type call(boost::optional<Attribute> const& attr, Context& ctx)
93 {
94 return extract_from<Exposed>(boost::get<Attribute>(attr), ctx);
95 }
96 };
97
98 template <typename Attribute, typename Exposed>
99 struct extract_from_attribute<boost::optional<Attribute const>, Exposed>
100 {
101 typedef Attribute const& type;
102
103 template <typename Context>
104 static type call(boost::optional<Attribute const> const& attr, Context& ctx)
105 {
106 return extract_from<Exposed>(boost::get<Attribute const>(attr), ctx);
107 }
108 };
109
110 // This handles attributes wrapped inside a boost::ref().
111 template <typename Attribute, typename Exposed>
112 struct extract_from_attribute<reference_wrapper<Attribute>, Exposed>
113 {
114 typedef Attribute const& type;
115
116 template <typename Context>
117 static type call(reference_wrapper<Attribute> const& attr, Context& ctx)
118 {
119 return extract_from<Exposed>(attr.get(), ctx);
120 }
121 };
122
123 ///////////////////////////////////////////////////////////////////////////
124 template <typename Attribute, typename Exposed, typename Enable>
125 struct extract_from_container
126 {
127 typedef typename traits::container_value<Attribute const>::type
128 value_type;
129 typedef typename is_convertible<value_type, Exposed>::type
130 is_convertible_to_value_type;
131
132 typedef typename mpl::if_<
133 mpl::or_<
134 is_same<value_type, Exposed>, is_same<Attribute, Exposed> >
135 , Exposed const&, Exposed
136 >::type type;
137
138 // handle case where container value type is convertible to result type
139 // we simply return the front element of the container
140 template <typename Context, typename Pred>
141 static type call(Attribute const& attr, Context&, mpl::true_, Pred)
142 {
143 // return first element from container
144 typedef typename traits::container_iterator<Attribute const>::type
145 iterator_type;
146
147 iterator_type it = traits::begin(attr);
148 type result = *it;
149 ++it;
150 return result;
151 }
152
153 // handle strings
154 template <typename Iterator>
155 static void append_to_string(Exposed& result, Iterator begin, Iterator end)
156 {
157 for (Iterator i = begin; i != end; ++i)
158 push_back(result, *i);
159 }
160
161 template <typename Context>
162 static type call(Attribute const& attr, Context&, mpl::false_, mpl::true_)
163 {
164 typedef typename char_type_of<Attribute>::type char_type;
165
166 Exposed result;
167 append_to_string(result, traits::get_begin<char_type>(attr)
168 , traits::get_end<char_type>(attr));
169 return result;
170 }
171
172 // everything else gets just passed through
173 template <typename Context>
174 static type call(Attribute const& attr, Context&, mpl::false_, mpl::false_)
175 {
176 return type(attr);
177 }
178
179 template <typename Context>
180 static type call(Attribute const& attr, Context& ctx)
181 {
182 typedef typename mpl::and_<
183 traits::is_string<Exposed>, traits::is_string<Attribute>
184 >::type handle_strings;
185
186 // return first element from container
187 return call(attr, ctx, is_convertible_to_value_type()
188 , handle_strings());
189 }
190 };
191
192 template <typename Attribute>
193 struct extract_from_container<Attribute, Attribute>
194 {
195 typedef Attribute const& type;
196
197 template <typename Context>
198 static type call(Attribute const& attr, Context&)
199 {
200 return attr;
201 }
202 };
203
204 ///////////////////////////////////////////////////////////////////////////
205 namespace detail
206 {
207 // overload for non-container attributes
208 template <typename Exposed, typename Attribute, typename Context>
209 inline typename spirit::result_of::extract_from<Exposed, Attribute>::type
210 extract_from(Attribute const& attr, Context& ctx, mpl::false_)
211 {
212 return extract_from_attribute<Attribute, Exposed>::call(attr, ctx);
213 }
214
215 // overload for containers (but not for variants or optionals
216 // holding containers)
217 template <typename Exposed, typename Attribute, typename Context>
218 inline typename spirit::result_of::extract_from<Exposed, Attribute>::type
219 extract_from(Attribute const& attr, Context& ctx, mpl::true_)
220 {
221 return extract_from_container<Attribute, Exposed>::call(attr, ctx);
222 }
223 }
224
225 template <typename Exposed, typename Attribute, typename Context>
226 inline typename spirit::result_of::extract_from<Exposed, Attribute>::type
227 extract_from(Attribute const& attr, Context& ctx
228 #if (defined(__GNUC__) && (__GNUC__ < 4)) || \
229 (defined(__APPLE__) && defined(__INTEL_COMPILER))
230 , typename enable_if<traits::not_is_unused<Attribute> >::type*
231 #endif
232 )
233 {
234 typedef typename mpl::and_<
235 traits::is_container<Attribute>
236 , traits::not_is_variant<Attribute>
237 , traits::not_is_optional<Attribute>
238 >::type is_not_wrapped_container;
239
240 return detail::extract_from<Exposed>(attr, ctx
241 , is_not_wrapped_container());
242 }
243
244 template <typename Exposed, typename Context>
245 inline unused_type extract_from(unused_type, Context&)
246 {
247 return unused;
248 }
249 }}}
250
251 ///////////////////////////////////////////////////////////////////////////////
252 namespace boost { namespace spirit { namespace result_of
253 {
254 template <typename Exposed, typename Attribute>
255 struct extract_from
256 : mpl::if_<
257 mpl::and_<
258 traits::is_container<Attribute>
259 , traits::not_is_variant<Attribute>
260 , traits::not_is_optional<Attribute> >
261 , traits::extract_from_container<Attribute, Exposed>
262 , traits::extract_from_attribute<Attribute, Exposed> >::type
263 {};
264
265 template <typename Exposed>
266 struct extract_from<Exposed, unused_type>
267 {
268 typedef unused_type type;
269 };
270
271 template <typename Exposed>
272 struct extract_from<Exposed, unused_type const>
273 {
274 typedef unused_type type;
275 };
276 }}}
277
278 #endif