blob: 27ebd416df8c5cc4a4f59de89d9c742de93eef6f [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/*
2 * Copyright (C) 2006 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 SkTemplates_DEFINED
18#define SkTemplates_DEFINED
19
20#include "SkTypes.h"
21
22/** \file SkTemplates.h
23
24 This file contains light-weight template classes for type-safe and exception-safe
25 resource management.
26*/
27
28/** \class SkAutoTCallVProc
29
30 Call a function when this goes out of scope. The template uses two
31 parameters, the object, and a function that is to be called in the destructor.
32 If detach() is called, the object reference is set to null. If the object
33 reference is null when the destructor is called, we do not call the
34 function.
35*/
36template <typename T, void (*P)(T*)> class SkAutoTCallVProc : SkNoncopyable {
37public:
38 SkAutoTCallVProc(T* obj): fObj(obj) {}
39 ~SkAutoTCallVProc() { if (fObj) P(fObj); }
40 T* detach() { T* obj = fObj; fObj = NULL; return obj; }
41private:
42 T* fObj;
43};
44
45/** \class SkAutoTCallIProc
46
47Call a function when this goes out of scope. The template uses two
48parameters, the object, and a function that is to be called in the destructor.
49If detach() is called, the object reference is set to null. If the object
50reference is null when the destructor is called, we do not call the
51function.
52*/
53template <typename T, int (*P)(T*)> class SkAutoTCallIProc : SkNoncopyable {
54public:
55 SkAutoTCallIProc(T* obj): fObj(obj) {}
56 ~SkAutoTCallIProc() { if (fObj) P(fObj); }
57 T* detach() { T* obj = fObj; fObj = NULL; return obj; }
58private:
59 T* fObj;
60};
61
62template <typename T> class SkAutoTDelete : SkNoncopyable {
63public:
64 SkAutoTDelete(T* obj) : fObj(obj) {}
65 ~SkAutoTDelete() { delete fObj; }
66
67 T* get() const { return fObj; }
68 void free() { delete fObj; fObj = NULL; }
69 T* detach() { T* obj = fObj; fObj = NULL; return obj; }
70
71private:
72 T* fObj;
73};
74
75template <typename T> class SkAutoTDeleteArray : SkNoncopyable {
76public:
77 SkAutoTDeleteArray(T array[]) : fArray(array) {}
78 ~SkAutoTDeleteArray() { delete[] fArray; }
79
80 T* get() const { return fArray; }
81 void free() { delete[] fArray; fArray = NULL; }
82 T* detach() { T* array = fArray; fArray = NULL; return array; }
83
84private:
85 T* fArray;
86};
87
88/** Allocate an array of T elements, and free the array in the destructor
89 */
90template <typename T> class SkAutoTArray : SkNoncopyable {
91public:
92 /** Allocate count number of T elements
93 */
94 SkAutoTArray(size_t count) {
95 fArray = NULL;
96 if (count) {
97 fArray = new T[count];
98 }
99 SkDEBUGCODE(fCount = count;)
100 }
101
102 ~SkAutoTArray() {
103 delete[] fArray;
104 }
105
106 /** Return the array of T elements. Will be NULL if count == 0
107 */
108 T* get() const { return fArray; }
109
110 /** Return the nth element in the array
111 */
112 T& operator[](int index) const {
113 SkASSERT((unsigned)index < fCount);
114 return fArray[index];
115 }
116
117private:
118 T* fArray;
119 SkDEBUGCODE(size_t fCount;)
120};
121
122/** Wraps SkAutoTArray, with room for up to N elements preallocated
123 */
124template <size_t N, typename T> class SkAutoSTArray : SkNoncopyable {
125public:
126 /** Allocate count number of T elements
127 */
128 SkAutoSTArray(size_t count) {
129 if (count > N) {
130 fArray = new T[count];
131 } else if (count) {
132 fArray = new (fStorage) T[count];
133 } else {
134 fArray = NULL;
135 }
136 fCount = count;
137 }
138
139 ~SkAutoSTArray() {
140 if (fCount > N) {
141 delete[] fArray;
142 } else {
143 T* start = fArray;
144 T* iter = start + fCount;
145 while (iter > start) {
146 (--iter)->~T();
147 }
148 }
149 }
150
151 /** Return the number of T elements in the array
152 */
153 size_t count() const { return fCount; }
154
155 /** Return the array of T elements. Will be NULL if count == 0
156 */
157 T* get() const { return fArray; }
158
159 /** Return the nth element in the array
160 */
161 T& operator[](int index) const {
162 SkASSERT((unsigned)index < fCount);
163 return fArray[index];
164 }
165
166private:
167 size_t fCount;
168 T* fArray;
169 // since we come right after fArray, fStorage should be properly aligned
170 char fStorage[N * sizeof(T)];
171};
172
173/** Allocate a temp array on the stack/heap.
174 Does NOT call any constructors/destructors on T (i.e. T must be POD)
175*/
176template <typename T> class SkAutoTMalloc : SkNoncopyable {
177public:
178 SkAutoTMalloc(size_t count)
179 {
180 fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP);
181 }
182 ~SkAutoTMalloc()
183 {
184 sk_free(fPtr);
185 }
186 T* get() const { return fPtr; }
187
188private:
189 T* fPtr;
190};
191
192template <size_t N, typename T> class SkAutoSTMalloc : SkNoncopyable {
193public:
194 SkAutoSTMalloc(size_t count)
195 {
196 if (count <= N)
197 fPtr = fTStorage;
198 else
199 fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP);
200 }
201 ~SkAutoSTMalloc()
202 {
203 if (fPtr != fTStorage)
204 sk_free(fPtr);
205 }
206 T* get() const { return fPtr; }
207
208private:
209 T* fPtr;
210 union {
211 uint32_t fStorage32[(N*sizeof(T) + 3) >> 2];
212 T fTStorage[1]; // do NOT want to invoke T::T()
213 };
214};
215
216#endif
217