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