1 :
2 : /*
3 : * Copyright 2006 The Android Open Source Project
4 : *
5 : * Use of this source code is governed by a BSD-style license that can be
6 : * found in the LICENSE file.
7 : */
8 :
9 :
10 : #ifndef SkTDArray_DEFINED
11 : #define SkTDArray_DEFINED
12 :
13 : #include "SkTypes.h"
14 :
15 : template <typename T> class SK_API SkTDArray {
16 : public:
17 1464 : SkTDArray() {
18 1464 : fReserve = fCount = 0;
19 1464 : fArray = NULL;
20 : #ifdef SK_DEBUG
21 1464 : fData = NULL;
22 : #endif
23 1464 : }
24 0 : SkTDArray(const T src[], size_t count) {
25 0 : SkASSERT(src || count == 0);
26 :
27 0 : fReserve = fCount = 0;
28 0 : fArray = NULL;
29 : #ifdef SK_DEBUG
30 0 : fData = NULL;
31 : #endif
32 0 : if (count) {
33 0 : fArray = (T*)sk_malloc_throw(count * sizeof(T));
34 : #ifdef SK_DEBUG
35 0 : fData = (ArrayT*)fArray;
36 : #endif
37 0 : memcpy(fArray, src, sizeof(T) * count);
38 0 : fReserve = fCount = count;
39 : }
40 0 : }
41 : SkTDArray(const SkTDArray<T>& src) {
42 : fReserve = fCount = 0;
43 : fArray = NULL;
44 : #ifdef SK_DEBUG
45 : fData = NULL;
46 : #endif
47 : SkTDArray<T> tmp(src.fArray, src.fCount);
48 : this->swap(tmp);
49 : }
50 1487 : ~SkTDArray() {
51 1487 : sk_free(fArray);
52 1487 : }
53 :
54 0 : SkTDArray<T>& operator=(const SkTDArray<T>& src) {
55 0 : if (this != &src) {
56 0 : if (src.fCount > fReserve) {
57 0 : SkTDArray<T> tmp(src.fArray, src.fCount);
58 0 : this->swap(tmp);
59 : } else {
60 0 : memcpy(fArray, src.fArray, sizeof(T) * src.fCount);
61 0 : fCount = src.fCount;
62 : }
63 : }
64 0 : return *this;
65 : }
66 :
67 0 : friend bool operator==(const SkTDArray<T>& a, const SkTDArray<T>& b) {
68 : return a.fCount == b.fCount &&
69 : (a.fCount == 0 ||
70 0 : !memcmp(a.fArray, b.fArray, a.fCount * sizeof(T)));
71 : }
72 :
73 0 : void swap(SkTDArray<T>& other) {
74 0 : SkTSwap(fArray, other.fArray);
75 : #ifdef SK_DEBUG
76 0 : SkTSwap(fData, other.fData);
77 : #endif
78 0 : SkTSwap(fReserve, other.fReserve);
79 0 : SkTSwap(fCount, other.fCount);
80 0 : }
81 :
82 : /** Return a ptr to the array of data, to be freed with sk_free. This also
83 : resets the SkTDArray to be empty.
84 : */
85 : T* detach() {
86 : T* array = fArray;
87 : fArray = NULL;
88 : fReserve = fCount = 0;
89 : SkDEBUGCODE(fData = NULL;)
90 : return array;
91 : }
92 :
93 0 : bool isEmpty() const { return fCount == 0; }
94 :
95 : /**
96 : * Return the number of elements in the array
97 : */
98 0 : int count() const { return fCount; }
99 :
100 : /**
101 : * return the number of bytes in the array: count * sizeof(T)
102 : */
103 0 : size_t bytes() const { return fCount * sizeof(T); }
104 :
105 0 : T* begin() const { return fArray; }
106 0 : T* end() const { return fArray ? fArray + fCount : NULL; }
107 0 : T& operator[](int index) const {
108 0 : SkASSERT((unsigned)index < fCount);
109 0 : return fArray[index];
110 : }
111 :
112 0 : void reset() {
113 0 : if (fArray) {
114 0 : sk_free(fArray);
115 0 : fArray = NULL;
116 : #ifdef SK_DEBUG
117 0 : fData = NULL;
118 : #endif
119 0 : fReserve = fCount = 0;
120 : } else {
121 0 : SkASSERT(fReserve == 0 && fCount == 0);
122 : }
123 0 : }
124 :
125 0 : void rewind() {
126 : // same as setCount(0)
127 0 : fCount = 0;
128 0 : }
129 :
130 0 : void setCount(size_t count) {
131 0 : if (count > fReserve) {
132 0 : this->growBy(count - fCount);
133 : } else {
134 0 : fCount = count;
135 : }
136 0 : }
137 :
138 0 : void setReserve(size_t reserve) {
139 0 : if (reserve > fReserve) {
140 0 : SkASSERT(reserve > fCount);
141 0 : size_t count = fCount;
142 0 : this->growBy(reserve - fCount);
143 0 : fCount = count;
144 : }
145 0 : }
146 :
147 : T* prepend() {
148 : this->growBy(1);
149 : memmove(fArray + 1, fArray, (fCount - 1) * sizeof(T));
150 : return fArray;
151 : }
152 :
153 0 : T* append() {
154 0 : return this->append(1, NULL);
155 : }
156 0 : T* append(size_t count, const T* src = NULL) {
157 0 : unsigned oldCount = fCount;
158 0 : if (count) {
159 0 : SkASSERT(src == NULL || fArray == NULL ||
160 : src + count <= fArray || fArray + oldCount <= src);
161 :
162 0 : this->growBy(count);
163 0 : if (src) {
164 0 : memcpy(fArray + oldCount, src, sizeof(T) * count);
165 : }
166 : }
167 0 : return fArray + oldCount;
168 : }
169 :
170 : T* appendClear() {
171 : T* result = this->append();
172 : *result = 0;
173 : return result;
174 : }
175 :
176 0 : T* insert(size_t index) {
177 0 : return this->insert(index, 1, NULL);
178 : }
179 0 : T* insert(size_t index, size_t count, const T* src = NULL) {
180 0 : SkASSERT(count);
181 0 : SkASSERT(index <= fCount);
182 0 : int oldCount = fCount;
183 0 : this->growBy(count);
184 0 : T* dst = fArray + index;
185 0 : memmove(dst + count, dst, sizeof(T) * (oldCount - index));
186 0 : if (src) {
187 0 : memcpy(dst, src, sizeof(T) * count);
188 : }
189 0 : return dst;
190 : }
191 :
192 0 : void remove(size_t index, size_t count = 1) {
193 0 : SkASSERT(index + count <= fCount);
194 0 : fCount = fCount - count;
195 0 : memmove(fArray + index, fArray + index + count, sizeof(T) * (fCount - index));
196 0 : }
197 :
198 0 : void removeShuffle(size_t index) {
199 0 : SkASSERT(index < fCount);
200 0 : unsigned newCount = fCount - 1;
201 0 : fCount = newCount;
202 0 : if (index != newCount) {
203 0 : memcpy(fArray + index, fArray + newCount, sizeof(T));
204 : }
205 0 : }
206 :
207 0 : int find(const T& elem) const {
208 0 : const T* iter = fArray;
209 0 : const T* stop = fArray + fCount;
210 :
211 0 : for (; iter < stop; iter++) {
212 0 : if (*iter == elem) {
213 0 : return (int) (iter - fArray);
214 : }
215 : }
216 0 : return -1;
217 : }
218 :
219 : int rfind(const T& elem) const {
220 : const T* iter = fArray + fCount;
221 : const T* stop = fArray;
222 :
223 : while (iter > stop) {
224 : if (*--iter == elem) {
225 : return iter - stop;
226 : }
227 : }
228 : return -1;
229 : }
230 :
231 : // routines to treat the array like a stack
232 : T* push() { return this->append(); }
233 0 : void push(const T& elem) { *this->append() = elem; }
234 : const T& top() const { return (*this)[fCount - 1]; }
235 0 : T& top() { return (*this)[fCount - 1]; }
236 : void pop(T* elem) { if (elem) *elem = (*this)[fCount - 1]; --fCount; }
237 0 : void pop() { --fCount; }
238 :
239 : void deleteAll() {
240 : T* iter = fArray;
241 : T* stop = fArray + fCount;
242 : while (iter < stop) {
243 : delete (*iter);
244 : iter += 1;
245 : }
246 : this->reset();
247 : }
248 :
249 : void freeAll() {
250 : T* iter = fArray;
251 : T* stop = fArray + fCount;
252 : while (iter < stop) {
253 : sk_free(*iter);
254 : iter += 1;
255 : }
256 : this->reset();
257 : }
258 :
259 0 : void unrefAll() {
260 0 : T* iter = fArray;
261 0 : T* stop = fArray + fCount;
262 0 : while (iter < stop) {
263 0 : (*iter)->unref();
264 0 : iter += 1;
265 : }
266 0 : this->reset();
267 0 : }
268 :
269 : void safeUnrefAll() {
270 : T* iter = fArray;
271 : T* stop = fArray + fCount;
272 : while (iter < stop) {
273 : SkSafeUnref(*iter);
274 : iter += 1;
275 : }
276 : this->reset();
277 : }
278 :
279 : #ifdef SK_DEBUG
280 0 : void validate() const {
281 0 : SkASSERT((fReserve == 0 && fArray == NULL) ||
282 : (fReserve > 0 && fArray != NULL));
283 0 : SkASSERT(fCount <= fReserve);
284 0 : SkASSERT(fData == (ArrayT*)fArray);
285 0 : }
286 : #endif
287 :
288 : private:
289 : #ifdef SK_DEBUG
290 : enum {
291 : kDebugArraySize = 16
292 : };
293 : typedef T ArrayT[kDebugArraySize];
294 : ArrayT* fData;
295 : #endif
296 : T* fArray;
297 : size_t fReserve, fCount;
298 :
299 0 : void growBy(size_t extra) {
300 0 : SkASSERT(extra);
301 :
302 0 : if (fCount + extra > fReserve) {
303 0 : size_t size = fCount + extra + 4;
304 0 : size += size >> 2;
305 :
306 0 : fArray = (T*)sk_realloc_throw(fArray, size * sizeof(T));
307 : #ifdef SK_DEBUG
308 0 : fData = (ArrayT*)fArray;
309 : #endif
310 0 : fReserve = size;
311 : }
312 0 : fCount += extra;
313 0 : }
314 : };
315 :
316 : #endif
317 :
|