1 /*
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 GATEKEEPER_UNIQUE_PTR_H_included
18 #define GATEKEEPER_UNIQUE_PTR_H_included
19 
20 #include <stddef.h> // for size_t
21 
22 namespace gatekeeper {
23 
24 // Default deleter for pointer types.
25 template <typename T>
26 struct DefaultDelete {
27     enum { type_must_be_complete = sizeof(T) };
DefaultDeleteDefaultDelete28     DefaultDelete() {}
operatorDefaultDelete29     void operator()(T* p) const {
30         delete p;
31     }
32 };
33 
34 // Default deleter for array types.
35 template <typename T>
36 struct 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);
51 template <typename T, typename D = DefaultDelete<T> >
52 class UniquePtr {
53     template<typename U, typename UD>
54     friend
55     class UniquePtr;
56 public:
57     UniquePtr() : mPtr(nullptr) {}
58     // Construct a new UniquePtr, taking ownership of the given raw pointer.
59     explicit UniquePtr(T* ptr) : mPtr(ptr) {
60     }
61     // NOLINTNEXTLINE(google-explicit-constructor)
62     UniquePtr(const decltype(nullptr)&) : mPtr(nullptr) {}
63 
64     UniquePtr(UniquePtr && other): mPtr(other.mPtr) {
65         other.mPtr = nullptr;
66     }
67 
68     template <typename U>
69     // NOLINTNEXTLINE(google-explicit-constructor)
70     UniquePtr(UniquePtr<U>&& other) : mPtr(other.mPtr) {
71         other.mPtr = nullptr;
72     }
73     UniquePtr& operator=(UniquePtr && other) {
74         if (&other != this) {
75             reset();
76             mPtr = other.release();
77         }
78         return *this;
79     }
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 
90     // NOLINTNEXTLINE(google-explicit-constructor)
91     operator bool() const { return mPtr != nullptr; }
92 
93     // 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 
111 private:
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[].
125 template <typename T, typename D>
126 class UniquePtr<T[], D> {
127 public:
128     UniquePtr() : mPtr(nullptr) {}
129     explicit UniquePtr(T* ptr) : mPtr(ptr) {
130     }
131     // NOLINTNEXTLINE(google-explicit-constructor)
132     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;
143     }
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 
160     // NOLINTNEXTLINE(google-explicit-constructor)
161     operator bool() const { return mPtr != nullptr; }
162 
163     void reset(T* ptr = nullptr) {
164         if (ptr != mPtr) {
165             D()(mPtr);
166             mPtr = ptr;
167         }
168     }
169 
170 private:
171     T* mPtr;
172 
173     UniquePtr(const UniquePtr&) = delete;
174     UniquePtr & operator=(const UniquePtr&) = delete;
175 };
176 
177 } // namespace gatekeeper
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>
185 using namespace keymaster;
186 
187 static void assert(bool b) {
188     if (!b) {
189         fprintf(stderr, "FAIL\n");
190         abort();
191     }
192     fprintf(stderr, "OK\n");
193 }
194 static int cCount = 0;
195 struct C {
196     C() { ++cCount; }
197     ~C() { --cCount; }
198 };
199 static bool freed = false;
200 struct Freer {
201     void operator()(int* p) {
202         assert(*p == 123);
203         free(p);
204         freed = true;
205     }
206 };
207 
208 int 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  // GATEKEEPER_UNIQUE_PTR_H_included
278