source: mainline/uspace/lib/cpp/include/impl/memory.hpp@ 7b1906e

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 7b1906e was 35584b19, checked in by Dzejrou <dzejrou@…>, 7 years ago

cpp: added mostly functioning version of std::vector, but inserts currently reallocate everytime

  • Property mode set to 100644
File size: 13.4 KB
Line 
1/*
2 * Copyright (c) 2017 Jaroslav Jindrak
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef LIBCPP_MEMORY
30#define LIBCPP_MEMORY
31
32#include <internal/aux.hpp>
33#include <type_traits>
34
35namespace std
36{
37 /**
38 * 20.7.3, pointer traits:
39 */
40
41 template<class Ptr>
42 struct pointer_traits
43 {
44 using pointer = Ptr;
45 // TODO: element type, difference type
46
47 // TODO: this is conditional, see standard
48 template<class U>
49 using rebind = typename Ptr::template rebind<U>;
50 };
51
52 /**
53 * 20.7.8, allocator traits:
54 */
55
56 namespace aux
57 {
58 /**
59 * The standard mandates that we reuse type from allocators
60 * *if* they are defined or that we use something different.
61 * These structures help us alternate between those by
62 * using SFINAE.
63 * TODO: Create tests for these!
64 */
65
66 template<class T, class = void>
67 struct get_pointer: aux::type_is<typename T::value_type*>
68 { /* DUMMY BODY */ };
69
70 template<class T>
71 struct get_pointer<T, void_t<typename T::pointer>>
72 : aux::type_is<typename T::pointer>
73 { /* DUMMY BODY */ };
74
75 template<class T, class Ptr, class = void>
76 struct get_const_pointer
77 : aux::type_is<typename pointer_traits<Ptr>::template rebind<const typename T::value_type>>
78 { /* DUMMY BODY */ };
79
80 template<class T, class Ptr>
81 struct get_const_pointer<T, Ptr, void_t<typename T::const_pointer>>
82 : aux::type_is<typename T::const_pointer>
83 { /* DUMMY BODY */ };
84
85 template<class T, class Ptr, class = void>
86 struct get_void_pointer
87 : aux::type_is<typename pointer_traits<Ptr>::template rebind<void>>
88 { /* DUMMY BODY */ };
89
90 template<class T, class Ptr>
91 struct get_void_pointer<T, Ptr, void_t<typename T::void_pointer>>
92 : aux::type_is<typename T::void_pointer>
93 { /* DUMMY BODY */ };
94
95 template<class T, class Ptr, class = void>
96 struct get_const_void_pointer
97 : aux::type_is<typename pointer_traits<Ptr>::template rebind<const void>>
98 { /* DUMMY BODY */ };
99
100 template<class T, class Ptr>
101 struct get_const_void_pointer<T, Ptr, void_t<typename T::const_void_pointer>>
102 : aux::type_is<typename T::const_void_pointer>
103 { /* DUMMY BODY */ };
104
105 template<class T, class Ptr, class = void>
106 struct get_difference_type
107 : aux::type_is<typename pointer_traits<Ptr>::difference_type>
108 { /* DUMMY BODY */ };
109
110 template<class T, class Ptr>
111 struct get_difference_type<T, Ptr, void_t<typename T::difference_type>>
112 : aux::type_is<typename T::difference_type>
113 { /* DUMMY BODY */ };
114
115 template<class T, class Difference, class = void>
116 struct get_size_type: aux::type_is<make_unsigned_t<Difference>>
117 { /* DUMMY BODY */ };
118
119 template<class T, class Difference>
120 struct get_size_type<T, Difference, void_t<typename T::size_type>>
121 : aux::type_is<typename T::size_type>
122 { /* DUMMY BODY */ };
123
124 template<class T, class = void>
125 struct get_copy_propagate: aux::type_is<false_type>
126 { /* DUMMY BODY */ };
127
128 template<class T>
129 struct get_copy_propagate<T, void_t<typename T::propagate_on_container_copy_assignment>>
130 : aux::type_is<typename T::propagate_on_container_copy_assignment>
131 { /* DUMMY BODY */ };
132
133 template<class T, class = void>
134 struct get_move_propagate: aux::type_is<false_type>
135 { /* DUMMY BODY */ };
136
137 template<class T>
138 struct get_move_propagate<T, void_t<typename T::propagate_on_container_move_assignment>>
139 : aux::type_is<typename T::propagate_on_container_move_assignment>
140 { /* DUMMY BODY */ };
141
142 template<class T, class = void>
143 struct get_swap_propagate: aux::type_is<false_type>
144 { /* DUMMY BODY */ };
145
146 template<class T>
147 struct get_swap_propagate<T, void_t<typename T::propagate_on_container_swap>>
148 : aux::type_is<typename T::propagate_on_container_swap>
149 { /* DUMMY BODY */ };
150
151 template<class T, class = void>
152 struct get_always_equal: aux::type_is<typename is_empty<T>::type>
153 { /* DUMMY BODY */ };
154
155 template<class T>
156 struct get_always_equal<T, void_t<typename T::is_always_equal>>
157 : aux::type_is<typename T::is_always_equal>
158 { /* DUMMY BODY */ };
159
160 template<class Alloc, class T, class = void>
161 struct get_rebind_other
162 { /* DUMMY BODY */ };
163
164 template<class Alloc, class T>
165 struct get_rebind_other<Alloc, T, void_t<typename Alloc::template rebind<T>::other>>
166 : aux::type_is<typename Alloc::template rebind<T>::other>
167 { /* DUMMY BODY */ };
168
169 /* TODO: How am I suppose to do this?!
170 template<template<class T, class... Args> class Alloc>
171 struct get_rebind_args;
172 */
173
174 template<class Alloc, class T>
175 struct get_rebind_args: aux::type_is<typename get_rebind_other<Alloc, T>::type>
176 { /* DUMMY BODY */ };
177 }
178
179 template<class Alloc>
180 struct allocator_traits
181 {
182 using allocator_type = Alloc;
183
184 using value_type = typename Alloc::value_type;
185 using pointer = typename aux::get_pointer<Alloc>::type;
186 using const_pointer = typename aux::get_const_pointer<Alloc, pointer>::type;
187 // TODO: fix void pointer typedefs
188 /* using void_pointer = typename aux::get_void_pointer<Alloc, pointer>::type; */
189 /* using const_void_pointer = typename aux::get_const_void_pointer<Alloc, pointer>::type; */
190 using void_pointer = void*;
191 using const_void_pointer = const void*;
192 using difference_type = typename aux::get_difference_type<Alloc, pointer>::type;
193 using size_type = typename aux::get_size_type<Alloc, difference_type>::type;
194
195 using propagate_on_container_copy_assignment = typename aux::get_copy_propagate<Alloc>::type;
196 using propagate_on_container_move_assignment = typename aux::get_move_propagate<Alloc>::type;
197 using propagate_on_container_swap = typename aux::get_swap_propagate<Alloc>::type;
198 using is_always_equal = typename aux::get_always_equal<Alloc>::type;
199
200 template<class T>
201 using rebind_alloc = typename aux::get_rebind_args<Alloc, T>;
202
203 template<class T>
204 using rebind_traits = allocator_traits<rebind_alloc<T>>;
205
206 static pointer allocate(Alloc& alloc, size_type n)
207 {
208 return alloc.allocate(n);
209 }
210
211 static pointer allocate(Alloc& alloc, size_type n, const_void_pointer hint)
212 { // TODO: this when it's well formed, otherwise alloc.allocate(n)
213 return alloc.allocate(n, hint);
214 }
215
216 static void deallocate(Alloc& alloc, pointer ptr, size_type n)
217 {
218 alloc.deallocate(ptr, n);
219 }
220
221 template<class T, class... Args>
222 static void construct(Alloc& alloc, T* ptr, Args&&... args)
223 {
224 // TODO: implement
225 }
226
227 template<class T>
228 static void destroy(Alloc& alloc, T* ptr)
229 {
230 // TODO: implement
231 }
232
233 static size_type max_size(const Alloc& alloc) noexcept
234 {
235 // TODO: implement
236 return 0;
237 }
238
239 static Alloc select_on_container_copy_construction(const Alloc& alloc)
240 {
241 // TODO: implement
242 return Alloc{};
243 }
244 };
245
246 /**
247 * 20.7.9, the default allocator
248 */
249
250 template<class T>
251 class allocator;
252
253 template<>
254 class allocator<void>
255 {
256 public:
257 using pointer = void*;
258 using const_pointer = const void*;
259 using value_type = void;
260
261 template<class U>
262 struct rebind
263 {
264 using other = allocator<U>;
265 };
266 };
267
268 template<class T>
269 class allocator
270 {
271 public:
272 using size_type = size_t;
273 using difference_type = ptrdiff_t;
274 using pointer = T*;
275 using const_pointer = const T*;
276 using reference = T&;
277 using const_reference = const T&;
278 using value_type = T;
279
280 template<class U>
281 struct rebind
282 {
283 using other = allocator<U>;
284 };
285
286 using propagate_on_container_move_assignment = true_type;
287 using is_always_equal = true_type;
288
289 allocator() noexcept = default;
290
291 allocator(const allocator&) noexcept = default;
292
293 template<class U>
294 allocator(const allocator<U>&) noexcept
295 {
296 // TODO: implement
297 }
298
299 ~allocator() = default;
300
301 pointer address(reference x) const noexcept
302 { // TODO: see std::addressof
303 return &x;
304 }
305
306 const_pointer address(const_reference x) const noexcept
307 { // TODO: see std::addressof
308 return &x;
309 }
310
311 pointer allocate(size_type n, allocator<void>::const_pointer hint = 0)
312 {
313 /**
314 * Note: The usage of hint is unspecified.
315 * TODO: Check HelenOS hint allocation capabilities.
316 * TODO: assert that n < max_size()
317 */
318 return static_cast<pointer>(::operator new(n * sizeof(value_type)));
319 }
320
321 void deallocate(pointer ptr, size_type n)
322 {
323 ::operator delete(ptr, n);
324 }
325
326 size_type max_size() const noexcept
327 { // TODO: implement, max argument to allocate
328 return 0xFFFFFFFF;
329 }
330
331 template<class U, class... Args>
332 void construct(U* ptr, Args&&... args)
333 {
334 ::new((void*)ptr) U(forward<Args>(args)...);
335 }
336
337 template<class U>
338 void destroy(U* ptr)
339 {
340 ptr->~U();
341 }
342 };
343
344 template<class T1, class T2>
345 bool operator==(const allocator<T1>&, const allocator<T2>&) noexcept
346 {
347 return true;
348 }
349
350 template<class T1, class T2>
351 bool operator!=(const allocator<T1>&, const allocator<T2>&) noexcept
352 {
353 return false;
354 }
355
356 /**
357 * 20.7.10, raw storage iterator:
358 */
359
360 // TODO: implement
361
362 /**
363 * 20.7.11, temporary buffers:
364 */
365
366 // TODO: implement
367
368 /**
369 * 20.7.12, specialized algorithms:
370 */
371
372 template<class T>
373 T* addressof(T& x) noexcept
374 { // TODO: This should actually work even with overloaded operator&.
375 return &x;
376 }
377
378 template<class InputIterator, class ForwardIterator>
379 ForwardIterator unitialized_copy(
380 InputIterator first, InputIterator last,
381 ForwardIterator result
382 )
383 {
384 for (; first != last; ++first, ++result)
385 ::new (static_cast<void*>(&*result)) typename iterator_traits<ForwardIterator>::value_type(*first);
386
387 return result;
388 }
389
390 template<class InputIterator, class Size, class ForwardIterator>
391 ForwardIterator unitialized_copy_n(
392 InputIterator first, Size n, ForwardIterator result
393 )
394 {
395 for (; n > 0; ++first, --n, ++result)
396 ::new (static_cast<void*>(&*result)) typename iterator_traits<ForwardIterator>::value_type(*first);
397
398 return result;
399 }
400
401 template<class ForwardIterator, class T>
402 void unitialized_fill(
403 ForwardIterator first, ForwardIterator last, const T& x
404 )
405 {
406 for (; first != last; ++first)
407 ::new (static_cast<void*>(&*first)) typename iterator_traits<ForwardIterator>::value_type(x);
408 }
409
410 template<class ForwardIterator, class Size, class T>
411 ForwardIterator unitialized_fill_n(
412 ForwardIterator first, Size n, const T& x
413 )
414 {
415 for (; n > 0; ++first, --n)
416 ::new (static_cast<void*>(&*first)) typename iterator_traits<ForwardIterator>::value_type(x);
417
418 return first;
419 }
420}
421
422#endif
Note: See TracBrowser for help on using the repository browser.