]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/spirit/home/x3/support/traits/container_traits.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / spirit / home / x3 / support / traits / container_traits.hpp
1 /*=============================================================================
2 Copyright (c) 2001-2014 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_X3_CONTAINER_FEBRUARY_06_2007_1001AM)
10 #define BOOST_SPIRIT_X3_CONTAINER_FEBRUARY_06_2007_1001AM
11
12 #include <boost/fusion/support/category_of.hpp>
13 #include <boost/spirit/home/x3/support/unused.hpp>
14 #include <boost/fusion/include/deque.hpp>
15 #include <boost/tti/has_type.hpp>
16 #include <boost/mpl/identity.hpp>
17
18 #include <vector>
19 #include <string>
20 #include <iterator>
21 #include <algorithm>
22
23 namespace boost { namespace spirit { namespace x3 { namespace traits
24 {
25 ///////////////////////////////////////////////////////////////////////////
26 // This file contains some container utils for stl containers.
27 ///////////////////////////////////////////////////////////////////////////
28
29 namespace detail
30 {
31 BOOST_TTI_HAS_TYPE(value_type)
32 BOOST_TTI_HAS_TYPE(iterator)
33 BOOST_TTI_HAS_TYPE(size_type)
34 BOOST_TTI_HAS_TYPE(reference)
35 BOOST_TTI_HAS_TYPE(key_type)
36 }
37
38 template <typename T>
39 using is_container = mpl::bool_<
40 detail::has_type_value_type<T>::value &&
41 detail::has_type_iterator<T>::value &&
42 detail::has_type_size_type<T>::value &&
43 detail::has_type_reference<T>::value>;
44
45 template <typename T>
46 using is_associative = mpl::bool_<
47 detail::has_type_key_type<T>::value>;
48
49 template<typename T, typename Enable = void>
50 struct is_reservable : mpl::false_ {};
51
52 template<typename T>
53 struct is_reservable<T, decltype(std::declval<T&>().reserve(0))>
54 : mpl::true_ {};
55
56 ///////////////////////////////////////////////////////////////////////////
57 namespace detail
58 {
59 template <typename T>
60 struct remove_value_const : mpl::identity<T> {};
61
62 template <typename T>
63 struct remove_value_const<T const> : remove_value_const<T> {};
64
65 template <typename F, typename S>
66 struct remove_value_const<std::pair<F, S>>
67 {
68 typedef typename remove_value_const<F>::type first_type;
69 typedef typename remove_value_const<S>::type second_type;
70 typedef std::pair<first_type, second_type> type;
71 };
72 }
73
74 ///////////////////////////////////////////////////////////////////////
75 template <typename Container, typename Enable = void>
76 struct container_value
77 : detail::remove_value_const<typename Container::value_type>
78 {};
79
80 template <typename Container>
81 struct container_value<Container const> : container_value<Container> {};
82
83 // There is no single container value for fusion maps, but because output
84 // of this metafunc is used to check wheter parser's attribute can be
85 // saved to container, we simply return whole fusion::map as is
86 // so that check can be done in traits::is_substitute specialisation
87 template <typename T>
88 struct container_value<T
89 , typename enable_if<typename mpl::eval_if <
90 fusion::traits::is_sequence<T>
91 , fusion::traits::is_associative<T>
92 , mpl::false_ >::type >::type>
93 : mpl::identity<T> {};
94
95 template <>
96 struct container_value<unused_type> : mpl::identity<unused_type> {};
97
98 ///////////////////////////////////////////////////////////////////////////
99 template <typename Container, typename Enable = void>
100 struct container_iterator
101 : mpl::identity<typename Container::iterator> {};
102
103 template <typename Container>
104 struct container_iterator<Container const>
105 : mpl::identity<typename Container::const_iterator> {};
106
107 template <>
108 struct container_iterator<unused_type>
109 : mpl::identity<unused_type const*> {};
110
111 template <>
112 struct container_iterator<unused_type const>
113 : mpl::identity<unused_type const*> {};
114
115 ///////////////////////////////////////////////////////////////////////////
116 template <typename Container, typename T>
117 bool push_back(Container& c, T&& val);
118
119 template <typename Container, typename Enable = void>
120 struct push_back_container
121 {
122 template <typename T>
123 static bool call(Container& c, T&& val)
124 {
125 c.insert(c.end(), static_cast<T&&>(val));
126 return true;
127 }
128 };
129
130 template <typename Container, typename T>
131 inline bool push_back(Container& c, T&& val)
132 {
133 return push_back_container<Container>::call(c, static_cast<T&&>(val));
134 }
135
136 template <typename Container>
137 inline bool push_back(Container&, unused_type)
138 {
139 return true;
140 }
141
142 template <typename T>
143 inline bool push_back(unused_type, T&&)
144 {
145 return true;
146 }
147
148 inline bool push_back(unused_type, unused_type)
149 {
150 return true;
151 }
152
153 ///////////////////////////////////////////////////////////////////////////
154 template <typename Container, typename Iterator>
155 bool append(Container& c, Iterator first, Iterator last);
156
157 template <typename Container, typename Enable = void>
158 struct append_container
159 {
160 private:
161 template <typename Iterator>
162 static void reserve(Container& /* c */, Iterator /* first */, Iterator /* last */, mpl::false_)
163 {
164 // Not all containers have "reserve"
165 }
166
167 template <typename Iterator>
168 static void reserve(Container& c, Iterator first, Iterator last, mpl::true_)
169 {
170 c.reserve(c.size() + std::distance(first, last));
171 }
172
173 template <typename Iterator>
174 static void insert(Container& c, Iterator first, Iterator last, mpl::false_)
175 {
176 c.insert(c.end(), first, last);
177 }
178
179 template <typename Iterator>
180 static void insert(Container& c, Iterator first, Iterator last, mpl::true_)
181 {
182 c.insert(first, last);
183 }
184
185 public:
186 template <typename Iterator>
187 static bool call(Container& c, Iterator first, Iterator last)
188 {
189 reserve(c, first, last, is_reservable<Container>{});
190 insert(c, first, last, is_associative<Container>{});
191 return true;
192 }
193 };
194
195 template <typename Container, typename Iterator>
196 inline bool append(Container& c, Iterator first, Iterator last)
197 {
198 return append_container<Container>::call(c, first, last);
199 }
200
201 template <typename Iterator>
202 inline bool append(unused_type, Iterator /* first */, Iterator /* last */)
203 {
204 return true;
205 }
206
207 ///////////////////////////////////////////////////////////////////////////
208 template <typename Container, typename Enable = void>
209 struct is_empty_container
210 {
211 static bool call(Container const& c)
212 {
213 return c.empty();
214 }
215 };
216
217 template <typename Container>
218 inline bool is_empty(Container const& c)
219 {
220 return is_empty_container<Container>::call(c);
221 }
222
223 inline bool is_empty(unused_type)
224 {
225 return true;
226 }
227
228 ///////////////////////////////////////////////////////////////////////////
229 template <typename Container, typename Enable = void>
230 struct begin_container
231 {
232 static typename container_iterator<Container>::type call(Container& c)
233 {
234 return c.begin();
235 }
236 };
237
238 template <typename Container>
239 inline typename container_iterator<Container>::type
240 begin(Container& c)
241 {
242 return begin_container<Container>::call(c);
243 }
244
245 inline unused_type const*
246 begin(unused_type)
247 {
248 return &unused;
249 }
250
251 ///////////////////////////////////////////////////////////////////////////
252 template <typename Container, typename Enable = void>
253 struct end_container
254 {
255 static typename container_iterator<Container>::type call(Container& c)
256 {
257 return c.end();
258 }
259 };
260
261 template <typename Container>
262 inline typename container_iterator<Container>::type
263 end(Container& c)
264 {
265 return end_container<Container>::call(c);
266 }
267
268 inline unused_type const*
269 end(unused_type)
270 {
271 return &unused;
272 }
273
274
275 ///////////////////////////////////////////////////////////////////////////
276 template <typename Iterator, typename Enable = void>
277 struct deref_iterator
278 {
279 typedef typename std::iterator_traits<Iterator>::reference type;
280 static type call(Iterator& it)
281 {
282 return *it;
283 }
284 };
285
286 template <typename Iterator>
287 typename deref_iterator<Iterator>::type
288 deref(Iterator& it)
289 {
290 return deref_iterator<Iterator>::call(it);
291 }
292
293 inline unused_type
294 deref(unused_type const*)
295 {
296 return unused;
297 }
298
299 ///////////////////////////////////////////////////////////////////////////
300 template <typename Iterator, typename Enable = void>
301 struct next_iterator
302 {
303 static void call(Iterator& it)
304 {
305 ++it;
306 }
307 };
308
309 template <typename Iterator>
310 void next(Iterator& it)
311 {
312 next_iterator<Iterator>::call(it);
313 }
314
315 inline void next(unused_type const*)
316 {
317 // do nothing
318 }
319
320 ///////////////////////////////////////////////////////////////////////////
321 template <typename Iterator, typename Enable = void>
322 struct compare_iterators
323 {
324 static bool call(Iterator const& it1, Iterator const& it2)
325 {
326 return it1 == it2;
327 }
328 };
329
330 template <typename Iterator>
331 bool compare(Iterator& it1, Iterator& it2)
332 {
333 return compare_iterators<Iterator>::call(it1, it2);
334 }
335
336 inline bool compare(unused_type const*, unused_type const*)
337 {
338 return false;
339 }
340
341 ///////////////////////////////////////////////////////////////////////////
342 template <typename T>
343 struct build_container : mpl::identity<std::vector<T>> {};
344
345 template <typename T>
346 struct build_container<boost::fusion::deque<T> > : build_container<T> {};
347
348 template <>
349 struct build_container<unused_type> : mpl::identity<unused_type> {};
350
351 template <>
352 struct build_container<char> : mpl::identity<std::string> {};
353
354 }}}}
355
356 #endif