]>
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> | |
14 | #include <boost/detail/iterator.hpp> | |
15 | #include <boost/fusion/include/deque.hpp> | |
16 | #include <boost/tti/has_type.hpp> | |
17 | #include <boost/tti/has_member_function.hpp> | |
18 | #include <boost/mpl/identity.hpp> | |
19 | ||
20 | #include <vector> | |
21 | #include <string> | |
22 | #include <iterator> | |
23 | #include <algorithm> | |
24 | ||
25 | namespace boost { namespace spirit { namespace x3 { namespace traits | |
26 | { | |
27 | /////////////////////////////////////////////////////////////////////////// | |
28 | // This file contains some container utils for stl containers. | |
29 | /////////////////////////////////////////////////////////////////////////// | |
30 | ||
31 | namespace detail | |
32 | { | |
33 | BOOST_TTI_HAS_TYPE(value_type) | |
34 | BOOST_TTI_HAS_TYPE(iterator) | |
35 | BOOST_TTI_HAS_TYPE(size_type) | |
36 | BOOST_TTI_HAS_TYPE(reference) | |
37 | BOOST_TTI_HAS_TYPE(key_type) | |
38 | BOOST_TTI_HAS_MEMBER_FUNCTION(reserve) | |
39 | } | |
40 | ||
41 | template <typename T> | |
42 | using is_container = mpl::bool_< | |
43 | detail::has_type_value_type<T>::value && | |
44 | detail::has_type_iterator<T>::value && | |
45 | detail::has_type_size_type<T>::value && | |
46 | detail::has_type_reference<T>::value>; | |
47 | ||
48 | template <typename T> | |
49 | using is_associative = mpl::bool_< | |
50 | detail::has_type_key_type<T>::value>; | |
51 | ||
52 | template <typename T> | |
53 | using is_reservable = mpl::bool_< | |
54 | detail::has_member_function_reserve<T, void, mpl::vector<size_t>>::value>; | |
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(), std::move(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, std::move(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 boost::detail::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 |