]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/spirit/include/boost/spirit/home/qi/detail/assign_to.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / spirit / include / boost / spirit / home / qi / detail / assign_to.hpp
CommitLineData
7c673cae
FG
1/*=============================================================================
2 Copyright (c) 2001-2011 Joel de Guzman
3 Copyright (c) 2001-2011 Hartmut Kaiser
4 http://spirit.sourceforge.net/
5
6 Distributed under the Boost Software License, Version 1.0. (See accompanying
7 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8=============================================================================*/
9#if !defined(BOOST_SPIRIT_ASSIGN_TO_APR_16_2006_0812PM)
10#define BOOST_SPIRIT_ASSIGN_TO_APR_16_2006_0812PM
11
12#if defined(_MSC_VER)
13#pragma once
14#endif
15
16#include <boost/spirit/home/qi/detail/construct.hpp>
17#include <boost/spirit/home/support/unused.hpp>
18#include <boost/spirit/home/qi/detail/attributes.hpp>
19#include <boost/spirit/home/support/container.hpp>
20#include <boost/fusion/include/copy.hpp>
21#include <boost/fusion/adapted/struct/detail/extension.hpp>
22#include <boost/ref.hpp>
23#include <boost/range/iterator_range.hpp>
24
25namespace boost { namespace spirit { namespace traits
26{
27 ///////////////////////////////////////////////////////////////////////////
28 // This file contains assignment utilities. The utilities provided also
29 // accept spirit's unused_type; all no-ops. Compiler optimization will
30 // easily strip these away.
31 ///////////////////////////////////////////////////////////////////////////
32 namespace detail
33 {
34 template <typename T>
35 struct is_iter_range : mpl::false_ {};
36
37 template <typename I>
38 struct is_iter_range<boost::iterator_range<I> > : mpl::true_ {};
39
40 template <typename C>
41 struct is_container_of_ranges
42 : is_iter_range<typename C::value_type> {};
43 }
44
45 template <typename Attribute, typename Iterator, typename Enable>
46 struct assign_to_attribute_from_iterators
47 {
48 // Common case
49 static void
50 call(Iterator const& first, Iterator const& last, Attribute& attr, mpl::false_)
51 {
52 if (traits::is_empty(attr))
53 attr = Attribute(first, last);
54 else {
55 for (Iterator i = first; i != last; ++i)
56 push_back(attr, *i);
57 }
58 }
59
60 // If Attribute is a container with value_type==iterator_range<T> just push the
61 // iterator_range into it
62 static void
63 call(Iterator const& first, Iterator const& last, Attribute& attr, mpl::true_)
64 {
65 typename Attribute::value_type rng(first, last);
66 push_back(attr, rng);
67 }
68
69 static void
70 call(Iterator const& first, Iterator const& last, Attribute& attr)
71 {
72 call(first, last, attr, detail::is_container_of_ranges<Attribute>());
73 }
74 };
75
76 template <typename Attribute, typename Iterator>
77 struct assign_to_attribute_from_iterators<
78 reference_wrapper<Attribute>, Iterator>
79 {
80 static void
81 call(Iterator const& first, Iterator const& last
82 , reference_wrapper<Attribute> attr)
83 {
84 if (traits::is_empty(attr))
85 attr = Attribute(first, last);
86 else {
87 for (Iterator i = first; i != last; ++i)
88 push_back(attr, *i);
89 }
90 }
91 };
92
93 template <typename Attribute, typename Iterator>
94 struct assign_to_attribute_from_iterators<
95 boost::optional<Attribute>, Iterator>
96 {
97 static void
98 call(Iterator const& first, Iterator const& last
99 , boost::optional<Attribute>& attr)
100 {
101 Attribute val;
102 assign_to(first, last, val);
103 attr = val;
104 }
105 };
106
107 template <typename Iterator>
108 struct assign_to_attribute_from_iterators<
109 iterator_range<Iterator>, Iterator>
110 {
111 static void
112 call(Iterator const& first, Iterator const& last
113 , iterator_range<Iterator>& attr)
114 {
115 attr = iterator_range<Iterator>(first, last);
116 }
117 };
118
119 template <typename Iterator, typename Attribute>
120 inline void
121 assign_to(Iterator const& first, Iterator const& last, Attribute& attr)
122 {
123 assign_to_attribute_from_iterators<Attribute, Iterator>::
124 call(first, last, attr);
125 }
126
127 template <typename Iterator>
128 inline void
129 assign_to(Iterator const&, Iterator const&, unused_type)
130 {
131 }
132
133 ///////////////////////////////////////////////////////////////////////////
134 template <typename T, typename Attribute>
135 void assign_to(T const& val, Attribute& attr);
136
137 template <typename Attribute, typename T, typename Enable>
138 struct assign_to_attribute_from_value
139 {
140 typedef typename traits::one_element_sequence<Attribute>::type
141 is_one_element_sequence;
142
143 typedef typename mpl::eval_if<
144 is_one_element_sequence
145 , fusion::result_of::at_c<Attribute, 0>
146 , mpl::identity<Attribute&>
147 >::type type;
148
149 template <typename T_>
150 static void
151 call(T_ const& val, Attribute& attr, mpl::false_)
152 {
153 attr = static_cast<Attribute>(val);
154 }
155
156 // This handles the case where the attribute is a single element fusion
157 // sequence. We silently assign to the only element and treat it as the
158 // attribute to parse the results into.
159 template <typename T_>
160 static void
161 call(T_ const& val, Attribute& attr, mpl::true_)
162 {
163 typedef typename fusion::result_of::value_at_c<Attribute, 0>::type
164 element_type;
165 fusion::at_c<0>(attr) = static_cast<element_type>(val);
166 }
167
168 static void
169 call(T const& val, Attribute& attr)
170 {
171 call(val, attr, is_one_element_sequence());
172 }
173 };
174
175 template <typename Attribute>
176 struct assign_to_attribute_from_value<Attribute, Attribute>
177 {
178 static void
179 call(Attribute const& val, Attribute& attr)
180 {
181 attr = val;
182 }
183 };
184
185 template <typename Attribute, typename T>
186 struct assign_to_attribute_from_value<Attribute, reference_wrapper<T>
187 , typename disable_if<is_same<Attribute, reference_wrapper<T> > >::type>
188 {
189 static void
190 call(reference_wrapper<T> const& val, Attribute& attr)
191 {
192 assign_to(val.get(), attr);
193 }
194 };
195
196 template <typename Attribute, typename T>
197 struct assign_to_attribute_from_value<Attribute, boost::optional<T>
198 , typename disable_if<is_same<Attribute, boost::optional<T> > >::type>
199 {
200 static void
201 call(boost::optional<T> const& val, Attribute& attr)
202 {
203 assign_to(val.get(), attr);
204 }
205 };
206
207 template <typename Attribute, int N, bool Const, typename T>
208 struct assign_to_attribute_from_value<fusion::extension::adt_attribute_proxy<Attribute, N, Const>, T>
209 {
210 static void
211 call(T const& val, typename fusion::extension::adt_attribute_proxy<Attribute, N, Const>& attr)
212 {
213 attr = val;
214 }
215 };
216
217 namespace detail
218 {
219 template <typename A, typename B>
220 struct is_same_size_sequence
221 : mpl::bool_<fusion::result_of::size<A>::value
222 == fusion::result_of::size<B>::value>
223 {};
224 }
225
226 template <typename Attribute, typename T>
227 struct assign_to_attribute_from_value<Attribute, T,
228 mpl::and_<
229 fusion::traits::is_sequence<Attribute>,
230 fusion::traits::is_sequence<T>,
231 detail::is_same_size_sequence<Attribute, T>
232 >
233 >
234 {
235 static void
236 call(T const& val, Attribute& attr)
237 {
238 fusion::copy(val, attr);
239 }
240 };
241
242 ///////////////////////////////////////////////////////////////////////////
243 template <typename Attribute, typename T, typename Enable>
244 struct assign_to_container_from_value
245 {
246 // T is not a container and not a string
247 template <typename T_>
248 static void call(T_ const& val, Attribute& attr, mpl::false_, mpl::false_)
249 {
250 traits::push_back(attr, val);
251 }
252
253 // T is a container (but not a string), and T is convertible to the
254 // value_type of the Attribute container
255 template <typename T_>
256 static void
257 append_to_container_not_string(T_ const& val, Attribute& attr, mpl::true_)
258 {
259 traits::push_back(attr, val);
260 }
261
262 // T is a container (but not a string), generic overload
263 template <typename T_>
264 static void
265 append_to_container_not_string(T_ const& val, Attribute& attr, mpl::false_)
266 {
267 typedef typename traits::container_iterator<T_ const>::type
268 iterator_type;
269
270 iterator_type end = traits::end(val);
271 for (iterator_type i = traits::begin(val); i != end; traits::next(i))
272 traits::push_back(attr, traits::deref(i));
273 }
274
275 // T is a container (but not a string)
276 template <typename T_>
277 static void call(T_ const& val, Attribute& attr, mpl::true_, mpl::false_)
278 {
279 typedef typename container_value<Attribute>::type value_type;
280 typedef typename is_convertible<T, value_type>::type is_value_type;
281
282 append_to_container_not_string(val, attr, is_value_type());
283 }
284
285 ///////////////////////////////////////////////////////////////////////
286 // T is a string
287 template <typename Iterator>
288 static void append_to_string(Attribute& attr, Iterator begin, Iterator end)
289 {
290 for (Iterator i = begin; i != end; ++i)
291 traits::push_back(attr, *i);
292 }
293
294 // T is string, but not convertible to value_type of container
295 template <typename T_>
296 static void append_to_container(T_ const& val, Attribute& attr, mpl::false_)
297 {
298 typedef typename char_type_of<T_>::type char_type;
299
300 append_to_string(attr, traits::get_begin<char_type>(val)
301 , traits::get_end<char_type>(val));
302 }
303
304 // T is string, and convertible to value_type of container
305 template <typename T_>
306 static void append_to_container(T_ const& val, Attribute& attr, mpl::true_)
307 {
308 traits::push_back(attr, val);
309 }
310
311 template <typename T_, typename Pred>
312 static void call(T_ const& val, Attribute& attr, Pred, mpl::true_)
313 {
314 typedef typename container_value<Attribute>::type value_type;
315 typedef typename is_convertible<T, value_type>::type is_value_type;
316
317 append_to_container(val, attr, is_value_type());
318 }
319
320 ///////////////////////////////////////////////////////////////////////
321 static void call(T const& val, Attribute& attr)
322 {
323 typedef typename traits::is_container<T>::type is_container;
324 typedef typename traits::is_string<T>::type is_string;
325
326 call(val, attr, is_container(), is_string());
327 }
328 };
329
330 template <typename Attribute>
331 struct assign_to_container_from_value<Attribute, Attribute>
332 {
333 static void
334 call(Attribute const& val, Attribute& attr)
335 {
336 attr = val;
337 }
338 };
339
340 template <typename Attribute, typename T>
341 struct assign_to_container_from_value<Attribute, boost::optional<T>
342 , typename disable_if<is_same<Attribute, boost::optional<T> > >::type>
343 {
344 static void
345 call(boost::optional<T> const& val, Attribute& attr)
346 {
347 assign_to(val.get(), attr);
348 }
349 };
350
351 template <typename Attribute, typename T>
352 struct assign_to_container_from_value<Attribute, reference_wrapper<T>
353 , typename disable_if<is_same<Attribute, reference_wrapper<T> > >::type>
354 {
355 static void
356 call(reference_wrapper<T> const& val, Attribute& attr)
357 {
358 assign_to(val.get(), attr);
359 }
360 };
361
362 ///////////////////////////////////////////////////////////////////////////
363 namespace detail
364 {
365 // overload for non-container attributes
366 template <typename T, typename Attribute>
367 inline void
368 assign_to(T const& val, Attribute& attr, mpl::false_)
369 {
370 assign_to_attribute_from_value<Attribute, T>::call(val, attr);
371 }
372
373 // overload for containers (but not for variants or optionals
374 // holding containers)
375 template <typename T, typename Attribute>
376 inline void
377 assign_to(T const& val, Attribute& attr, mpl::true_)
378 {
379 assign_to_container_from_value<Attribute, T>::call(val, attr);
380 }
381 }
382
383 template <typename T, typename Attribute>
384 inline void
385 assign_to(T const& val, Attribute& attr)
386 {
387 typedef typename mpl::and_<
388 traits::is_container<Attribute>
389 , traits::not_is_variant<Attribute>
390 , traits::not_is_optional<Attribute>
391 >::type is_not_wrapped_container;
392
393 detail::assign_to(val, attr, is_not_wrapped_container());
394 }
395
396 template <typename T>
397 inline void
398 assign_to(T const&, unused_type)
399 {
400 }
401}}}
402
403#endif