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
164
165// resize_list
166template <typename T>
167inline
168typename boost::disable_if<use_container_allocator_for_elements<T> >::type
169resize_list(T& list, uint32_t size)
170{
171 list.resize(size, make_element(list));
172}
173
174
175template <typename T>
176inline
177typename boost::enable_if<use_container_allocator_for_elements<T> >::type
178resize_list(T& list, uint32_t size)
179{
180 list.clear();
181 list.resize(size, make_element(list));
182}
183
184
185// modify_element
186template <typename A, typename F>
187inline
188void modify_element(std::vector<bool, A>&,
189 typename std::vector<bool, A>::reference element,
190 F deserialize)
191{
192 bool value;
193
194 deserialize(value);
195 element = value;
196}
197
198
199// clear_set
200template <typename T, typename C, typename A>
201inline
202void clear_set(std::set<T, C, A>& set)
203{
204 set.clear();
205}
206
207
208// set_insert
209template <typename T, typename C, typename A>
210inline
211void set_insert(std::set<T, C, A>& set, const T& item)
212{
213 set.insert(item);
214}
215
216
217// clear_map
218template <typename K, typename T, typename C, typename A>
219inline
220void clear_map(std::map<K, T, C, A>& map)
221{
222 map.clear();
223}
224
225
226// use_map_allocator_for_keys
227template <typename T, typename Enable = void> struct
228use_map_allocator_for_keys
229 : std::false_type {};
230
231
232template <typename T> struct
233use_map_allocator_for_keys<T, typename boost::enable_if<
234 std::uses_allocator<typename element_type<T>::type::first_type, typename T::allocator_type> >::type>
235 : std::true_type {};
236
237
238// make_key
239template <typename T>
240inline
241typename boost::disable_if<use_map_allocator_for_keys<T>, typename element_type<T>::type::first_type>::type
242make_key(T& /*map*/)
243{
244 return typename element_type<T>::type::first_type();
245}
246
247
248template <typename T>
249inline
250typename boost::enable_if<use_map_allocator_for_keys<T>, typename element_type<T>::type::first_type>::type
251make_key(T& map)
252{
253 return typename element_type<T>::type::first_type(map.get_allocator());
254}
255
256
257// use_map_allocator_for_values
258template <typename T, typename Enable = void> struct
259use_map_allocator_for_values
260 : std::false_type {};
261
262
263template <typename T> struct
264use_map_allocator_for_values<T, typename boost::enable_if<
265 std::uses_allocator<typename element_type<T>::type::second_type, typename T::allocator_type> >::type>
266 : std::true_type {};
267
268
269// make_value
270template <typename T>
271inline
272typename boost::disable_if_c<use_map_allocator_for_values<T>::value,
273 typename element_type<T>::type::second_type>::type
274make_value(T& /*map*/)
275{
276 return typename element_type<T>::type::second_type();
277}
278
279
280template <typename T>
281inline
282typename boost::enable_if<use_map_allocator_for_values<T>, typename element_type<T>::type::second_type>::type
283make_value(T& map)
284{
285 return typename element_type<T>::type::second_type(map.get_allocator());
286}
287
288
289// mapped_at
290template <typename K, typename T, typename C, typename A>
291inline
292T& mapped_at(std::map<K, T, C, A>& map, const K& key)
293{
294 return map.insert(typename std::map<K, T, C, A>::value_type(key, make_value(map))).first->second;
295}
296
297template <typename K, typename T, typename C, typename A>
298inline
299const T& mapped_at(const std::map<K, T, C, A>& map, const K& key)
300{
301 typename std::map<K, T, C, A>::const_iterator it = map.find(key);
302
303 if (it == map.end())
304 ElementNotFoundException(key);
305
306 return it->second;
307}
308
309
310// enumerators
311template <typename T>
312class const_enumerator
313{
314public:
315 explicit const_enumerator(const T& list)
316 : it(list.begin()),
317 end(list.end())
318 {}
319
320 bool more() const
321 {
322 return it != end;
323 }
324
325 typename T::const_reference
326 next()
327 {
328 return *(it++);
329 }
330
331private:
332 typename T::const_iterator it, end;
333};
334
335template <typename A>
336class const_enumerator<std::vector<bool, A> >
337{
338public:
339 explicit const_enumerator(const std::vector<bool, A>& list)
340 : it(list.begin()),
341 end(list.end())
342 {}
343
344 bool more() const
345 {
346 return it != end;
347 }
348
349 bool next()
350 {
351 return *(it++);
352 }
353
354private:
355 typename std::vector<bool, A>::const_iterator it, end;
356};
357
358template <typename T>
359class enumerator
360{
361public:
362 explicit enumerator(T& list)
363 : it(list.begin()),
364 end(list.end())
365 {}
366
367 bool more() const
368 {
369 return it != end;
370 }
371
372 typename T::reference
373 next()
374 {
375 return *(it++);
376 }
377
378private:
379 typename T::iterator it, end;
380};
381
382
383template <typename K, typename V>
384std::map<V, K> reverse_map(const std::map<K, V>& map)
385{
386 std::map<V, K> reversed;
387
388 for (typename std::map<K, V>::const_iterator it = map.begin(); it != map.end(); ++it)
389 reversed[it->second] = it->first;
390
391 return reversed;
392}
393
394}
namespace bond
Definition: apply.h:17
STL namespace.