blob: 05f5e9f2413363c54849587ec1ae644552d38359 [file] [log] [blame]
Nolan Scobied7e45e42023-01-05 16:04:58 -05001/**
2 * Copyright (C) 2023 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#pragma once
18
19#include <cstdlib>
20#include <memory>
21#include <type_traits>
22
23namespace android {
24namespace uirenderer {
25
26/** Manages an array of T elements, freeing the array in the destructor.
27 * Does NOT call any constructors/destructors on T (T must be POD).
28 */
29template <typename T,
30 typename = std::enable_if_t<std::is_trivially_default_constructible<T>::value &&
31 std::is_trivially_destructible<T>::value>>
32class AutoTMalloc {
33public:
34 /** Takes ownership of the ptr. The ptr must be a value which can be passed to std::free. */
35 explicit AutoTMalloc(T* ptr = nullptr) : fPtr(ptr) {}
36
37 /** Allocates space for 'count' Ts. */
38 explicit AutoTMalloc(size_t count) : fPtr(mallocIfCountThrowOnFail(count)) {}
39
40 AutoTMalloc(AutoTMalloc&&) = default;
41 AutoTMalloc& operator=(AutoTMalloc&&) = default;
42
43 /** Resize the memory area pointed to by the current ptr preserving contents. */
44 void realloc(size_t count) { fPtr.reset(reallocIfCountThrowOnFail(count)); }
45
46 /** Resize the memory area pointed to by the current ptr without preserving contents. */
47 T* reset(size_t count = 0) {
48 fPtr.reset(mallocIfCountThrowOnFail(count));
49 return this->get();
50 }
51
52 T* get() const { return fPtr.get(); }
53
54 operator T*() { return fPtr.get(); }
55
56 operator const T*() const { return fPtr.get(); }
57
58 T& operator[](int index) { return fPtr.get()[index]; }
59
60 const T& operator[](int index) const { return fPtr.get()[index]; }
61
62 /**
63 * Transfer ownership of the ptr to the caller, setting the internal
64 * pointer to NULL. Note that this differs from get(), which also returns
65 * the pointer, but it does not transfer ownership.
66 */
67 T* release() { return fPtr.release(); }
68
69private:
70 struct FreeDeleter {
71 void operator()(uint8_t* p) { std::free(p); }
72 };
73 std::unique_ptr<T, FreeDeleter> fPtr;
74
75 T* mallocIfCountThrowOnFail(size_t count) {
76 T* newPtr = nullptr;
77 if (count) {
78 newPtr = (T*)std::malloc(count * sizeof(T));
79 LOG_ALWAYS_FATAL_IF(!newPtr, "failed to malloc %zu bytes", count * sizeof(T));
80 }
81 return newPtr;
82 }
83 T* reallocIfCountThrowOnFail(size_t count) {
84 T* newPtr = nullptr;
85 if (count) {
86 newPtr = (T*)std::realloc(fPtr.release(), count * sizeof(T));
87 LOG_ALWAYS_FATAL_IF(!newPtr, "failed to realloc %zu bytes", count * sizeof(T));
88 }
89 return newPtr;
90 }
91};
92
93} // namespace uirenderer
94} // namespace android