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