blob: 6ef1a1355889e5395b050c6fd2c7a67c332c7eb8 [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.comd302f142011-03-03 13:54:13 +0000179 void reset() { this->pop_back_n(fCount); }
180
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000181 int count() const { return fCount; }
reed@google.comac10a2d2010-12-22 21:39:39 +0000182
183 bool empty() const { return !fCount; }
184
185 T& push_back() {
186 checkRealloc(1);
187 new ((char*)fMemArray+sizeof(T)*fCount) T;
188 ++fCount;
189 return fItemArray[fCount-1];
190 }
191
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000192 void push_back_n(int n) {
193 GrAssert(n >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000194 checkRealloc(n);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000195 for (int i = 0; i < n; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000196 new (fItemArray + fCount + i) T;
197 }
198 fCount += n;
199 }
200
201 void pop_back() {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000202 GrAssert(fCount > 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000203 --fCount;
204 fItemArray[fCount].~T();
205 checkRealloc(0);
206 }
207
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000208 void pop_back_n(int n) {
209 GrAssert(n >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000210 GrAssert(fCount >= n);
211 fCount -= n;
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000212 for (int i = 0; i < n; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000213 fItemArray[i].~T();
214 }
215 checkRealloc(0);
216 }
217
218 // pushes or pops from the back to resize
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000219 void resize_back(int newCount) {
220 GrAssert(newCount >= 0);
221
reed@google.comac10a2d2010-12-22 21:39:39 +0000222 if (newCount > fCount) {
223 push_back_n(newCount - fCount);
224 } else if (newCount < fCount) {
225 pop_back_n(fCount - newCount);
226 }
227 }
228
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000229 T& operator[] (int i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000230 GrAssert(i < fCount);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000231 GrAssert(i >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000232 return fItemArray[i];
233 }
234
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000235 const T& operator[] (int i) const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000236 GrAssert(i < fCount);
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000237 GrAssert(i >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000238 return fItemArray[i];
239 }
240
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000241 T& front() { GrAssert(fCount > 0); return fItemArray[0];}
reed@google.comac10a2d2010-12-22 21:39:39 +0000242
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000243 const T& front() const { GrAssert(fCount > 0); return fItemArray[0];}
reed@google.comac10a2d2010-12-22 21:39:39 +0000244
245 T& back() { GrAssert(fCount); return fItemArray[fCount - 1];}
246
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000247 const T& back() const { GrAssert(fCount > 0); return fItemArray[fCount - 1];}
reed@google.comac10a2d2010-12-22 21:39:39 +0000248
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000249 T& fromBack(int i) {
250 GrAssert(i >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000251 GrAssert(i < fCount);
252 return fItemArray[fCount - i - 1];
253 }
254
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000255 const T& fromBack(int i) const {
256 GrAssert(i >= 0);
reed@google.comac10a2d2010-12-22 21:39:39 +0000257 GrAssert(i < fCount);
258 return fItemArray[fCount - i - 1];
259 }
260
261private:
reed@google.comac10a2d2010-12-22 21:39:39 +0000262
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000263 static const int MIN_ALLOC_COUNT = 8;
reed@google.comac10a2d2010-12-22 21:39:39 +0000264
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000265 inline void checkRealloc(int delta) {
266 GrAssert(fCount >= 0);
267 GrAssert(fAllocCount >= 0);
268
269 GrAssert(-delta <= fCount);
270
271 int newCount = fCount + delta;
272 int fNewAllocCount = fAllocCount;
reed@google.comac10a2d2010-12-22 21:39:39 +0000273
274 if (newCount > fAllocCount) {
275 fNewAllocCount = GrMax(newCount + ((newCount + 1) >> 1),
276 fReserveCount);
277 } else if (newCount < fAllocCount / 3) {
278 fNewAllocCount = GrMax(fAllocCount / 2, fReserveCount);
279 }
280
281 if (fNewAllocCount != fAllocCount) {
282
283 fAllocCount = fNewAllocCount;
284 char* fNewMemArray;
285
286 if (fAllocCount == fReserveCount && NULL != fPreAllocMemArray) {
287 fNewMemArray = (char*) fPreAllocMemArray;
288 } else {
289 fNewMemArray = (char*) GrMalloc(fAllocCount*sizeof(T));
290 }
291
292 if (DATA_TYPE) {
293 memcpy(fNewMemArray, fMemArray, fCount * sizeof(T));
294 } else {
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000295 for (int i = 0; i < fCount; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000296 new (fNewMemArray + sizeof(T) * i) T(fItemArray[i]);
297 fItemArray[i].~T();
298 }
299 }
300
301 if (fMemArray != fPreAllocMemArray) {
302 GrFree(fMemArray);
303 }
304 fMemArray = fNewMemArray;
305 }
306 }
307
bsalomon@google.com1c13c962011-02-14 16:51:21 +0000308 int fReserveCount;
309 int fCount;
310 int fAllocCount;
reed@google.comac10a2d2010-12-22 21:39:39 +0000311 void* fPreAllocMemArray;
312 union {
313 T* fItemArray;
314 void* fMemArray;
315 };
316};
317
318#endif
319