Bond
 
Loading...
Searching...
No Matches
stl_containers.h
1// Copyright (c) Microsoft. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
4#pragma once
5
6#include <bond/core/config.h>
7
8#include "container_interface.h"
9#include "traits.h"
10
11#include <boost/utility/enable_if.hpp>
12
13#include <list>
14#include <map>
15#include <set>
16#include <stdint.h>
17#include <string>
18#include <vector>
19
20// Bond container interface on top of STL container classes
21
22namespace bond
23{
24
25template <typename Key>
26[[noreturn]] void ElementNotFoundException(const Key& key);
27
28// is_string<std::basic_string<char, T, A> >
29template<typename T, typename A> struct
30is_string<std::basic_string<char, T, A> >
31 : std::true_type {};
32
33
34// is_wstring<std::basic_string<wchar_t, T, A> >
35template<typename T, typename A> struct
36is_wstring<std::basic_string<wchar_t, T, A> >
37 : std::true_type {};
38
39
40// is_string_type
41template <typename T> struct
42is_string_type
43 : std::integral_constant<bool,
44 is_string<typename std::remove_const<T>::type>::value
45 || is_wstring<typename std::remove_const<T>::type>::value> {};
46
47
48// is_list_container<std::list<T, A> >
49template <typename T, typename A> struct
50is_list_container<std::list<T, A> >
51 : std::true_type {};
52
53
54// is_list_container<std::vector<T, A> >
55template <typename T, typename A> struct
56is_list_container<std::vector<T, A> >
57 : std::true_type {};
58
59
60// require_modify_element<std::vector<bool, A> >
61template <typename A> struct
62require_modify_element<std::vector<bool, A> >
63 : std::true_type {};
64
65
66// is_set_container<std::set<T, C, A> >
67template <typename T, typename C, typename A> struct
68is_set_container<std::set<T, C, A> >
69 : std::true_type {};
70
71
72// is_map_container<std::map<K, T, C, A> >
73template <typename K, typename T, typename C, typename A> struct
74is_map_container<std::map<K, T, C, A> >
75 : std::true_type {};
76
77
78// specialize element_type for map becuase map::value_type is pair<const K, T>
79template <typename K, typename T, typename C, typename A> struct
80element_type<std::map<K, T, C, A> >
81{
82 typedef typename std::pair<K, T> type;
83};
84
85
86// string_data
87template<typename C, typename T, typename A>
88inline
89const C* string_data(const std::basic_string<C, T, A>& str)
90{
91 return str.data();
92}
93
94
95template<typename C, typename T, typename A>
96inline
97C* string_data(std::basic_string<C, T, A>& str)
98{
99 // C++11 disallows COW string implementation (see [string.require] 21.4.1)
100 // however it was permitted in C++03. In order to support COW we can't
101 // return data() here.
102 static C c;
103 return str.size() ? &*str.begin() : &c;
104}
105
106
107// string_length
108template<typename C, typename T, typename A>
109inline
110uint32_t string_length(const std::basic_string<C, T, A>& str)
111{
112 return static_cast<uint32_t>(str.length());
113}
114
115
116// resize_string
117template<typename C, typename T, typename A>
118inline
119void resize_string(std::basic_string<C, T, A>& str, uint32_t size)
120{
121 str.resize(size);
122}
123
124
125// container_size
126template <typename T>
127inline
128uint32_t container_size(const T& list)
129{
130 return static_cast<uint32_t>(list.size());
131}
132
133
134// use_container_allocator_for_elements
135template <typename T, typename Enable = void> struct
136use_container_allocator_for_elements
137 : std::false_type {};
138
139
140template <typename T> struct
141use_container_allocator_for_elements<T, typename boost::enable_if_c<
142 std::uses_allocator<typename element_type<T>::type, typename T::allocator_type>::value>::type>
143 : std::true_type {};
144
145
146// make_element
147template <typename T>
148inline
149typename boost::disable_if_c<use_container_allocator_for_elements<T>::value, typename element_type<T>::type>::type
150make_element(T& /*container*/)
151{
152 return typename element_type<T>::type();
153}
154
155
156template <typename T>
157inline
158typename boost::enable_if<use_container_allocator_for_elements<T>, typename element_type<T>::type>::type
159make_element(T& container)
160{
161 return typename element_type<T>::type(container.get_allocator());
162}
163
164template <typename T, typename E>
165inline
166void insert_list(T& list, const E& item)
167{
168 list.push_back(item);
169}
170
171
172// resize_list
173template <typename T>
174inline
175typename boost::disable_if<use_container_allocator_for_elements<T> >::type
176resize_list(T& list, uint32_t size)
177{
178 list.resize(size, make_element(list));
179}
180
181
182template <typename T>
183inline
184typename boost::enable_if<use_container_allocator_for_elements<T> >::type
185resize_list(T& list, uint32_t size)
186{
187 list.clear();
188 list.resize(size, make_element(list));
189}
190
191template <typename T>
192inline
193void reset_list(T& list, uint32_t/* size_hint*/)
194{
195 list.clear();
196}
197
198// modify_element
199template <typename A, typename F>
200inline
201void modify_element(std::vector<bool, A>&,
202 typename std::vector<bool, A>::reference element,
203 F deserialize)
204{
205 bool value;
206
207 deserialize(value);
208 element = value;
209}
210
211
212// clear_set
213template <typename T, typename C, typename A>
214inline
215void clear_set(std::set<T, C, A>& set)
216{
217 set.clear();
218}
219
220
221// set_insert
222template <typename T, typename C, typename A>
223inline
224void set_insert(std::set<T, C, A>& set, const T& item)
225{
226 set.insert(item);
227}
228
229
230// clear_map
231template <typename K, typename T, typename C, typename A>
232inline
233void clear_map(std::map<K, T, C, A>& map)
234{
235 map.clear();
236}
237
238
239// use_map_allocator_for_keys
240template <typename T, typename Enable = void> struct
241use_map_allocator_for_keys
242 : std::false_type {};
243
244
245template <typename T> struct
246use_map_allocator_for_keys<T, typename boost::enable_if<
247 std::uses_allocator<typename element_type<T>::type::first_type, typename T::allocator_type> >::type>
248 : std::true_type {};
249
250
251// make_key
252template <typename T>
253inline
254typename boost::disable_if<use_map_allocator_for_keys<T>, typename element_type<T>::type::first_type>::type
255make_key(T& /*map*/)
256{
257 return typename element_type<T>::type::first_type();
258}
259
260
261template <typename T>
262inline
263typename boost::enable_if<use_map_allocator_for_keys<T>, typename element_type<T>::type::first_type>::type
264make_key(T& map)
265{
266 return typename element_type<T>::type::first_type(map.get_allocator());
267}
268
269
270// use_map_allocator_for_values
271template <typename T, typename Enable = void> struct
272use_map_allocator_for_values
273 : std::false_type {};
274
275
276template <typename T> struct
277use_map_allocator_for_values<T, typename boost::enable_if<
278 std::uses_allocator<typename element_type<T>::type::second_type, typename T::allocator_type> >::type>
279 : std::true_type {};
280
281
282// make_value
283template <typename T>
284inline
285typename boost::disable_if_c<use_map_allocator_for_values<T>::value,
286 typename element_type<T>::type::second_type>::type
287make_value(T& /*map*/)
288{
289 return typename element_type<T>::type::second_type();
290}
291
292
293template <typename T>
294inline
295typename boost::enable_if<use_map_allocator_for_values<T>, typename element_type<T>::type::second_type>::type
296make_value(T& map)
297{
298 return typename element_type<T>::type::second_type(map.get_allocator());
299}
300
301
302// mapped_at
303template <typename K, typename T, typename C, typename A>
304inline
305T& mapped_at(std::map<K, T, C, A>& map, const K& key)
306{
307 return map.insert(typename std::map<K, T, C, A>::value_type(key, make_value(map))).first->second;
308}
309
310template <typename K, typename T, typename C, typename A>
311inline
312const T& mapped_at(const std::map<K, T, C, A>& map, const K& key)
313{
314 typename std::map<K, T, C, A>::const_iterator it = map.find(key);
315
316 if (it == map.end())
317 ElementNotFoundException(key);
318
319 return it->second;
320}
321
322
323// enumerators
324template <typename T>
325class const_enumerator
326{
327public:
328 explicit const_enumerator(const T& list)
329 : it(list.begin()),
330 end(list.end())
331 {}
332
333 bool more() const
334 {
335 return it != end;
336 }
337
338 typename T::const_reference
339 next()
340 {
341 return *(it++);
342 }
343
344private:
345 typename T::const_iterator it, end;
346};
347
348template <typename A>
349class const_enumerator<std::vector<bool, A> >
350{
351public:
352 explicit const_enumerator(const std::vector<bool, A>& list)
353 : it(list.begin()),
354 end(list.end())
355 {}
356
357 bool more() const
358 {
359 return it != end;
360 }
361
362 bool next()
363 {
364 return *(it++);
365 }
366
367private:
368 typename std::vector<bool, A>::const_iterator it, end;
369};
370
371template <typename T>
372class enumerator
373{
374public:
375 explicit enumerator(T& list)
376 : it(list.begin()),
377 end(list.end())
378 {}
379
380 bool more() const
381 {
382 return it != end;
383 }
384
385 typename T::reference
386 next()
387 {
388 return *(it++);
389 }
390
391private:
392 typename T::iterator it, end;
393};
394
395
396template <typename K, typename V>
397std::map<V, K> reverse_map(const std::map<K, V>& map)
398{
399 std::map<V, K> reversed;
400
401 for (typename std::map<K, V>::const_iterator it = map.begin(); it != map.end(); ++it)
402 reversed[it->second] = it->first;
403
404 return reversed;
405}
406
407}
namespace bond
Definition apply.h:17