blob: 821424b869ea8d84ecce03d2615f81766620655d [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
2 Copyright 2010 Google Inc.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17
18#ifndef GrTArray_DEFINED
19#define GrTArray_DEFINED
20
21#include <new>
22#include "GrTypes.h"
bsalomon@google.coma55847b2011-04-20 15:47:04 +000023#include "GrTemplates.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000024
reed@google.comac10a2d2010-12-22 21:39:39 +000025// DATA_TYPE indicates that T has a trivial cons, destructor
26// and can be shallow-copied
27template <typename T, bool DATA_TYPE = false> class GrTArray {
28public:
29 GrTArray() {
30 fCount = 0;
31 fReserveCount = MIN_ALLOC_COUNT;
32 fAllocCount = 0;
33 fMemArray = NULL;
34 fPreAllocMemArray = NULL;
35 }
36
bsalomon@google.com1c13c962011-02-14 16:51:21 +000037 explicit GrTArray(int reserveCount) {
38 GrAssert(reserveCount >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +000039 fCount = 0;
bsalomon@google.com1c13c962011-02-14 16:51:21 +000040 fReserveCount = reserveCount > MIN_ALLOC_COUNT ? reserveCount :
41 MIN_ALLOC_COUNT;
reed@google.comac10a2d2010-12-22 21:39:39 +000042 fAllocCount = fReserveCount;
43 fMemArray = GrMalloc(sizeof(T) * fReserveCount);
44 fPreAllocMemArray = NULL;
45 }
46
bsalomon@google.coma55847b2011-04-20 15:47:04 +000047 template <int N>
48 GrTArray(GrAlignedSTStorage<N,T>* storage) {
49 GrAssert(N > 0);
50 fCount = 0;
51 fReserveCount = N;
52 fAllocCount = N;
53 fMemArray = storage->get();
54 fPreAllocMemArray = storage->get();
55 }
56
bsalomon@google.com1c13c962011-02-14 16:51:21 +000057 GrTArray(void* preAllocStorage, int preAllocCount) {
58 GrAssert(preAllocCount >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +000059 // we allow NULL,0 args and revert to the default cons. behavior
60 // this makes it possible for a owner-object to use same constructor
61 // to get either prealloc or nonprealloc behavior based using same line
62 GrAssert((NULL == preAllocStorage) == !preAllocCount);
63
64 fCount = 0;
65 fReserveCount = preAllocCount > 0 ? preAllocCount :
66 MIN_ALLOC_COUNT;
67 fAllocCount = preAllocCount;
68 fMemArray = preAllocStorage;
69 fPreAllocMemArray = preAllocStorage;
70 }
71
bsalomon@google.com1c13c962011-02-14 16:51:21 +000072 explicit GrTArray(const GrTArray& array) {
reed@google.comac10a2d2010-12-22 21:39:39 +000073 fCount = array.count();
74 fReserveCount = MIN_ALLOC_COUNT;
75 fAllocCount = GrMax(fReserveCount, fCount);
76 fMemArray = GrMalloc(sizeof(T) * fAllocCount);
77 fPreAllocMemArray = NULL;
bsalomon@google.coma55847b2011-04-20 15:47:04 +000078
reed@google.comac10a2d2010-12-22 21:39:39 +000079 if (DATA_TYPE) {
80 memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
81 } else {
bsalomon@google.com1c13c962011-02-14 16:51:21 +000082 for (int i = 0; i < fCount; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +000083 new (fItemArray + i) T(array[i]);
84 }
85 }
86 }
87
bsalomon@google.com1c13c962011-02-14 16:51:21 +000088 GrTArray(const T* array, int count) {
89 GrAssert(count >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +000090 fCount = count;
91 fReserveCount = MIN_ALLOC_COUNT;
92 fAllocCount = GrMax(fReserveCount, fCount);
93 fMemArray = GrMalloc(sizeof(T) * fAllocCount);
94 fPreAllocMemArray = NULL;
95 if (DATA_TYPE) {
96 memcpy(fMemArray, array, sizeof(T) * fCount);
97 } else {
bsalomon@google.com1c13c962011-02-14 16:51:21 +000098 for (int i = 0; i < fCount; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +000099 new (fItemArray + i) T(array[i]);
100 }
101 }
102 }
103
104 GrTArray(const GrTArray& array,
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000105 void* preAllocStorage, int preAllocCount) {
106
107 GrAssert(preAllocCount >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000108
109 // for same reason as non-copying cons we allow NULL, 0 for prealloc
110 GrAssert((NULL == preAllocStorage) == !preAllocCount);
111
112 fCount = array.count();
113 fReserveCount = preAllocCount > 0 ? preAllocCount :
114 MIN_ALLOC_COUNT;
115 fPreAllocMemArray = preAllocStorage;
116
117 if (fReserveCount >= fCount && preAllocCount) {
118 fAllocCount = fReserveCount;
119 fMemArray = preAllocStorage;
120 } else {
121 fAllocCount = GrMax(fCount, fReserveCount);
122 fMemArray = GrMalloc(fAllocCount * sizeof(T));
123 }
124
125 if (DATA_TYPE) {
126 memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
127 } else {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000128 for (int i = 0; i < fCount; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000129 new (fItemArray + i) T(array[i]);
130 }
131 }
132 }
133
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000134 GrTArray(const T* array, int count,
135 void* preAllocStorage, int preAllocCount) {
136
137 GrAssert(count >= 0);
138 GrAssert(preAllocCount >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000139
140 // for same reason as non-copying cons we allow NULL, 0 for prealloc
141 GrAssert((NULL == preAllocStorage) == !preAllocCount);
142
143 fCount = count;
144 fReserveCount = (preAllocCount > 0) ? preAllocCount :
145 MIN_ALLOC_COUNT;
146 fPreAllocMemArray = preAllocStorage;
147
148 if (fReserveCount >= fCount && preAllocCount) {
149 fAllocCount = fReserveCount;
150 fMemArray = preAllocStorage;
151 } else {
152 fAllocCount = GrMax(fCount, fReserveCount);
153 fMemArray = GrMalloc(fAllocCount * sizeof(T));
154 }
155
156 if (DATA_TYPE) {
157 memcpy(fMemArray, array, sizeof(T) * fCount);
158 } else {
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 new (fItemArray + i) T(array[i]);
161 }
162 }
163 }
164
165 GrTArray& operator =(const GrTArray& array) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000166 for (int i = 0; i < fCount; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000167 fItemArray[i].~T();
168 }
169 fCount = 0;
170 checkRealloc((int)array.count());
171 fCount = array.count();
172 if (DATA_TYPE) {
173 memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
174 } else {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000175 for (int i = 0; i < fCount; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000176 new (fItemArray + i) T(array[i]);
177 }
178 }
179 return *this;
180 }
181
182 ~GrTArray() {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000183 for (int i = 0; i < fCount; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000184 fItemArray[i].~T();
185 }
186 if (fMemArray != fPreAllocMemArray) {
187 GrFree(fMemArray);
188 }
189 }
190
bsalomon@google.comd302f142011-03-03 13:54:13 +0000191 void reset() { this->pop_back_n(fCount); }
192
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000193 int count() const { return fCount; }
reed@google.comac10a2d2010-12-22 21:39:39 +0000194
195 bool empty() const { return !fCount; }
196
197 T& push_back() {
198 checkRealloc(1);
199 new ((char*)fMemArray+sizeof(T)*fCount) T;
200 ++fCount;
201 return fItemArray[fCount-1];
202 }
203
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000204 void push_back_n(int n) {
205 GrAssert(n >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000206 checkRealloc(n);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000207 for (int i = 0; i < n; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000208 new (fItemArray + fCount + i) T;
209 }
210 fCount += n;
211 }
212
213 void pop_back() {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000214 GrAssert(fCount > 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000215 --fCount;
216 fItemArray[fCount].~T();
217 checkRealloc(0);
218 }
219
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000220 void pop_back_n(int n) {
221 GrAssert(n >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000222 GrAssert(fCount >= n);
223 fCount -= n;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000224 for (int i = 0; i < n; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000225 fItemArray[i].~T();
226 }
227 checkRealloc(0);
228 }
229
230 // pushes or pops from the back to resize
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000231 void resize_back(int newCount) {
232 GrAssert(newCount >= 0);
233
reed@google.comac10a2d2010-12-22 21:39:39 +0000234 if (newCount > fCount) {
235 push_back_n(newCount - fCount);
236 } else if (newCount < fCount) {
237 pop_back_n(fCount - newCount);
238 }
239 }
240
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000241 T& operator[] (int i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000242 GrAssert(i < fCount);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000243 GrAssert(i >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000244 return fItemArray[i];
245 }
246
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000247 const T& operator[] (int i) const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000248 GrAssert(i < fCount);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000249 GrAssert(i >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000250 return fItemArray[i];
251 }
252
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000253 T& front() { GrAssert(fCount > 0); return fItemArray[0];}
reed@google.comac10a2d2010-12-22 21:39:39 +0000254
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000255 const T& front() const { GrAssert(fCount > 0); return fItemArray[0];}
reed@google.comac10a2d2010-12-22 21:39:39 +0000256
257 T& back() { GrAssert(fCount); return fItemArray[fCount - 1];}
258
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000259 const T& back() const { GrAssert(fCount > 0); return fItemArray[fCount - 1];}
reed@google.comac10a2d2010-12-22 21:39:39 +0000260
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000261 T& fromBack(int i) {
262 GrAssert(i >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000263 GrAssert(i < fCount);
264 return fItemArray[fCount - i - 1];
265 }
266
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000267 const T& fromBack(int i) const {
268 GrAssert(i >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000269 GrAssert(i < fCount);
270 return fItemArray[fCount - i - 1];
271 }
272
273private:
reed@google.comac10a2d2010-12-22 21:39:39 +0000274
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000275 static const int MIN_ALLOC_COUNT = 8;
reed@google.comac10a2d2010-12-22 21:39:39 +0000276
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000277 inline void checkRealloc(int delta) {
278 GrAssert(fCount >= 0);
279 GrAssert(fAllocCount >= 0);
280
281 GrAssert(-delta <= fCount);
282
283 int newCount = fCount + delta;
284 int fNewAllocCount = fAllocCount;
reed@google.comac10a2d2010-12-22 21:39:39 +0000285
286 if (newCount > fAllocCount) {
287 fNewAllocCount = GrMax(newCount + ((newCount + 1) >> 1),
288 fReserveCount);
289 } else if (newCount < fAllocCount / 3) {
290 fNewAllocCount = GrMax(fAllocCount / 2, fReserveCount);
291 }
292
293 if (fNewAllocCount != fAllocCount) {
294
295 fAllocCount = fNewAllocCount;
296 char* fNewMemArray;
297
298 if (fAllocCount == fReserveCount && NULL != fPreAllocMemArray) {
299 fNewMemArray = (char*) fPreAllocMemArray;
300 } else {
301 fNewMemArray = (char*) GrMalloc(fAllocCount*sizeof(T));
302 }
303
304 if (DATA_TYPE) {
305 memcpy(fNewMemArray, fMemArray, fCount * sizeof(T));
306 } else {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000307 for (int i = 0; i < fCount; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000308 new (fNewMemArray + sizeof(T) * i) T(fItemArray[i]);
309 fItemArray[i].~T();
310 }
311 }
312
313 if (fMemArray != fPreAllocMemArray) {
314 GrFree(fMemArray);
315 }
316 fMemArray = fNewMemArray;
317 }
318 }
319
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000320 int fReserveCount;
321 int fCount;
322 int fAllocCount;
reed@google.comac10a2d2010-12-22 21:39:39 +0000323 void* fPreAllocMemArray;
324 union {
325 T* fItemArray;
326 void* fMemArray;
327 };
328};
329
330#endif
331