blob: 20ff446dd60852e257ba2c4ceb32f140ff96da4f [file] [log] [blame]
Janis Danisevskisf38a0022017-04-26 14:44:46 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef INCLUDE_KEYMASTER_UNIQUEPTR_H_
18#define INCLUDE_KEYMASTER_UNIQUEPTR_H_
19
20#include <stddef.h> // for size_t
21
22namespace keymaster {
23
24// Default deleter for pointer types.
25template <typename T>
26struct DefaultDelete {
27 enum { type_must_be_complete = sizeof(T) };
28 DefaultDelete() {}
29 void operator()(T* p) const {
30 delete p;
31 }
32};
33
34// Default deleter for array types.
35template <typename T>
36struct DefaultDelete<T[]> {
37 enum { type_must_be_complete = sizeof(T) };
38 void operator()(T* p) const {
39 delete[] p;
40 }
41};
42
43// A smart pointer that deletes the given pointer on destruction.
44// Equivalent to C++0x's std::unique_ptr (a combination of boost::scoped_ptr
45// and boost::scoped_array).
46// Named to be in keeping with Android style but also to avoid
47// collision with any other implementation, until we can switch over
48// to unique_ptr.
49// Use thus:
50// UniquePtr<C> c(new C);
51template <typename T, typename D = DefaultDelete<T> >
52class UniquePtr {
Janis Danisevskisd8091852017-05-10 18:56:35 -070053 template<typename U, typename UD>
54 friend
55 class UniquePtr;
Janis Danisevskisf38a0022017-04-26 14:44:46 -070056public:
Janis Danisevskisd8091852017-05-10 18:56:35 -070057 UniquePtr() : mPtr(nullptr) {}
Janis Danisevskisf38a0022017-04-26 14:44:46 -070058 // Construct a new UniquePtr, taking ownership of the given raw pointer.
Janis Danisevskisd8091852017-05-10 18:56:35 -070059 explicit UniquePtr(T* ptr) : mPtr(ptr) {
60 }
Chih-Hung Hsieh82ac3412019-01-02 13:34:23 -080061 // NOLINTNEXTLINE(google-explicit-constructor)
Janis Danisevskisd8091852017-05-10 18:56:35 -070062 UniquePtr(const decltype(nullptr)&) : mPtr(nullptr) {}
63
64 UniquePtr(UniquePtr && other): mPtr(other.mPtr) {
65 other.mPtr = nullptr;
66 }
67
Chih-Hung Hsieh82ac3412019-01-02 13:34:23 -080068 template <typename U>
69 // NOLINTNEXTLINE(google-explicit-constructor)
70 UniquePtr(UniquePtr<U>&& other) : mPtr(other.mPtr) {
Janis Danisevskisd8091852017-05-10 18:56:35 -070071 other.mPtr = nullptr;
72 }
73 UniquePtr& operator=(UniquePtr && other) {
74 if (&other != this) {
75 reset();
76 mPtr = other.release();
77 }
78 return *this;
Janis Danisevskisf38a0022017-04-26 14:44:46 -070079 }
80
81 ~UniquePtr() {
82 reset();
83 }
84
85 // Accessors.
86 T& operator*() const { return *mPtr; }
87 T* operator->() const { return mPtr; }
88 T* get() const { return mPtr; }
89
Chih-Hung Hsieh82ac3412019-01-02 13:34:23 -080090 // NOLINTNEXTLINE(google-explicit-constructor)
Janis Danisevskisd8091852017-05-10 18:56:35 -070091 operator bool() const { return mPtr != nullptr; }
92
Janis Danisevskisf38a0022017-04-26 14:44:46 -070093 // Returns the raw pointer and hands over ownership to the caller.
94 // The pointer will not be deleted by UniquePtr.
95 T* release() __attribute__((warn_unused_result)) {
96 T* result = mPtr;
97 mPtr = nullptr;
98 return result;
99 }
100
101 // Takes ownership of the given raw pointer.
102 // If this smart pointer previously owned a different raw pointer, that
103 // raw pointer will be freed.
104 void reset(T* ptr = nullptr) {
105 if (ptr != mPtr) {
106 D()(mPtr);
107 mPtr = ptr;
108 }
109 }
110
111private:
112 // The raw pointer.
113 T* mPtr;
114
115 // Comparing unique pointers is probably a mistake, since they're unique.
116 template <typename T2> bool operator==(const UniquePtr<T2>& p) const;
117 template <typename T2> bool operator!=(const UniquePtr<T2>& p) const;
118
119 UniquePtr(const UniquePtr&) = delete;
120 UniquePtr & operator=(const UniquePtr&) = delete;
121};
122
123// Partial specialization for array types. Like std::unique_ptr, this removes
124// operator* and operator-> but adds operator[].
125template <typename T, typename D>
126class UniquePtr<T[], D> {
127public:
Janis Danisevskisd8091852017-05-10 18:56:35 -0700128 UniquePtr() : mPtr(nullptr) {}
129 explicit UniquePtr(T* ptr) : mPtr(ptr) {
130 }
Chih-Hung Hsieh82ac3412019-01-02 13:34:23 -0800131 // NOLINTNEXTLINE(google-explicit-constructor)
Janis Danisevskisd8091852017-05-10 18:56:35 -0700132 UniquePtr(const decltype(nullptr)&) : mPtr(nullptr) {}
133
134 UniquePtr(UniquePtr && other): mPtr(other.mPtr) {
135 other.mPtr = nullptr;
136 }
137 UniquePtr& operator=(UniquePtr && other) {
138 if (&other != this) {
139 reset();
140 mPtr = other.release();
141 }
142 return *this;
Janis Danisevskisf38a0022017-04-26 14:44:46 -0700143 }
144
145 ~UniquePtr() {
146 reset();
147 }
148
149 T& operator[](size_t i) const {
150 return mPtr[i];
151 }
152 T* get() const { return mPtr; }
153
154 T* release() __attribute__((warn_unused_result)) {
155 T* result = mPtr;
156 mPtr = nullptr;
157 return result;
158 }
159
Chih-Hung Hsieh82ac3412019-01-02 13:34:23 -0800160 // NOLINTNEXTLINE(google-explicit-constructor)
Janis Danisevskisd8091852017-05-10 18:56:35 -0700161 operator bool() const { return mPtr != nullptr; }
162
Janis Danisevskisf38a0022017-04-26 14:44:46 -0700163 void reset(T* ptr = nullptr) {
164 if (ptr != mPtr) {
165 D()(mPtr);
166 mPtr = ptr;
167 }
168 }
169
170private:
171 T* mPtr;
172
173 UniquePtr(const UniquePtr&) = delete;
174 UniquePtr & operator=(const UniquePtr&) = delete;
175};
176
177} // namespace keymaster
178
179#if UNIQUE_PTR_TESTS
180
181// Run these tests with:
182// g++ -g -DUNIQUE_PTR_TESTS -x c++ UniquePtr.h && ./a.out
183
184#include <stdio.h>
185using namespace keymaster;
186
187static void assert(bool b) {
188 if (!b) {
189 fprintf(stderr, "FAIL\n");
190 abort();
191 }
192 fprintf(stderr, "OK\n");
193}
194static int cCount = 0;
195struct C {
196 C() { ++cCount; }
197 ~C() { --cCount; }
198};
199static bool freed = false;
200struct Freer {
201 void operator()(int* p) {
202 assert(*p == 123);
203 free(p);
204 freed = true;
205 }
206};
207
208int main(int argc, char* argv[]) {
209 //
210 // UniquePtr<T> tests...
211 //
212
213 // Can we free a single object?
214 {
215 UniquePtr<C> c(new C);
216 assert(cCount == 1);
217 }
218 assert(cCount == 0);
219 // Does release work?
220 C* rawC;
221 {
222 UniquePtr<C> c(new C);
223 assert(cCount == 1);
224 rawC = c.release();
225 }
226 assert(cCount == 1);
227 delete rawC;
228 // Does reset work?
229 {
230 UniquePtr<C> c(new C);
231 assert(cCount == 1);
232 c.reset(new C);
233 assert(cCount == 1);
234 }
235 assert(cCount == 0);
236
237 //
238 // UniquePtr<T[]> tests...
239 //
240
241 // Can we free an array?
242 {
243 UniquePtr<C[]> cs(new C[4]);
244 assert(cCount == 4);
245 }
246 assert(cCount == 0);
247 // Does release work?
248 {
249 UniquePtr<C[]> c(new C[4]);
250 assert(cCount == 4);
251 rawC = c.release();
252 }
253 assert(cCount == 4);
254 delete[] rawC;
255 // Does reset work?
256 {
257 UniquePtr<C[]> c(new C[4]);
258 assert(cCount == 4);
259 c.reset(new C[2]);
260 assert(cCount == 2);
261 }
262 assert(cCount == 0);
263
264 //
265 // Custom deleter tests...
266 //
267 assert(!freed);
268 {
269 UniquePtr<int, Freer> i(reinterpret_cast<int*>(malloc(sizeof(int))));
270 *i = 123;
271 }
272 assert(freed);
273 return 0;
274}
275#endif
276
277#endif // INCLUDE_KEYMASTER_UNIQUEPTR_H_