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

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

cpp: fixed some bugs found by the string tests

  • 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 <utility>
34#include <type_traits>
35
36namespace std
37{
38 /**
39 * 20.7.3, pointer traits:
40 */
41
42 template<class Ptr>
43 struct pointer_traits
44 {
45 using pointer = Ptr;
46 // TODO: element type, difference type
47
48 // TODO: this is conditional, see standard
49 template<class U>
50 using rebind = typename Ptr::template rebind<U>;
51 };
52
53 /**
54 * 20.7.8, allocator traits:
55 */
56
57 namespace aux
58 {
59 /**
60 * The standard mandates that we reuse type from allocators
61 * *if* they are defined or that we use something different.
62 * These structures help us alternate between those by
63 * using SFINAE.
64 * TODO: Create tests for these!
65 */
66
67 template<class T, class = void>
68 struct get_pointer: aux::type_is<typename T::value_type*>
69 { /* DUMMY BODY */ };
70
71 template<class T>
72 struct get_pointer<T, void_t<typename T::pointer>>
73 : aux::type_is<typename T::pointer>
74 { /* DUMMY BODY */ };
75
76 template<class T, class Ptr, class = void>
77 struct get_const_pointer
78 : aux::type_is<typename pointer_traits<Ptr>::template rebind<const typename T::value_type>>
79 { /* DUMMY BODY */ };
80
81 template<class T, class Ptr>
82 struct get_const_pointer<T, Ptr, void_t<typename T::const_pointer>>
83 : aux::type_is<typename T::const_pointer>
84 { /* DUMMY BODY */ };
85
86 template<class T, class Ptr, class = void>
87 struct get_void_pointer
88 : aux::type_is<typename pointer_traits<Ptr>::template rebind<void>>
89 { /* DUMMY BODY */ };
90
91 template<class T, class Ptr>
92 struct get_void_pointer<T, Ptr, void_t<typename T::void_pointer>>
93 : aux::type_is<typename T::void_pointer>
94 { /* DUMMY BODY */ };
95
96 template<class T, class Ptr, class = void>
97 struct get_const_void_pointer
98 : aux::type_is<typename pointer_traits<Ptr>::template rebind<const void>>
99 { /* DUMMY BODY */ };
100
101 template<class T, class Ptr>
102 struct get_const_void_pointer<T, Ptr, void_t<typename T::const_void_pointer>>
103 : aux::type_is<typename T::const_void_pointer>
104 { /* DUMMY BODY */ };
105
106 template<class T, class Ptr, class = void>
107 struct get_difference_type
108 : aux::type_is<typename pointer_traits<Ptr>::difference_type>
109 { /* DUMMY BODY */ };
110
111 template<class T, class Ptr>
112 struct get_difference_type<T, Ptr, void_t<typename T::difference_type>>
113 : aux::type_is<typename T::difference_type>
114 { /* DUMMY BODY */ };
115
116 template<class T, class Difference, class = void>
117 struct get_size_type: aux::type_is<make_unsigned_t<Difference>>
118 { /* DUMMY BODY */ };
119
120 template<class T, class Difference>
121 struct get_size_type<T, Difference, void_t<typename T::size_type>>
122 : aux::type_is<typename T::size_type>
123 { /* DUMMY BODY */ };
124
125 template<class T, class = void>
126 struct get_copy_propagate: aux::type_is<false_type>
127 { /* DUMMY BODY */ };
128
129 template<class T>
130 struct get_copy_propagate<T, void_t<typename T::propagate_on_container_copy_assignment>>
131 : aux::type_is<typename T::propagate_on_container_copy_assignment>
132 { /* DUMMY BODY */ };
133
134 template<class T, class = void>
135 struct get_move_propagate: aux::type_is<false_type>
136 { /* DUMMY BODY */ };
137
138 template<class T>
139 struct get_move_propagate<T, void_t<typename T::propagate_on_container_move_assignment>>
140 : aux::type_is<typename T::propagate_on_container_move_assignment>
141 { /* DUMMY BODY */ };
142
143 template<class T, class = void>
144 struct get_swap_propagate: aux::type_is<false_type>
145 { /* DUMMY BODY */ };
146
147 template<class T>
148 struct get_swap_propagate<T, void_t<typename T::propagate_on_container_swap>>
149 : aux::type_is<typename T::propagate_on_container_swap>
150 { /* DUMMY BODY */ };
151
152 template<class T, class = void>
153 struct get_always_equal: aux::type_is<typename is_empty<T>::type>
154 { /* DUMMY BODY */ };
155
156 template<class T>
157 struct get_always_equal<T, void_t<typename T::is_always_equal>>
158 : aux::type_is<typename T::is_always_equal>
159 { /* DUMMY BODY */ };
160
161 template<class Alloc, class T, class = void>
162 struct get_rebind_other
163 { /* DUMMY BODY */ };
164
165 template<class Alloc, class T>
166 struct get_rebind_other<Alloc, T, void_t<typename Alloc::template rebind<T>::other>>
167 : aux::type_is<typename Alloc::template rebind<T>::other>
168 { /* DUMMY BODY */ };
169
170 /* TODO: How am I suppose to do this?!
171 template<template<class T, class... Args> class Alloc>
172 struct get_rebind_args;
173 */
174
175 template<class Alloc, class T>
176 struct get_rebind_args: aux::type_is<typename get_rebind_other<Alloc, T>::type>
177 { /* DUMMY BODY */ };
178 }
179
180 template<class Alloc>
181 struct allocator_traits
182 {
183 using allocator_type = Alloc;
184
185 using value_type = typename Alloc::value_type;
186 using pointer = typename aux::get_pointer<Alloc>::type;
187 using const_pointer = typename aux::get_const_pointer<Alloc, pointer>::type;
188 // TODO: fix void pointer typedefs
189 /* using void_pointer = typename aux::get_void_pointer<Alloc, pointer>::type; */
190 /* using const_void_pointer = typename aux::get_const_void_pointer<Alloc, pointer>::type; */
191 using void_pointer = void*;
192 using const_void_pointer = const void*;
193 using difference_type = typename aux::get_difference_type<Alloc, pointer>::type;
194 using size_type = typename aux::get_size_type<Alloc, difference_type>::type;
195
196 using propagate_on_container_copy_assignment = typename aux::get_copy_propagate<Alloc>::type;
197 using propagate_on_container_move_assignment = typename aux::get_move_propagate<Alloc>::type;
198 using propagate_on_container_swap = typename aux::get_swap_propagate<Alloc>::type;
199 using is_always_equal = typename aux::get_always_equal<Alloc>::type;
200
201 template<class T>
202 using rebind_alloc = typename aux::get_rebind_args<Alloc, T>;
203
204 template<class T>
205 using rebind_traits = allocator_traits<rebind_alloc<T>>;
206
207 static pointer allocate(Alloc& alloc, size_type n)
208 {
209 return alloc.allocate(n);
210 }
211
212 static pointer allocate(Alloc& alloc, size_type n, const_void_pointer hint)
213 { // TODO: this when it's well formed, otherwise alloc.allocate(n)
214 return alloc.allocate(n, hint);
215 }
216
217 static void deallocate(Alloc& alloc, pointer ptr, size_type n)
218 {
219 alloc.deallocate(ptr, n);
220 }
221
222 template<class T, class... Args>
223 static void construct(Alloc& alloc, T* ptr, Args&&... args)
224 {
225 // TODO: implement
226 }
227
228 template<class T>
229 static void destroy(Alloc& alloc, T* ptr)
230 {
231 // TODO: implement
232 }
233
234 static size_type max_size(const Alloc& alloc) noexcept
235 {
236 // TODO: implement
237 return 0;
238 }
239
240 static Alloc select_on_container_copy_construction(const Alloc& alloc)
241 {
242 // TODO: implement
243 return Alloc{};
244 }
245 };
246
247 /**
248 * 20.7.9, the default allocator
249 */
250
251 template<class T>
252 class allocator;
253
254 template<>
255 class allocator<void>
256 {
257 public:
258 using pointer = void*;
259 using const_pointer = const void*;
260 using value_type = void;
261
262 template<class U>
263 struct rebind
264 {
265 using other = allocator<U>;
266 };
267 };
268
269 template<class T>
270 class allocator
271 {
272 public:
273 using size_type = size_t;
274 using difference_type = ptrdiff_t;
275 using pointer = T*;
276 using const_pointer = const T*;
277 using reference = T&;
278 using const_reference = const T&;
279 using value_type = T;
280
281 template<class U>
282 struct rebind
283 {
284 using other = allocator<U>;
285 };
286
287 using propagate_on_container_move_assignment = true_type;
288 using is_always_equal = true_type;
289
290 allocator() noexcept = default;
291
292 allocator(const allocator&) noexcept = default;
293
294 template<class U>
295 allocator(const allocator<U>&) noexcept
296 {
297 // TODO: implement
298 }
299
300 ~allocator() = default;
301
302 pointer address(reference x) const noexcept
303 { // TODO: see std::addressof
304 return &x;
305 }
306
307 const_pointer address(const_reference x) const noexcept
308 { // TODO: see std::addressof
309 return &x;
310 }
311
312 pointer allocate(size_type n, allocator<void>::const_pointer hint = 0)
313 {
314 /**
315 * Note: The usage of hint is unspecified.
316 * TODO: Check HelenOS hint allocation capabilities.
317 * TODO: assert that n < max_size()
318 */
319 return static_cast<pointer>(::operator new(n * sizeof(value_type)));
320 }
321
322 void deallocate(pointer ptr, size_type n)
323 {
324 ::operator delete(ptr, n);
325 }
326
327 size_type max_size() const noexcept
328 { // TODO: implement, max argument to allocate
329 return 0xFFFFFFFF;
330 }
331
332 template<class U, class... Args>
333 void construct(U* ptr, Args&&... args)
334 {
335 ::new((void*)ptr) U(forward<Args>(args)...);
336 }
337
338 template<class U>
339 void destroy(U* ptr)
340 {
341 ptr->~U();
342 }
343 };
344
345 template<class T1, class T2>
346 bool operator==(const allocator<T1>&, const allocator<T2>&) noexcept
347 {
348 return true;
349 }
350
351 template<class T1, class T2>
352 bool operator!=(const allocator<T1>&, const allocator<T2>&) noexcept
353 {
354 return false;
355 }
356
357 /**
358 * 20.7.10, raw storage iterator:
359 */
360
361 // TODO: implement
362
363 /**
364 * 20.7.11, temporary buffers:
365 */
366
367 // TODO: implement
368
369 /**
370 * 20.7.12, specialized algorithms:
371 */
372
373 template<class T>
374 T* addressof(T& x) noexcept
375 { // TODO: This should actually work even with overloaded operator&.
376 return &x;
377 }
378
379 template<class InputIterator, class ForwardIterator>
380 ForwardIterator unitialized_copy(
381 InputIterator first, InputIterator last,
382 ForwardIterator result
383 )
384 {
385 for (; first != last; ++first, ++result)
386 ::new (static_cast<void*>(&*result)) typename iterator_traits<ForwardIterator>::value_type(*first);
387
388 return result;
389 }
390
391 template<class InputIterator, class Size, class ForwardIterator>
392 ForwardIterator unitialized_copy_n(
393 InputIterator first, Size n, ForwardIterator result
394 )
395 {
396 for (; n > 0; ++first, --n, ++result)
397 ::new (static_cast<void*>(&*result)) typename iterator_traits<ForwardIterator>::value_type(*first);
398
399 return result;
400 }
401
402 template<class ForwardIterator, class T>
403 void unitialized_fill(
404 ForwardIterator first, ForwardIterator last, const T& x
405 )
406 {
407 for (; first != last; ++first)
408 ::new (static_cast<void*>(&*first)) typename iterator_traits<ForwardIterator>::value_type(x);
409 }
410
411 template<class ForwardIterator, class Size, class T>
412 ForwardIterator unitialized_fill_n(
413 ForwardIterator first, Size n, const T& x
414 )
415 {
416 for (; n > 0; ++first, --n)
417 ::new (static_cast<void*>(&*first)) typename iterator_traits<ForwardIterator>::value_type(x);
418
419 return first;
420 }
421}
422
423#endif
Note: See TracBrowser for help on using the repository browser.