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