3 * Copyright 2006 The Android Open Source Project
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
10 #ifndef SkTDArray_DEFINED
11 #define SkTDArray_DEFINED
15 template <typename T> class SK_API SkTDArray {
18 fReserve = fCount = 0;
24 SkTDArray(const T src[], int count) {
25 SkASSERT(src || count == 0);
27 fReserve = fCount = 0;
33 fArray = (T*)sk_malloc_throw(count * sizeof(T));
35 fData = (ArrayT*)fArray;
37 memcpy(fArray, src, sizeof(T) * count);
38 fReserve = fCount = count;
41 SkTDArray(const SkTDArray<T>& src) {
42 fReserve = fCount = 0;
47 SkTDArray<T> tmp(src.fArray, src.fCount);
54 SkTDArray<T>& operator=(const SkTDArray<T>& src) {
56 if (src.fCount > fReserve) {
57 SkTDArray<T> tmp(src.fArray, src.fCount);
60 memcpy(fArray, src.fArray, sizeof(T) * src.fCount);
67 friend bool operator==(const SkTDArray<T>& a, const SkTDArray<T>& b) {
68 return a.fCount == b.fCount &&
70 !memcmp(a.fArray, b.fArray, a.fCount * sizeof(T)));
72 friend bool operator!=(const SkTDArray<T>& a, const SkTDArray<T>& b) {
76 void swap(SkTDArray<T>& other) {
77 SkTSwap(fArray, other.fArray);
79 SkTSwap(fData, other.fData);
81 SkTSwap(fReserve, other.fReserve);
82 SkTSwap(fCount, other.fCount);
85 /** Return a ptr to the array of data, to be freed with sk_free. This also
86 resets the SkTDArray to be empty.
91 fReserve = fCount = 0;
92 SkDEBUGCODE(fData = NULL;)
96 bool isEmpty() const { return fCount == 0; }
99 * Return the number of elements in the array
101 int count() const { return fCount; }
104 * return the number of bytes in the array: count * sizeof(T)
106 size_t bytes() const { return fCount * sizeof(T); }
108 T* begin() { return fArray; }
109 const T* begin() const { return fArray; }
110 T* end() { return fArray ? fArray + fCount : NULL; }
111 const T* end() const { return fArray ? fArray + fCount : NULL; }
113 T& operator[](int index) {
114 SkASSERT(index < fCount);
115 return fArray[index];
117 const T& operator[](int index) const {
118 SkASSERT(index < fCount);
119 return fArray[index];
122 T& getAt(int index) {
123 return (*this)[index];
125 const T& getAt(int index) const {
126 return (*this)[index];
136 fReserve = fCount = 0;
138 SkASSERT(fReserve == 0 && fCount == 0);
143 // same as setCount(0)
147 void setCount(int count) {
148 if (count > fReserve) {
149 this->growBy(count - fCount);
155 void setReserve(int reserve) {
156 if (reserve > fReserve) {
157 SkASSERT(reserve > fCount);
159 this->growBy(reserve - fCount);
166 memmove(fArray + 1, fArray, (fCount - 1) * sizeof(T));
171 return this->append(1, NULL);
173 T* append(int count, const T* src = NULL) {
174 int oldCount = fCount;
176 SkASSERT(src == NULL || fArray == NULL ||
177 src + count <= fArray || fArray + oldCount <= src);
181 memcpy(fArray + oldCount, src, sizeof(T) * count);
184 return fArray + oldCount;
188 T* result = this->append();
193 T* insert(int index) {
194 return this->insert(index, 1, NULL);
196 T* insert(int index, int count, const T* src = NULL) {
198 SkASSERT(index <= fCount);
199 size_t oldCount = fCount;
201 T* dst = fArray + index;
202 memmove(dst + count, dst, sizeof(T) * (oldCount - index));
204 memcpy(dst, src, sizeof(T) * count);
209 void remove(int index, int count = 1) {
210 SkASSERT(index + count <= fCount);
211 fCount = fCount - count;
212 memmove(fArray + index, fArray + index + count, sizeof(T) * (fCount - index));
215 void removeShuffle(int index) {
216 SkASSERT(index < fCount);
217 int newCount = fCount - 1;
219 if (index != newCount) {
220 memcpy(fArray + index, fArray + newCount, sizeof(T));
224 int find(const T& elem) const {
225 const T* iter = fArray;
226 const T* stop = fArray + fCount;
228 for (; iter < stop; iter++) {
230 return (int) (iter - fArray);
236 int rfind(const T& elem) const {
237 const T* iter = fArray + fCount;
238 const T* stop = fArray;
240 while (iter > stop) {
241 if (*--iter == elem) {
249 * Returns true iff the array contains this element.
251 bool contains(const T& elem) const {
252 return (this->find(elem) >= 0);
256 * Copies up to max elements into dst. The number of items copied is
257 * capped by count - index. The actual number copied is returned.
259 int copyRange(T* dst, int index, int max) const {
261 SkASSERT(!max || dst);
262 if (index >= fCount) {
265 int count = SkMin32(max, fCount - index);
266 memcpy(dst, fArray + index, sizeof(T) * count);
270 void copy(T* dst) const {
271 this->copyRange(dst, 0, fCount);
274 // routines to treat the array like a stack
275 T* push() { return this->append(); }
276 void push(const T& elem) { *this->append() = elem; }
277 const T& top() const { return (*this)[fCount - 1]; }
278 T& top() { return (*this)[fCount - 1]; }
279 void pop(T* elem) { if (elem) *elem = (*this)[fCount - 1]; --fCount; }
280 void pop() { --fCount; }
284 T* stop = fArray + fCount;
285 while (iter < stop) {
294 T* stop = fArray + fCount;
295 while (iter < stop) {
304 T* stop = fArray + fCount;
305 while (iter < stop) {
312 void safeUnrefAll() {
314 T* stop = fArray + fCount;
315 while (iter < stop) {
322 void visitAll(void visitor(T&)) {
323 T* stop = this->end();
324 for (T* curr = this->begin(); curr < stop; curr++) {
332 void validate() const {
333 SkASSERT((fReserve == 0 && fArray == NULL) ||
334 (fReserve > 0 && fArray != NULL));
335 SkASSERT(fCount <= fReserve);
336 SkASSERT(fData == (ArrayT*)fArray);
345 typedef T ArrayT[kDebugArraySize];
352 void growBy(int extra) {
355 if (fCount + extra > fReserve) {
356 int size = fCount + extra + 4;
359 fArray = (T*)sk_realloc_throw(fArray, size * sizeof(T));
361 fData = (ArrayT*)fArray;