blob: 731001a8c9d7d8bb03dfd33379bb3239e0a8e469 [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"
bsalomon@google.comb0951402011-08-19 15:37:34 +000015#include "GrRefCnt.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000016
17static int GrInitialArrayAllocationCount() {
18 return 4;
19}
20
21static int GrNextArrayAllocationCount(int count) {
22 return count + ((count + 1) >> 1);
23}
24
25template <typename T> class GrTDArray {
26public:
27 GrTDArray() : fArray(NULL), fAllocated(0), fCount(0) {}
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 }
33 ~GrTDArray() {
34 if (fArray) {
35 GrFree(fArray);
36 }
37 }
38
39 bool isEmpty() const { return 0 == fCount; }
40 int count() const { return fCount; }
41
42 const T& at(int index) const {
43 GrAssert((unsigned)index < (unsigned)fCount);
44 return fArray[index];
45 }
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
65 void reset() {
66 if (fArray) {
67 GrFree(fArray);
68 fArray = NULL;
69 }
70 fAllocated = fCount = 0;
71 }
72
73 T* begin() const { return fArray; }
74 T* end() const { return fArray + fCount; }
75 T* back() const { GrAssert(fCount); return fArray + (fCount - 1); }
76
77 T* prepend() {
78 this->growAt(0);
79 return fArray;
80 }
81
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 */
90 T* insert(int index) {
91 GrAssert((unsigned)index <= (unsigned)fCount);
92 this->growAt(index);
93 return fArray + index;
94 }
95
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
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 */
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 */
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 */
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
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
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
180private:
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.
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
211extern void* GrTDArray_growAt(void*, int* allocated, int& count, int index,
212 size_t);
213
214
215#endif
216