blob: c32a75e564638b05d25cb5778b9917efe60cfcaa [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 GrTArray_DEFINED
12#define GrTArray_DEFINED
13
14#include <new>
15#include "GrTypes.h"
bsalomon@google.coma55847b2011-04-20 15:47:04 +000016#include "GrTemplates.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000017
reed@google.comac10a2d2010-12-22 21:39:39 +000018// DATA_TYPE indicates that T has a trivial cons, destructor
19// and can be shallow-copied
20template <typename T, bool DATA_TYPE = false> class GrTArray {
21public:
22 GrTArray() {
23 fCount = 0;
24 fReserveCount = MIN_ALLOC_COUNT;
25 fAllocCount = 0;
26 fMemArray = NULL;
27 fPreAllocMemArray = NULL;
28 }
29
bsalomon@google.com1c13c962011-02-14 16:51:21 +000030 explicit GrTArray(int reserveCount) {
31 GrAssert(reserveCount >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +000032 fCount = 0;
bsalomon@google.com1c13c962011-02-14 16:51:21 +000033 fReserveCount = reserveCount > MIN_ALLOC_COUNT ? reserveCount :
34 MIN_ALLOC_COUNT;
reed@google.comac10a2d2010-12-22 21:39:39 +000035 fAllocCount = fReserveCount;
36 fMemArray = GrMalloc(sizeof(T) * fReserveCount);
37 fPreAllocMemArray = NULL;
38 }
39
bsalomon@google.coma55847b2011-04-20 15:47:04 +000040 template <int N>
41 GrTArray(GrAlignedSTStorage<N,T>* storage) {
42 GrAssert(N > 0);
43 fCount = 0;
44 fReserveCount = N;
45 fAllocCount = N;
46 fMemArray = storage->get();
47 fPreAllocMemArray = storage->get();
48 }
49
bsalomon@google.com1c13c962011-02-14 16:51:21 +000050 GrTArray(void* preAllocStorage, int preAllocCount) {
51 GrAssert(preAllocCount >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +000052 // we allow NULL,0 args and revert to the default cons. behavior
53 // this makes it possible for a owner-object to use same constructor
54 // to get either prealloc or nonprealloc behavior based using same line
55 GrAssert((NULL == preAllocStorage) == !preAllocCount);
56
57 fCount = 0;
58 fReserveCount = preAllocCount > 0 ? preAllocCount :
59 MIN_ALLOC_COUNT;
60 fAllocCount = preAllocCount;
61 fMemArray = preAllocStorage;
62 fPreAllocMemArray = preAllocStorage;
63 }
64
bsalomon@google.com1c13c962011-02-14 16:51:21 +000065 explicit GrTArray(const GrTArray& array) {
reed@google.comac10a2d2010-12-22 21:39:39 +000066 fCount = array.count();
67 fReserveCount = MIN_ALLOC_COUNT;
68 fAllocCount = GrMax(fReserveCount, fCount);
69 fMemArray = GrMalloc(sizeof(T) * fAllocCount);
70 fPreAllocMemArray = NULL;
bsalomon@google.coma55847b2011-04-20 15:47:04 +000071
reed@google.comac10a2d2010-12-22 21:39:39 +000072 if (DATA_TYPE) {
73 memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
74 } else {
bsalomon@google.com1c13c962011-02-14 16:51:21 +000075 for (int i = 0; i < fCount; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +000076 new (fItemArray + i) T(array[i]);
77 }
78 }
79 }
80
bsalomon@google.com1c13c962011-02-14 16:51:21 +000081 GrTArray(const T* array, int count) {
82 GrAssert(count >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +000083 fCount = count;
84 fReserveCount = MIN_ALLOC_COUNT;
85 fAllocCount = GrMax(fReserveCount, fCount);
86 fMemArray = GrMalloc(sizeof(T) * fAllocCount);
87 fPreAllocMemArray = NULL;
88 if (DATA_TYPE) {
89 memcpy(fMemArray, array, sizeof(T) * fCount);
90 } else {
bsalomon@google.com1c13c962011-02-14 16:51:21 +000091 for (int i = 0; i < fCount; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +000092 new (fItemArray + i) T(array[i]);
93 }
94 }
95 }
96
97 GrTArray(const GrTArray& array,
bsalomon@google.com1c13c962011-02-14 16:51:21 +000098 void* preAllocStorage, int preAllocCount) {
99
100 GrAssert(preAllocCount >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000101
102 // for same reason as non-copying cons we allow NULL, 0 for prealloc
103 GrAssert((NULL == preAllocStorage) == !preAllocCount);
104
105 fCount = array.count();
106 fReserveCount = preAllocCount > 0 ? preAllocCount :
107 MIN_ALLOC_COUNT;
108 fPreAllocMemArray = preAllocStorage;
109
110 if (fReserveCount >= fCount && preAllocCount) {
111 fAllocCount = fReserveCount;
112 fMemArray = preAllocStorage;
113 } else {
114 fAllocCount = GrMax(fCount, fReserveCount);
115 fMemArray = GrMalloc(fAllocCount * sizeof(T));
116 }
117
118 if (DATA_TYPE) {
119 memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
120 } else {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000121 for (int i = 0; i < fCount; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000122 new (fItemArray + i) T(array[i]);
123 }
124 }
125 }
126
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000127 GrTArray(const T* array, int count,
128 void* preAllocStorage, int preAllocCount) {
129
130 GrAssert(count >= 0);
131 GrAssert(preAllocCount >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000132
133 // for same reason as non-copying cons we allow NULL, 0 for prealloc
134 GrAssert((NULL == preAllocStorage) == !preAllocCount);
135
136 fCount = count;
137 fReserveCount = (preAllocCount > 0) ? preAllocCount :
138 MIN_ALLOC_COUNT;
139 fPreAllocMemArray = preAllocStorage;
140
141 if (fReserveCount >= fCount && preAllocCount) {
142 fAllocCount = fReserveCount;
143 fMemArray = preAllocStorage;
144 } else {
145 fAllocCount = GrMax(fCount, fReserveCount);
146 fMemArray = GrMalloc(fAllocCount * sizeof(T));
147 }
148
149 if (DATA_TYPE) {
150 memcpy(fMemArray, array, sizeof(T) * fCount);
151 } else {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000152 for (int i = 0; i < fCount; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000153 new (fItemArray + i) T(array[i]);
154 }
155 }
156 }
157
158 GrTArray& operator =(const GrTArray& array) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000159 for (int i = 0; i < fCount; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000160 fItemArray[i].~T();
161 }
162 fCount = 0;
163 checkRealloc((int)array.count());
164 fCount = array.count();
165 if (DATA_TYPE) {
166 memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
167 } else {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000168 for (int i = 0; i < fCount; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000169 new (fItemArray + i) T(array[i]);
170 }
171 }
172 return *this;
173 }
174
175 ~GrTArray() {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000176 for (int i = 0; i < fCount; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000177 fItemArray[i].~T();
178 }
179 if (fMemArray != fPreAllocMemArray) {
180 GrFree(fMemArray);
181 }
182 }
183
bsalomon@google.comd302f142011-03-03 13:54:13 +0000184 void reset() { this->pop_back_n(fCount); }
185
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000186 int count() const { return fCount; }
reed@google.comac10a2d2010-12-22 21:39:39 +0000187
188 bool empty() const { return !fCount; }
189
190 T& push_back() {
191 checkRealloc(1);
192 new ((char*)fMemArray+sizeof(T)*fCount) T;
193 ++fCount;
194 return fItemArray[fCount-1];
195 }
196
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000197 void push_back_n(int n) {
198 GrAssert(n >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000199 checkRealloc(n);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000200 for (int i = 0; i < n; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000201 new (fItemArray + fCount + i) T;
202 }
203 fCount += n;
204 }
205
206 void pop_back() {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000207 GrAssert(fCount > 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000208 --fCount;
209 fItemArray[fCount].~T();
210 checkRealloc(0);
211 }
212
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000213 void pop_back_n(int n) {
214 GrAssert(n >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000215 GrAssert(fCount >= n);
216 fCount -= n;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000217 for (int i = 0; i < n; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000218 fItemArray[i].~T();
219 }
220 checkRealloc(0);
221 }
222
223 // pushes or pops from the back to resize
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000224 void resize_back(int newCount) {
225 GrAssert(newCount >= 0);
226
reed@google.comac10a2d2010-12-22 21:39:39 +0000227 if (newCount > fCount) {
228 push_back_n(newCount - fCount);
229 } else if (newCount < fCount) {
230 pop_back_n(fCount - newCount);
231 }
232 }
233
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000234 T& operator[] (int i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000235 GrAssert(i < fCount);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000236 GrAssert(i >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000237 return fItemArray[i];
238 }
239
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000240 const T& operator[] (int i) const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000241 GrAssert(i < fCount);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000242 GrAssert(i >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000243 return fItemArray[i];
244 }
245
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000246 T& front() { GrAssert(fCount > 0); return fItemArray[0];}
reed@google.comac10a2d2010-12-22 21:39:39 +0000247
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000248 const T& front() const { GrAssert(fCount > 0); return fItemArray[0];}
reed@google.comac10a2d2010-12-22 21:39:39 +0000249
250 T& back() { GrAssert(fCount); return fItemArray[fCount - 1];}
251
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000252 const T& back() const { GrAssert(fCount > 0); return fItemArray[fCount - 1];}
reed@google.comac10a2d2010-12-22 21:39:39 +0000253
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000254 T& fromBack(int i) {
255 GrAssert(i >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000256 GrAssert(i < fCount);
257 return fItemArray[fCount - i - 1];
258 }
259
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000260 const T& fromBack(int i) const {
261 GrAssert(i >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000262 GrAssert(i < fCount);
263 return fItemArray[fCount - i - 1];
264 }
265
266private:
reed@google.comac10a2d2010-12-22 21:39:39 +0000267
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000268 static const int MIN_ALLOC_COUNT = 8;
reed@google.comac10a2d2010-12-22 21:39:39 +0000269
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000270 inline void checkRealloc(int delta) {
271 GrAssert(fCount >= 0);
272 GrAssert(fAllocCount >= 0);
273
274 GrAssert(-delta <= fCount);
275
276 int newCount = fCount + delta;
277 int fNewAllocCount = fAllocCount;
reed@google.comac10a2d2010-12-22 21:39:39 +0000278
279 if (newCount > fAllocCount) {
280 fNewAllocCount = GrMax(newCount + ((newCount + 1) >> 1),
281 fReserveCount);
282 } else if (newCount < fAllocCount / 3) {
283 fNewAllocCount = GrMax(fAllocCount / 2, fReserveCount);
284 }
285
286 if (fNewAllocCount != fAllocCount) {
287
288 fAllocCount = fNewAllocCount;
289 char* fNewMemArray;
290
291 if (fAllocCount == fReserveCount && NULL != fPreAllocMemArray) {
292 fNewMemArray = (char*) fPreAllocMemArray;
293 } else {
294 fNewMemArray = (char*) GrMalloc(fAllocCount*sizeof(T));
295 }
296
297 if (DATA_TYPE) {
298 memcpy(fNewMemArray, fMemArray, fCount * sizeof(T));
299 } else {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000300 for (int i = 0; i < fCount; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000301 new (fNewMemArray + sizeof(T) * i) T(fItemArray[i]);
302 fItemArray[i].~T();
303 }
304 }
305
306 if (fMemArray != fPreAllocMemArray) {
307 GrFree(fMemArray);
308 }
309 fMemArray = fNewMemArray;
310 }
311 }
312
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000313 int fReserveCount;
314 int fCount;
315 int fAllocCount;
reed@google.comac10a2d2010-12-22 21:39:39 +0000316 void* fPreAllocMemArray;
317 union {
318 T* fItemArray;
319 void* fMemArray;
320 };
321};
322
323#endif
324