blob: c31c820884db0aa673125840b6e39b0327840669 [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"
23
reed@google.comac10a2d2010-12-22 21:39:39 +000024// DATA_TYPE indicates that T has a trivial cons, destructor
25// and can be shallow-copied
26template <typename T, bool DATA_TYPE = false> class GrTArray {
27public:
28 GrTArray() {
29 fCount = 0;
30 fReserveCount = MIN_ALLOC_COUNT;
31 fAllocCount = 0;
32 fMemArray = NULL;
33 fPreAllocMemArray = NULL;
34 }
35
bsalomon@google.com1c13c962011-02-14 16:51:21 +000036 explicit GrTArray(int reserveCount) {
37 GrAssert(reserveCount >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +000038 fCount = 0;
bsalomon@google.com1c13c962011-02-14 16:51:21 +000039 fReserveCount = reserveCount > MIN_ALLOC_COUNT ? reserveCount :
40 MIN_ALLOC_COUNT;
reed@google.comac10a2d2010-12-22 21:39:39 +000041 fAllocCount = fReserveCount;
42 fMemArray = GrMalloc(sizeof(T) * fReserveCount);
43 fPreAllocMemArray = NULL;
44 }
45
bsalomon@google.com1c13c962011-02-14 16:51:21 +000046 GrTArray(void* preAllocStorage, int preAllocCount) {
47 GrAssert(preAllocCount >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +000048 // we allow NULL,0 args and revert to the default cons. behavior
49 // this makes it possible for a owner-object to use same constructor
50 // to get either prealloc or nonprealloc behavior based using same line
51 GrAssert((NULL == preAllocStorage) == !preAllocCount);
52
53 fCount = 0;
54 fReserveCount = preAllocCount > 0 ? preAllocCount :
55 MIN_ALLOC_COUNT;
56 fAllocCount = preAllocCount;
57 fMemArray = preAllocStorage;
58 fPreAllocMemArray = preAllocStorage;
59 }
60
bsalomon@google.com1c13c962011-02-14 16:51:21 +000061 explicit GrTArray(const GrTArray& array) {
reed@google.comac10a2d2010-12-22 21:39:39 +000062 fCount = array.count();
63 fReserveCount = MIN_ALLOC_COUNT;
64 fAllocCount = GrMax(fReserveCount, fCount);
65 fMemArray = GrMalloc(sizeof(T) * fAllocCount);
66 fPreAllocMemArray = NULL;
67 if (DATA_TYPE) {
68 memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
69 } else {
bsalomon@google.com1c13c962011-02-14 16:51:21 +000070 for (int i = 0; i < fCount; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +000071 new (fItemArray + i) T(array[i]);
72 }
73 }
74 }
75
bsalomon@google.com1c13c962011-02-14 16:51:21 +000076 GrTArray(const T* array, int count) {
77 GrAssert(count >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +000078 fCount = count;
79 fReserveCount = MIN_ALLOC_COUNT;
80 fAllocCount = GrMax(fReserveCount, fCount);
81 fMemArray = GrMalloc(sizeof(T) * fAllocCount);
82 fPreAllocMemArray = NULL;
83 if (DATA_TYPE) {
84 memcpy(fMemArray, array, sizeof(T) * fCount);
85 } else {
bsalomon@google.com1c13c962011-02-14 16:51:21 +000086 for (int i = 0; i < fCount; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +000087 new (fItemArray + i) T(array[i]);
88 }
89 }
90 }
91
92 GrTArray(const GrTArray& array,
bsalomon@google.com1c13c962011-02-14 16:51:21 +000093 void* preAllocStorage, int preAllocCount) {
94
95 GrAssert(preAllocCount >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +000096
97 // for same reason as non-copying cons we allow NULL, 0 for prealloc
98 GrAssert((NULL == preAllocStorage) == !preAllocCount);
99
100 fCount = array.count();
101 fReserveCount = preAllocCount > 0 ? preAllocCount :
102 MIN_ALLOC_COUNT;
103 fPreAllocMemArray = preAllocStorage;
104
105 if (fReserveCount >= fCount && preAllocCount) {
106 fAllocCount = fReserveCount;
107 fMemArray = preAllocStorage;
108 } else {
109 fAllocCount = GrMax(fCount, fReserveCount);
110 fMemArray = GrMalloc(fAllocCount * sizeof(T));
111 }
112
113 if (DATA_TYPE) {
114 memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
115 } else {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000116 for (int i = 0; i < fCount; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000117 new (fItemArray + i) T(array[i]);
118 }
119 }
120 }
121
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000122 GrTArray(const T* array, int count,
123 void* preAllocStorage, int preAllocCount) {
124
125 GrAssert(count >= 0);
126 GrAssert(preAllocCount >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000127
128 // for same reason as non-copying cons we allow NULL, 0 for prealloc
129 GrAssert((NULL == preAllocStorage) == !preAllocCount);
130
131 fCount = count;
132 fReserveCount = (preAllocCount > 0) ? preAllocCount :
133 MIN_ALLOC_COUNT;
134 fPreAllocMemArray = preAllocStorage;
135
136 if (fReserveCount >= fCount && preAllocCount) {
137 fAllocCount = fReserveCount;
138 fMemArray = preAllocStorage;
139 } else {
140 fAllocCount = GrMax(fCount, fReserveCount);
141 fMemArray = GrMalloc(fAllocCount * sizeof(T));
142 }
143
144 if (DATA_TYPE) {
145 memcpy(fMemArray, array, sizeof(T) * fCount);
146 } else {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000147 for (int i = 0; i < fCount; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000148 new (fItemArray + i) T(array[i]);
149 }
150 }
151 }
152
153 GrTArray& operator =(const GrTArray& array) {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000154 for (int i = 0; i < fCount; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000155 fItemArray[i].~T();
156 }
157 fCount = 0;
158 checkRealloc((int)array.count());
159 fCount = array.count();
160 if (DATA_TYPE) {
161 memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
162 } else {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000163 for (int i = 0; i < fCount; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000164 new (fItemArray + i) T(array[i]);
165 }
166 }
167 return *this;
168 }
169
170 ~GrTArray() {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000171 for (int i = 0; i < fCount; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000172 fItemArray[i].~T();
173 }
174 if (fMemArray != fPreAllocMemArray) {
175 GrFree(fMemArray);
176 }
177 }
178
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000179 int count() const { return fCount; }
reed@google.comac10a2d2010-12-22 21:39:39 +0000180
181 bool empty() const { return !fCount; }
182
183 T& push_back() {
184 checkRealloc(1);
185 new ((char*)fMemArray+sizeof(T)*fCount) T;
186 ++fCount;
187 return fItemArray[fCount-1];
188 }
189
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000190 void push_back_n(int n) {
191 GrAssert(n >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000192 checkRealloc(n);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000193 for (int i = 0; i < n; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000194 new (fItemArray + fCount + i) T;
195 }
196 fCount += n;
197 }
198
199 void pop_back() {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000200 GrAssert(fCount > 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000201 --fCount;
202 fItemArray[fCount].~T();
203 checkRealloc(0);
204 }
205
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000206 void pop_back_n(int n) {
207 GrAssert(n >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000208 GrAssert(fCount >= n);
209 fCount -= n;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000210 for (int i = 0; i < n; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000211 fItemArray[i].~T();
212 }
213 checkRealloc(0);
214 }
215
216 // pushes or pops from the back to resize
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000217 void resize_back(int newCount) {
218 GrAssert(newCount >= 0);
219
reed@google.comac10a2d2010-12-22 21:39:39 +0000220 if (newCount > fCount) {
221 push_back_n(newCount - fCount);
222 } else if (newCount < fCount) {
223 pop_back_n(fCount - newCount);
224 }
225 }
226
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000227 T& operator[] (int i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000228 GrAssert(i < fCount);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000229 GrAssert(i >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000230 return fItemArray[i];
231 }
232
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000233 const T& operator[] (int i) const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000234 GrAssert(i < fCount);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000235 GrAssert(i >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000236 return fItemArray[i];
237 }
238
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000239 T& front() { GrAssert(fCount > 0); return fItemArray[0];}
reed@google.comac10a2d2010-12-22 21:39:39 +0000240
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000241 const T& front() const { GrAssert(fCount > 0); return fItemArray[0];}
reed@google.comac10a2d2010-12-22 21:39:39 +0000242
243 T& back() { GrAssert(fCount); return fItemArray[fCount - 1];}
244
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000245 const T& back() const { GrAssert(fCount > 0); return fItemArray[fCount - 1];}
reed@google.comac10a2d2010-12-22 21:39:39 +0000246
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000247 T& fromBack(int i) {
248 GrAssert(i >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000249 GrAssert(i < fCount);
250 return fItemArray[fCount - i - 1];
251 }
252
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000253 const T& fromBack(int i) const {
254 GrAssert(i >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000255 GrAssert(i < fCount);
256 return fItemArray[fCount - i - 1];
257 }
258
259private:
reed@google.comac10a2d2010-12-22 21:39:39 +0000260
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000261 static const int MIN_ALLOC_COUNT = 8;
reed@google.comac10a2d2010-12-22 21:39:39 +0000262
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000263 inline void checkRealloc(int delta) {
264 GrAssert(fCount >= 0);
265 GrAssert(fAllocCount >= 0);
266
267 GrAssert(-delta <= fCount);
268
269 int newCount = fCount + delta;
270 int fNewAllocCount = fAllocCount;
reed@google.comac10a2d2010-12-22 21:39:39 +0000271
272 if (newCount > fAllocCount) {
273 fNewAllocCount = GrMax(newCount + ((newCount + 1) >> 1),
274 fReserveCount);
275 } else if (newCount < fAllocCount / 3) {
276 fNewAllocCount = GrMax(fAllocCount / 2, fReserveCount);
277 }
278
279 if (fNewAllocCount != fAllocCount) {
280
281 fAllocCount = fNewAllocCount;
282 char* fNewMemArray;
283
284 if (fAllocCount == fReserveCount && NULL != fPreAllocMemArray) {
285 fNewMemArray = (char*) fPreAllocMemArray;
286 } else {
287 fNewMemArray = (char*) GrMalloc(fAllocCount*sizeof(T));
288 }
289
290 if (DATA_TYPE) {
291 memcpy(fNewMemArray, fMemArray, fCount * sizeof(T));
292 } else {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000293 for (int i = 0; i < fCount; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000294 new (fNewMemArray + sizeof(T) * i) T(fItemArray[i]);
295 fItemArray[i].~T();
296 }
297 }
298
299 if (fMemArray != fPreAllocMemArray) {
300 GrFree(fMemArray);
301 }
302 fMemArray = fNewMemArray;
303 }
304 }
305
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000306 int fReserveCount;
307 int fCount;
308 int fAllocCount;
reed@google.comac10a2d2010-12-22 21:39:39 +0000309 void* fPreAllocMemArray;
310 union {
311 T* fItemArray;
312 void* fMemArray;
313 };
314};
315
316#endif
317