blob: 8f796515afffd0ad3a7b9ce041b27e826e452027 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
reed@google.comac10a2d2010-12-22 21:39:39 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * Copyright 2010 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
reed@google.comac10a2d2010-12-22 21:39:39 +00007 */
8
9
epoger@google.comec3ed6a2011-07-28 14:26:00 +000010
reed@google.comac10a2d2010-12-22 21:39:39 +000011#ifndef GrTDArray_DEFINED
12#define GrTDArray_DEFINED
13
14#include "GrTypes.h"
15
16static int GrInitialArrayAllocationCount() {
17 return 4;
18}
19
20static int GrNextArrayAllocationCount(int count) {
21 return count + ((count + 1) >> 1);
22}
23
24template <typename T> class GrTDArray {
25public:
26 GrTDArray() : fArray(NULL), fAllocated(0), fCount(0) {}
27 GrTDArray(const GrTDArray& src) {
28 fCount = fAllocated = src.fCount;
29 fArray = (T*)GrMalloc(fAllocated * sizeof(T));
30 memcpy(fArray, src.fArray, fCount * sizeof(T));
31 }
32 ~GrTDArray() {
33 if (fArray) {
34 GrFree(fArray);
35 }
36 }
37
38 bool isEmpty() const { return 0 == fCount; }
39 int count() const { return fCount; }
40
41 const T& at(int index) const {
42 GrAssert((unsigned)index < (unsigned)fCount);
43 return fArray[index];
44 }
45 T& at(int index) {
46 GrAssert((unsigned)index < (unsigned)fCount);
47 return fArray[index];
48 }
49
50 const T& operator[](int index) const { return this->at(index); }
51 T& operator[](int index) { return this->at(index); }
52
53 GrTDArray& operator=(const GrTDArray& src) {
54 if (fAllocated < src.fCount) {
55 fAllocated = src.fCount;
56 GrFree(fArray);
57 fArray = (T*)GrMalloc(fAllocated * sizeof(T));
58 }
59 fCount = src.fCount;
60 memcpy(fArray, src.fArray, fCount * sizeof(T));
61 return *this;
62 }
63
64 void reset() {
65 if (fArray) {
66 GrFree(fArray);
67 fArray = NULL;
68 }
69 fAllocated = fCount = 0;
70 }
71
72 T* begin() const { return fArray; }
73 T* end() const { return fArray + fCount; }
74 T* back() const { GrAssert(fCount); return fArray + (fCount - 1); }
75
76 T* prepend() {
77 this->growAt(0);
78 return fArray;
79 }
80
81 T* append() {
82 this->growAt(fCount);
83 return fArray + fCount - 1;
84 }
85
86 /**
87 * index may be [0..count], so that you can insert at the end (like append)
88 */
89 T* insert(int index) {
90 GrAssert((unsigned)index <= (unsigned)fCount);
91 this->growAt(index);
92 return fArray + index;
93 }
94
95 void remove(int index) {
96 GrAssert((unsigned)index < (unsigned)fCount);
97 fCount -= 1;
98 if (index < fCount) {
99 int remaining = fCount - index;
100 memmove(fArray + index, fArray + index + 1, remaining * sizeof(T));
101 }
102 }
103
104 void removeShuffle(int index) {
105 GrAssert((unsigned)index < (unsigned)fCount);
106 fCount -= 1;
107 if (index < fCount) {
108 memmove(fArray + index, fArray + fCount, sizeof(T));
109 }
110 }
111
112 // Utility iterators
113
114 /**
115 * Calls GrFree() on each element. Assumes each is NULL or was allocated
116 * with GrMalloc().
117 */
118 void freeAll() {
119 T* stop = this->end();
120 for (T* curr = this->begin(); curr < stop; curr++) {
121 GrFree(*curr);
122 }
123 this->reset();
124 }
125
126 /**
127 * Calls delete on each element. Assumes each is NULL or was allocated
128 * with new.
129 */
130 void deleteAll() {
131 T* stop = this->end();
132 for (T* curr = this->begin(); curr < stop; curr++) {
133 delete *curr;
134 }
135 this->reset();
136 }
137
138 /**
139 * Calls GrSafeUnref() on each element. Assumes each is NULL or is a
140 * subclass of GrRefCnt.
141 */
142 void unrefAll() {
143 T* stop = this->end();
144 for (T* curr = this->begin(); curr < stop; curr++) {
145 GrSafeUnref(*curr);
146 }
147 this->reset();
148 }
149
150 void visit(void visitor(T&)) const {
151 T* stop = this->end();
152 for (T* curr = this->begin(); curr < stop; curr++) {
153 if (*curr) {
154 visitor(*curr);
155 }
156 }
157 }
158
159 int find(const T& elem) const {
160 int count = this->count();
161 T* curr = this->begin();
162 for (int i = 0; i < count; i++) {
163 if (elem == curr[i]) {
164 return i;
165 }
166 }
167 return -1;
168 }
169
170 friend bool operator==(const GrTDArray<T>& a, const GrTDArray<T>& b) {
171 return a.count() == b.count() &&
172 (0 == a.count() ||
173 0 == memcmp(a.begin(), b.begin(), a.count() * sizeof(T)));
174 }
175 friend bool operator!=(const GrTDArray<T>& a, const GrTDArray<T>& b) {
176 return !(a == b);
177 }
178
179private:
180 T* fArray;
181 int fAllocated, fCount;
182
183 // growAt will increment fCount, reallocate fArray (as needed), and slide
184 // the contents of fArray to make a hole for new data at index.
185 void growAt(int index) {
186 GrAssert(fCount <= fAllocated);
187 if (0 == fAllocated) {
188 fAllocated = GrInitialArrayAllocationCount();
189 fArray = (T*)GrMalloc(fAllocated * sizeof(T));
190 } else if (fCount == fAllocated) {
191 fAllocated = GrNextArrayAllocationCount(fAllocated);
192 T* newArray = (T*)GrMalloc(fAllocated * sizeof(T));
193 memcpy(newArray, fArray, index * sizeof(T));
194 memcpy(newArray + index + 1, fArray + index,
195 (fCount - index) * sizeof(T));
196 GrFree(fArray);
197 fArray = newArray;
198 } else {
199 // check that we're not just appending
200 if (index < fCount) {
201 memmove(fArray + index + 1, fArray + index,
202 (fCount - index) * sizeof(T));
203 }
204 }
205 GrAssert(fCount < fAllocated);
206 fCount += 1;
207 }
208};
209
210extern void* GrTDArray_growAt(void*, int* allocated, int& count, int index,
211 size_t);
212
213
214#endif
215