/* * Copyright (c) 2017 Jaroslav Jindrak * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef LIBCPP_MEMORY #define LIBCPP_MEMORY #include #include namespace std { /** * 20.7.3, pointer traits: */ template struct pointer_traits { using pointer = Ptr; // TODO: element type, difference type // TODO: this is conditional, see standard template using rebind = typename Ptr::template rebind; }; /** * 20.7.8, allocator traits: */ namespace aux { /** * The standard mandates that we reuse type from allocators * *if* they are defined or that we use something different. * These structures help us alternate between those by * using SFINAE. * TODO: Create tests for these! */ template struct get_pointer: aux::type_is { /* DUMMY BODY */ }; template struct get_pointer> : aux::type_is { /* DUMMY BODY */ }; template struct get_const_pointer : aux::type_is::template rebind> { /* DUMMY BODY */ }; template struct get_const_pointer> : aux::type_is { /* DUMMY BODY */ }; template struct get_void_pointer : aux::type_is::template rebind> { /* DUMMY BODY */ }; template struct get_void_pointer> : aux::type_is { /* DUMMY BODY */ }; template struct get_const_void_pointer : aux::type_is::template rebind> { /* DUMMY BODY */ }; template struct get_const_void_pointer> : aux::type_is { /* DUMMY BODY */ }; template struct get_difference_type : aux::type_is::difference_type> { /* DUMMY BODY */ }; template struct get_difference_type> : aux::type_is { /* DUMMY BODY */ }; template struct get_size_type: aux::type_is> { /* DUMMY BODY */ }; template struct get_size_type> : aux::type_is { /* DUMMY BODY */ }; template struct get_copy_propagate: aux::type_is { /* DUMMY BODY */ }; template struct get_copy_propagate> : aux::type_is { /* DUMMY BODY */ }; template struct get_move_propagate: aux::type_is { /* DUMMY BODY */ }; template struct get_move_propagate> : aux::type_is { /* DUMMY BODY */ }; template struct get_swap_propagate: aux::type_is { /* DUMMY BODY */ }; template struct get_swap_propagate> : aux::type_is { /* DUMMY BODY */ }; template struct get_always_equal: aux::type_is::type> { /* DUMMY BODY */ }; template struct get_always_equal> : aux::type_is { /* DUMMY BODY */ }; template struct get_rebind_other { /* DUMMY BODY */ }; template struct get_rebind_other::other>> : aux::type_is::other> { /* DUMMY BODY */ }; /* TODO: How am I suppose to do this?! template class Alloc> struct get_rebind_args; */ template struct get_rebind_args: aux::type_is::type> { /* DUMMY BODY */ }; } template struct allocator_traits { using allocator_type = Alloc; using value_type = typename Alloc::value_type; using pointer = typename aux::get_pointer::type; using const_pointer = typename aux::get_const_pointer::type; // TODO: fix void pointer typedefs /* using void_pointer = typename aux::get_void_pointer::type; */ /* using const_void_pointer = typename aux::get_const_void_pointer::type; */ using void_pointer = void*; using const_void_pointer = const void*; using difference_type = typename aux::get_difference_type::type; using size_type = typename aux::get_size_type::type; using propagate_on_container_copy_assignment = typename aux::get_copy_propagate::type; using propagate_on_container_move_assignment = typename aux::get_move_propagate::type; using propagate_on_container_swap = typename aux::get_swap_propagate::type; using is_always_equal = typename aux::get_always_equal::type; template using rebind_alloc = typename aux::get_rebind_args; template using rebind_traits = allocator_traits>; static pointer allocate(Alloc& alloc, size_type n) { return alloc.allocate(n); } static pointer allocate(Alloc& alloc, size_type n, const_void_pointer hint) { // TODO: this when it's well formed, otherwise alloc.allocate(n) return alloc.allocate(n, hint); } static void deallocate(Alloc& alloc, pointer ptr, size_type n) { alloc.deallocate(ptr, n); } template static void construct(Alloc& alloc, T* ptr, Args&&... args) { // TODO: implement } template static void destroy(Alloc& alloc, T* ptr) { // TODO: implement } static size_type max_size(const Alloc& alloc) noexcept { // TODO: implement return 0; } static Alloc select_on_container_copy_construction(const Alloc& alloc) { // TODO: implement return Alloc{}; } }; /** * 20.7.9, the default allocator */ template class allocator; template<> class allocator { public: using pointer = void*; using const_pointer = const void*; using value_type = void; template struct rebind { using other = allocator; }; }; template class allocator { public: using size_type = size_t; using difference_type = ptrdiff_t; using pointer = T*; using const_pointer = const T*; using reference = T&; using const_reference = const T&; using value_type = T; template struct rebind { using other = allocator; }; using propagate_on_container_move_assignment = true_type; using is_always_equal = true_type; allocator() noexcept = default; allocator(const allocator&) noexcept = default; template allocator(const allocator&) noexcept { // TODO: implement } ~allocator() = default; pointer address(reference x) const noexcept { // TODO: see std::addressof return &x; } const_pointer address(const_reference x) const noexcept { // TODO: see std::addressof return &x; } pointer allocate(size_type n, allocator::const_pointer hint = 0) { /** * Note: The usage of hint is unspecified. * TODO: Check HelenOS hint allocation capabilities. * TODO: assert that n < max_size() */ return static_cast(::operator new(n * sizeof(value_type))); } void deallocate(pointer ptr, size_type n) { ::operator delete(ptr, n); } size_type max_size() const noexcept { // TODO: implement, max argument to allocate return 0xFFFFFFFF; } template void construct(U* ptr, Args&&... args) { ::new((void*)ptr) U(forward(args)...); } template void destroy(U* ptr) { ptr->~U(); } }; template bool operator==(const allocator&, const allocator&) noexcept { return true; } template bool operator!=(const allocator&, const allocator&) noexcept { return false; } /** * 20.7.10, raw storage iterator: */ // TODO: implement /** * 20.7.11, temporary buffers: */ // TODO: implement /** * 20.7.12, specialized algorithms: */ template T* addressof(T& x) noexcept { // TODO: This should actually work even with overloaded operator&. return &x; } template ForwardIterator unitialized_copy( InputIterator first, InputIterator last, ForwardIterator result ) { for (; first != last; ++first, ++result) ::new (static_cast(&*result)) typename iterator_traits::value_type(*first); return result; } template ForwardIterator unitialized_copy_n( InputIterator first, Size n, ForwardIterator result ) { for (; n > 0; ++first, --n, ++result) ::new (static_cast(&*result)) typename iterator_traits::value_type(*first); return result; } template void unitialized_fill( ForwardIterator first, ForwardIterator last, const T& x ) { for (; first != last; ++first) ::new (static_cast(&*first)) typename iterator_traits::value_type(x); } template ForwardIterator unitialized_fill_n( ForwardIterator first, Size n, const T& x ) { for (; n > 0; ++first, --n) ::new (static_cast(&*first)) typename iterator_traits::value_type(x); return first; } } #endif