| /* |
| * Copyright (c) 2012 Glen Joseph Fernandes |
| * glenfe at live dot com |
| * |
| * Distributed under the Boost Software License, |
| * Version 1.0. (See accompanying file LICENSE_1_0.txt |
| * or copy at http://boost.org/LICENSE_1_0.txt) |
| */ |
| #ifndef NDNBOOST_SMART_PTR_DETAIL_ALLOCATE_ARRAY_HELPER_HPP |
| #define NDNBOOST_SMART_PTR_DETAIL_ALLOCATE_ARRAY_HELPER_HPP |
| |
| #include <ndnboost/type_traits/alignment_of.hpp> |
| |
| namespace ndnboost { |
| namespace detail { |
| template<typename A, typename T, typename Y = char> |
| class allocate_array_helper; |
| template<typename A, typename T, typename Y> |
| class allocate_array_helper<A, T[], Y> { |
| template<typename A9, typename T9, typename Y9> |
| friend class allocate_array_helper; |
| typedef typename A::template rebind<Y> ::other A2; |
| typedef typename A::template rebind<char>::other A3; |
| public: |
| typedef typename A2::value_type value_type; |
| typedef typename A2::pointer pointer; |
| typedef typename A2::const_pointer const_pointer; |
| typedef typename A2::reference reference; |
| typedef typename A2::const_reference const_reference; |
| typedef typename A2::size_type size_type; |
| typedef typename A2::difference_type difference_type; |
| template<typename U> |
| struct rebind { |
| typedef allocate_array_helper<A, T[], U> other; |
| }; |
| allocate_array_helper(const A& allocator_, std::size_t size_, T** data_) |
| : allocator(allocator_), |
| size(sizeof(T) * size_), |
| data(data_) { |
| } |
| template<class U> |
| allocate_array_helper(const allocate_array_helper<A, T[], U>& other) |
| : allocator(other.allocator), |
| size(other.size), |
| data(other.data) { |
| } |
| pointer address(reference value) const { |
| return allocator.address(value); |
| } |
| const_pointer address(const_reference value) const { |
| return allocator.address(value); |
| } |
| size_type max_size() const { |
| return allocator.max_size(); |
| } |
| pointer allocate(size_type count, const void* value = 0) { |
| std::size_t a1 = ndnboost::alignment_of<T>::value; |
| std::size_t n1 = count * sizeof(Y) + a1 - 1; |
| char* p1 = A3(allocator).allocate(n1 + size, value); |
| char* p2 = p1 + n1; |
| while (std::size_t(p2) % a1 != 0) { |
| p2--; |
| } |
| *data = reinterpret_cast<T*>(p2); |
| return reinterpret_cast<Y*>(p1); |
| } |
| void deallocate(pointer memory, size_type count) { |
| std::size_t a1 = ndnboost::alignment_of<T>::value; |
| std::size_t n1 = count * sizeof(Y) + a1 - 1; |
| char* p1 = reinterpret_cast<char*>(memory); |
| A3(allocator).deallocate(p1, n1 + size); |
| } |
| void construct(pointer memory, const Y& value) { |
| allocator.construct(memory, value); |
| } |
| void destroy(pointer memory) { |
| allocator.destroy(memory); |
| } |
| template<typename U> |
| bool operator==(const allocate_array_helper<A, T[], U>& other) const { |
| return allocator == other.allocator; |
| } |
| template<typename U> |
| bool operator!=(const allocate_array_helper<A, T[], U>& other) const { |
| return !(*this == other); |
| } |
| private: |
| A2 allocator; |
| std::size_t size; |
| T** data; |
| }; |
| template<typename A, typename T, std::size_t N, typename Y> |
| class allocate_array_helper<A, T[N], Y> { |
| template<typename A9, typename T9, typename Y9> |
| friend class allocate_array_helper; |
| typedef typename A::template rebind<Y> ::other A2; |
| typedef typename A::template rebind<char>::other A3; |
| public: |
| typedef typename A2::value_type value_type; |
| typedef typename A2::pointer pointer; |
| typedef typename A2::const_pointer const_pointer; |
| typedef typename A2::reference reference; |
| typedef typename A2::const_reference const_reference; |
| typedef typename A2::size_type size_type; |
| typedef typename A2::difference_type difference_type; |
| template<typename U> |
| struct rebind { |
| typedef allocate_array_helper<A, T[N], U> other; |
| }; |
| allocate_array_helper(const A& allocator_, T** data_) |
| : allocator(allocator_), |
| data(data_) { |
| } |
| template<class U> |
| allocate_array_helper(const allocate_array_helper<A, T[N], U>& other) |
| : allocator(other.allocator), |
| data(other.data) { |
| } |
| pointer address(reference value) const { |
| return allocator.address(value); |
| } |
| const_pointer address(const_reference value) const { |
| return allocator.address(value); |
| } |
| size_type max_size() const { |
| return allocator.max_size(); |
| } |
| pointer allocate(size_type count, const void* value = 0) { |
| std::size_t a1 = ndnboost::alignment_of<T>::value; |
| std::size_t n1 = count * sizeof(Y) + a1 - 1; |
| char* p1 = A3(allocator).allocate(n1 + N1, value); |
| char* p2 = p1 + n1; |
| while (std::size_t(p2) % a1 != 0) { |
| p2--; |
| } |
| *data = reinterpret_cast<T*>(p2); |
| return reinterpret_cast<Y*>(p1); |
| } |
| void deallocate(pointer memory, size_type count) { |
| std::size_t a1 = ndnboost::alignment_of<T>::value; |
| std::size_t n1 = count * sizeof(Y) + a1 - 1; |
| char* p1 = reinterpret_cast<char*>(memory); |
| A3(allocator).deallocate(p1, n1 + N1); |
| } |
| void construct(pointer memory, const Y& value) { |
| allocator.construct(memory, value); |
| } |
| void destroy(pointer memory) { |
| allocator.destroy(memory); |
| } |
| template<typename U> |
| bool operator==(const allocate_array_helper<A, T[N], U>& other) const { |
| return allocator == other.allocator; |
| } |
| template<typename U> |
| bool operator!=(const allocate_array_helper<A, T[N], U>& other) const { |
| return !(*this == other); |
| } |
| private: |
| enum { |
| N1 = N * sizeof(T) |
| }; |
| A2 allocator; |
| T** data; |
| }; |
| } |
| } |
| |
| #endif |