blob: f0d94943a9b269d6baf5e232e69ab7d5bb6617fe [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
24// TODO: convert from uint32_t to int.
25
26// DATA_TYPE indicates that T has a trivial cons, destructor
27// and can be shallow-copied
28template <typename T, bool DATA_TYPE = false> class GrTArray {
29public:
30 GrTArray() {
31 fCount = 0;
32 fReserveCount = MIN_ALLOC_COUNT;
33 fAllocCount = 0;
34 fMemArray = NULL;
35 fPreAllocMemArray = NULL;
36 }
37
38 GrTArray(uint32_t reserveCount) {
39 fCount = 0;
40 fReserveCount = GrMax(reserveCount, (uint32_t)MIN_ALLOC_COUNT);
41 fAllocCount = fReserveCount;
42 fMemArray = GrMalloc(sizeof(T) * fReserveCount);
43 fPreAllocMemArray = NULL;
44 }
45
46 GrTArray(void* preAllocStorage, uint32_t preAllocCount) {
47 // we allow NULL,0 args and revert to the default cons. behavior
48 // this makes it possible for a owner-object to use same constructor
49 // to get either prealloc or nonprealloc behavior based using same line
50 GrAssert((NULL == preAllocStorage) == !preAllocCount);
51
52 fCount = 0;
53 fReserveCount = preAllocCount > 0 ? preAllocCount :
54 MIN_ALLOC_COUNT;
55 fAllocCount = preAllocCount;
56 fMemArray = preAllocStorage;
57 fPreAllocMemArray = preAllocStorage;
58 }
59
60 GrTArray(const GrTArray& array) {
61 fCount = array.count();
62 fReserveCount = MIN_ALLOC_COUNT;
63 fAllocCount = GrMax(fReserveCount, fCount);
64 fMemArray = GrMalloc(sizeof(T) * fAllocCount);
65 fPreAllocMemArray = NULL;
66 if (DATA_TYPE) {
67 memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
68 } else {
69 for (uint32_t i = 0; i < fCount; ++i) {
70 new (fItemArray + i) T(array[i]);
71 }
72 }
73 }
74
75 GrTArray(const T* array, uint32_t count) {
76 fCount = count;
77 fReserveCount = MIN_ALLOC_COUNT;
78 fAllocCount = GrMax(fReserveCount, fCount);
79 fMemArray = GrMalloc(sizeof(T) * fAllocCount);
80 fPreAllocMemArray = NULL;
81 if (DATA_TYPE) {
82 memcpy(fMemArray, array, sizeof(T) * fCount);
83 } else {
84 for (uint32_t i = 0; i < fCount; ++i) {
85 new (fItemArray + i) T(array[i]);
86 }
87 }
88 }
89
90 GrTArray(const GrTArray& array,
91 void* preAllocStorage, uint32_t preAllocCount) {
92
93 // for same reason as non-copying cons we allow NULL, 0 for prealloc
94 GrAssert((NULL == preAllocStorage) == !preAllocCount);
95
96 fCount = array.count();
97 fReserveCount = preAllocCount > 0 ? preAllocCount :
98 MIN_ALLOC_COUNT;
99 fPreAllocMemArray = preAllocStorage;
100
101 if (fReserveCount >= fCount && preAllocCount) {
102 fAllocCount = fReserveCount;
103 fMemArray = preAllocStorage;
104 } else {
105 fAllocCount = GrMax(fCount, fReserveCount);
106 fMemArray = GrMalloc(fAllocCount * sizeof(T));
107 }
108
109 if (DATA_TYPE) {
110 memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
111 } else {
112 for (uint32_t i = 0; i < fCount; ++i) {
113 new (fItemArray + i) T(array[i]);
114 }
115 }
116 }
117
118 GrTArray(const T* array, uint32_t count,
119 void* preAllocStorage, uint32_t preAllocCount) {
120
121 // for same reason as non-copying cons we allow NULL, 0 for prealloc
122 GrAssert((NULL == preAllocStorage) == !preAllocCount);
123
124 fCount = count;
125 fReserveCount = (preAllocCount > 0) ? preAllocCount :
126 MIN_ALLOC_COUNT;
127 fPreAllocMemArray = preAllocStorage;
128
129 if (fReserveCount >= fCount && preAllocCount) {
130 fAllocCount = fReserveCount;
131 fMemArray = preAllocStorage;
132 } else {
133 fAllocCount = GrMax(fCount, fReserveCount);
134 fMemArray = GrMalloc(fAllocCount * sizeof(T));
135 }
136
137 if (DATA_TYPE) {
138 memcpy(fMemArray, array, sizeof(T) * fCount);
139 } else {
140 for (uint32_t i = 0; i < fCount; ++i) {
141 new (fItemArray + i) T(array[i]);
142 }
143 }
144 }
145
146 GrTArray& operator =(const GrTArray& array) {
147 for (uint32_t i = 0; i < fCount; ++i) {
148 fItemArray[i].~T();
149 }
150 fCount = 0;
151 checkRealloc((int)array.count());
152 fCount = array.count();
153 if (DATA_TYPE) {
154 memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
155 } else {
156 for (uint32_t i = 0; i < fCount; ++i) {
157 new (fItemArray + i) T(array[i]);
158 }
159 }
160 return *this;
161 }
162
163 ~GrTArray() {
164 for (uint32_t i = 0; i < fCount; ++i) {
165 fItemArray[i].~T();
166 }
167 if (fMemArray != fPreAllocMemArray) {
168 GrFree(fMemArray);
169 }
170 }
171
172 uint32_t count() const { return fCount; }
173
174 bool empty() const { return !fCount; }
175
176 T& push_back() {
177 checkRealloc(1);
178 new ((char*)fMemArray+sizeof(T)*fCount) T;
179 ++fCount;
180 return fItemArray[fCount-1];
181 }
182
183 void push_back_n(uint32_t n) {
184 checkRealloc(n);
185 for (uint32_t i = 0; i < n; ++i) {
186 new (fItemArray + fCount + i) T;
187 }
188 fCount += n;
189 }
190
191 void pop_back() {
192 GrAssert(0 != fCount);
193 --fCount;
194 fItemArray[fCount].~T();
195 checkRealloc(0);
196 }
197
198 void pop_back_n(uint32_t n) {
199 GrAssert(fCount >= n);
200 fCount -= n;
201 for (uint32_t i = 0; i < n; ++i) {
202 fItemArray[i].~T();
203 }
204 checkRealloc(0);
205 }
206
207 // pushes or pops from the back to resize
208 void resize_back(uint32_t newCount) {
209 if (newCount > fCount) {
210 push_back_n(newCount - fCount);
211 } else if (newCount < fCount) {
212 pop_back_n(fCount - newCount);
213 }
214 }
215
216 T& operator[] (uint32_t i) {
217 GrAssert(i < fCount);
218 return fItemArray[i];
219 }
220
221 const T& operator[] (uint32_t i) const {
222 GrAssert(i < fCount);
223 return fItemArray[i];
224 }
225
226 T& front() { GrAssert(fCount); return fItemArray[0];}
227
228 const T& front() const { GrAssert(fCount); return fItemArray[0];}
229
230 T& back() { GrAssert(fCount); return fItemArray[fCount - 1];}
231
232 const T& back() const { GrAssert(fCount); return fItemArray[fCount - 1];}
233
234 T& fromBack(uint32_t i) {
235 GrAssert(i < fCount);
236 return fItemArray[fCount - i - 1];
237 }
238
239 const T& fromBack(uint32_t i) const {
240 GrAssert(i < fCount);
241 return fItemArray[fCount - i - 1];
242 }
243
244private:
245 static const uint32_t MIN_ALLOC_COUNT = 8;
246
247 inline void checkRealloc(int32_t delta) {
248 GrAssert(-delta <= (int32_t)fCount);
249
250 uint32_t newCount = fCount + delta;
251 uint32_t fNewAllocCount = fAllocCount;
252
253 if (newCount > fAllocCount) {
254 fNewAllocCount = GrMax(newCount + ((newCount + 1) >> 1),
255 fReserveCount);
256 } else if (newCount < fAllocCount / 3) {
257 fNewAllocCount = GrMax(fAllocCount / 2, fReserveCount);
258 }
259
260 if (fNewAllocCount != fAllocCount) {
261
262 fAllocCount = fNewAllocCount;
263 char* fNewMemArray;
264
265 if (fAllocCount == fReserveCount && NULL != fPreAllocMemArray) {
266 fNewMemArray = (char*) fPreAllocMemArray;
267 } else {
268 fNewMemArray = (char*) GrMalloc(fAllocCount*sizeof(T));
269 }
270
271 if (DATA_TYPE) {
272 memcpy(fNewMemArray, fMemArray, fCount * sizeof(T));
273 } else {
274 for (uint32_t i = 0; i < fCount; ++i) {
275 new (fNewMemArray + sizeof(T) * i) T(fItemArray[i]);
276 fItemArray[i].~T();
277 }
278 }
279
280 if (fMemArray != fPreAllocMemArray) {
281 GrFree(fMemArray);
282 }
283 fMemArray = fNewMemArray;
284 }
285 }
286
287 uint32_t fReserveCount;
288 uint32_t fCount;
289 uint32_t fAllocCount;
290 void* fPreAllocMemArray;
291 union {
292 T* fItemArray;
293 void* fMemArray;
294 };
295};
296
297#endif
298