blob: 5a59c093798939665f532e06ffdc22a11ca731c4 [file] [log] [blame]
Jeff Thompsonf7d49942013-08-01 16:47:40 -07001/*
2 * Copyright (c) 2012 Glen Joseph Fernandes
3 * glenfe at live dot com
4 *
5 * Distributed under the Boost Software License,
6 * Version 1.0. (See accompanying file LICENSE_1_0.txt
7 * or copy at http://boost.org/LICENSE_1_0.txt)
8 */
9#ifndef BOOST_SMART_PTR_DETAIL_ALLOCATE_ARRAY_HELPER_HPP
10#define BOOST_SMART_PTR_DETAIL_ALLOCATE_ARRAY_HELPER_HPP
11
12#include <boost/type_traits/alignment_of.hpp>
13
14namespace ndnboost {
15 namespace detail {
16 template<typename A, typename T, typename Y = char>
17 class allocate_array_helper;
18 template<typename A, typename T, typename Y>
19 class allocate_array_helper<A, T[], Y> {
20 template<typename A9, typename T9, typename Y9>
21 friend class allocate_array_helper;
22 typedef typename A::template rebind<Y> ::other A2;
23 typedef typename A::template rebind<char>::other A3;
24 public:
25 typedef typename A2::value_type value_type;
26 typedef typename A2::pointer pointer;
27 typedef typename A2::const_pointer const_pointer;
28 typedef typename A2::reference reference;
29 typedef typename A2::const_reference const_reference;
30 typedef typename A2::size_type size_type;
31 typedef typename A2::difference_type difference_type;
32 template<typename U>
33 struct rebind {
34 typedef allocate_array_helper<A, T[], U> other;
35 };
36 allocate_array_helper(const A& allocator, std::size_t size, T** data)
37 : allocator(allocator),
38 size(sizeof(T) * size),
39 data(data) {
40 }
41 template<class U>
42 allocate_array_helper(const allocate_array_helper<A, T[], U>& other)
43 : allocator(other.allocator),
44 size(other.size),
45 data(other.data) {
46 }
47 pointer address(reference value) const {
48 return allocator.address(value);
49 }
50 const_pointer address(const_reference value) const {
51 return allocator.address(value);
52 }
53 size_type max_size() const {
54 return allocator.max_size();
55 }
56 pointer allocate(size_type count, const void* value = 0) {
57 std::size_t a1 = ndnboost::alignment_of<T>::value;
58 std::size_t n1 = count * sizeof(Y) + a1 - 1;
59 char* p1 = A3(allocator).allocate(n1 + size, value);
60 char* p2 = p1 + n1;
61 while (std::size_t(p2) % a1 != 0) {
62 p2--;
63 }
64 *data = reinterpret_cast<T*>(p2);
65 return reinterpret_cast<Y*>(p1);
66 }
67 void deallocate(pointer memory, size_type count) {
68 std::size_t a1 = ndnboost::alignment_of<T>::value;
69 std::size_t n1 = count * sizeof(Y) + a1 - 1;
70 char* p1 = reinterpret_cast<char*>(memory);
71 A3(allocator).deallocate(p1, n1 + size);
72 }
73 void construct(pointer memory, const Y& value) {
74 allocator.construct(memory, value);
75 }
76 void destroy(pointer memory) {
77 allocator.destroy(memory);
78 }
79 template<typename U>
80 bool operator==(const allocate_array_helper<A, T[], U>& other) const {
81 return allocator == other.allocator;
82 }
83 template<typename U>
84 bool operator!=(const allocate_array_helper<A, T[], U>& other) const {
85 return !(*this == other);
86 }
87 private:
88 A2 allocator;
89 std::size_t size;
90 T** data;
91 };
92 template<typename A, typename T, std::size_t N, typename Y>
93 class allocate_array_helper<A, T[N], Y> {
94 template<typename A9, typename T9, typename Y9>
95 friend class allocate_array_helper;
96 typedef typename A::template rebind<Y> ::other A2;
97 typedef typename A::template rebind<char>::other A3;
98 public:
99 typedef typename A2::value_type value_type;
100 typedef typename A2::pointer pointer;
101 typedef typename A2::const_pointer const_pointer;
102 typedef typename A2::reference reference;
103 typedef typename A2::const_reference const_reference;
104 typedef typename A2::size_type size_type;
105 typedef typename A2::difference_type difference_type;
106 template<typename U>
107 struct rebind {
108 typedef allocate_array_helper<A, T[N], U> other;
109 };
110 allocate_array_helper(const A& allocator, T** data)
111 : allocator(allocator),
112 data(data) {
113 }
114 template<class U>
115 allocate_array_helper(const allocate_array_helper<A, T[N], U>& other)
116 : allocator(other.allocator),
117 data(other.data) {
118 }
119 pointer address(reference value) const {
120 return allocator.address(value);
121 }
122 const_pointer address(const_reference value) const {
123 return allocator.address(value);
124 }
125 size_type max_size() const {
126 return allocator.max_size();
127 }
128 pointer allocate(size_type count, const void* value = 0) {
129 std::size_t a1 = ndnboost::alignment_of<T>::value;
130 std::size_t n1 = count * sizeof(Y) + a1 - 1;
131 char* p1 = A3(allocator).allocate(n1 + N1, value);
132 char* p2 = p1 + n1;
133 while (std::size_t(p2) % a1 != 0) {
134 p2--;
135 }
136 *data = reinterpret_cast<T*>(p2);
137 return reinterpret_cast<Y*>(p1);
138 }
139 void deallocate(pointer memory, size_type count) {
140 std::size_t a1 = ndnboost::alignment_of<T>::value;
141 std::size_t n1 = count * sizeof(Y) + a1 - 1;
142 char* p1 = reinterpret_cast<char*>(memory);
143 A3(allocator).deallocate(p1, n1 + N1);
144 }
145 void construct(pointer memory, const Y& value) {
146 allocator.construct(memory, value);
147 }
148 void destroy(pointer memory) {
149 allocator.destroy(memory);
150 }
151 template<typename U>
152 bool operator==(const allocate_array_helper<A, T[N], U>& other) const {
153 return allocator == other.allocator;
154 }
155 template<typename U>
156 bool operator!=(const allocate_array_helper<A, T[N], U>& other) const {
157 return !(*this == other);
158 }
159 private:
160 enum {
161 N1 = N * sizeof(T)
162 };
163 A2 allocator;
164 T** data;
165 };
166 }
167}
168
169#endif