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