blob: 9d410c12ea6940dc404ee1563ec325c64d2584d7 [file] [log] [blame]
bsalomon@google.com49313f62011-09-14 13:54:05 +00001/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
bsalomon@google.com49313f62011-09-14 13:54:05 +00008#ifndef SkTArray_DEFINED
9#define SkTArray_DEFINED
10
11#include <new>
12#include "SkTypes.h"
13#include "SkTemplates.h"
14
bungeman@google.coma12cc7f2011-10-07 20:54:15 +000015template <typename T, bool MEM_COPY = false> class SkTArray;
16
17namespace SkTArrayExt {
18
19template<typename T>
bungeman@google.com95ebd172014-03-21 19:39:02 +000020inline void copy(SkTArray<T, true>* self, int dst, int src) {
21 memcpy(&self->fItemArray[dst], &self->fItemArray[src], sizeof(T));
22}
23template<typename T>
bungeman@google.coma12cc7f2011-10-07 20:54:15 +000024inline void copy(SkTArray<T, true>* self, const T* array) {
25 memcpy(self->fMemArray, array, self->fCount * sizeof(T));
26}
27template<typename T>
28inline void copyAndDelete(SkTArray<T, true>* self, char* newMemArray) {
29 memcpy(newMemArray, self->fMemArray, self->fCount * sizeof(T));
30}
31
32template<typename T>
bungeman@google.com95ebd172014-03-21 19:39:02 +000033inline void copy(SkTArray<T, false>* self, int dst, int src) {
34 SkNEW_PLACEMENT_ARGS(&self->fItemArray[dst], T, (self->fItemArray[src]));
35}
36template<typename T>
bungeman@google.coma12cc7f2011-10-07 20:54:15 +000037inline void copy(SkTArray<T, false>* self, const T* array) {
38 for (int i = 0; i < self->fCount; ++i) {
commit-bot@chromium.orgb4a8d972013-06-05 15:40:59 +000039 SkNEW_PLACEMENT_ARGS(self->fItemArray + i, T, (array[i]));
bungeman@google.coma12cc7f2011-10-07 20:54:15 +000040 }
41}
42template<typename T>
43inline void copyAndDelete(SkTArray<T, false>* self, char* newMemArray) {
44 for (int i = 0; i < self->fCount; ++i) {
commit-bot@chromium.orgb4a8d972013-06-05 15:40:59 +000045 SkNEW_PLACEMENT_ARGS(newMemArray + sizeof(T) * i, T, (self->fItemArray[i]));
bungeman@google.coma12cc7f2011-10-07 20:54:15 +000046 self->fItemArray[i].~T();
47 }
48}
49
50}
51
bsalomon@google.comd5104142013-06-13 15:13:46 +000052template <typename T, bool MEM_COPY> void* operator new(size_t, SkTArray<T, MEM_COPY>*, int);
53
bungeman@google.coma12cc7f2011-10-07 20:54:15 +000054/** When MEM_COPY is true T will be bit copied when moved.
55 When MEM_COPY is false, T will be copy constructed / destructed.
bungeman@google.comd58a8562014-03-24 15:55:01 +000056 In all cases T will be default-initialized on allocation,
bungeman@google.coma12cc7f2011-10-07 20:54:15 +000057 and its destructor will be called from this object's destructor.
58*/
59template <typename T, bool MEM_COPY> class SkTArray {
bsalomon@google.com49313f62011-09-14 13:54:05 +000060public:
61 /**
62 * Creates an empty array with no initial storage
63 */
64 SkTArray() {
65 fCount = 0;
66 fReserveCount = gMIN_ALLOC_COUNT;
67 fAllocCount = 0;
68 fMemArray = NULL;
69 fPreAllocMemArray = NULL;
70 }
71
72 /**
rmistry@google.comfbfcd562012-08-23 18:09:54 +000073 * Creates an empty array that will preallocate space for reserveCount
bsalomon@google.com49313f62011-09-14 13:54:05 +000074 * elements.
75 */
76 explicit SkTArray(int reserveCount) {
bsalomon@google.com92669012011-09-27 19:10:05 +000077 this->init(NULL, 0, NULL, reserveCount);
bsalomon@google.com49313f62011-09-14 13:54:05 +000078 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +000079
bsalomon@google.com49313f62011-09-14 13:54:05 +000080 /**
81 * Copies one array to another. The new array will be heap allocated.
82 */
83 explicit SkTArray(const SkTArray& array) {
bsalomon@google.com92669012011-09-27 19:10:05 +000084 this->init(array.fItemArray, array.fCount, NULL, 0);
bsalomon@google.com49313f62011-09-14 13:54:05 +000085 }
86
87 /**
rmistry@google.comfbfcd562012-08-23 18:09:54 +000088 * Creates a SkTArray by copying contents of a standard C array. The new
bsalomon@google.com49313f62011-09-14 13:54:05 +000089 * array will be heap allocated. Be careful not to use this constructor
90 * when you really want the (void*, int) version.
91 */
92 SkTArray(const T* array, int count) {
bsalomon@google.com92669012011-09-27 19:10:05 +000093 this->init(array, count, NULL, 0);
bsalomon@google.com49313f62011-09-14 13:54:05 +000094 }
95
96 /**
97 * assign copy of array to this
98 */
99 SkTArray& operator =(const SkTArray& array) {
100 for (int i = 0; i < fCount; ++i) {
101 fItemArray[i].~T();
102 }
103 fCount = 0;
bsalomon@google.comd5104142013-06-13 15:13:46 +0000104 this->checkRealloc((int)array.count());
bsalomon@google.com49313f62011-09-14 13:54:05 +0000105 fCount = array.count();
bungeman@google.coma12cc7f2011-10-07 20:54:15 +0000106 SkTArrayExt::copy(this, static_cast<const T*>(array.fMemArray));
bsalomon@google.com49313f62011-09-14 13:54:05 +0000107 return *this;
108 }
109
bsalomon@google.com92669012011-09-27 19:10:05 +0000110 virtual ~SkTArray() {
bsalomon@google.com49313f62011-09-14 13:54:05 +0000111 for (int i = 0; i < fCount; ++i) {
112 fItemArray[i].~T();
113 }
114 if (fMemArray != fPreAllocMemArray) {
115 sk_free(fMemArray);
116 }
117 }
118
119 /**
120 * Resets to count() == 0
121 */
122 void reset() { this->pop_back_n(fCount); }
123
124 /**
commit-bot@chromium.orgb4a8d972013-06-05 15:40:59 +0000125 * Resets to count() = n newly constructed T objects.
126 */
127 void reset(int n) {
128 SkASSERT(n >= 0);
129 for (int i = 0; i < fCount; ++i) {
130 fItemArray[i].~T();
131 }
132 // set fCount to 0 before calling checkRealloc so that no copy cons. are called.
133 fCount = 0;
134 this->checkRealloc(n);
135 fCount = n;
136 for (int i = 0; i < fCount; ++i) {
137 SkNEW_PLACEMENT(fItemArray + i, T);
138 }
139 }
140
141 /**
jvanverth@google.com054ae992013-04-01 20:06:51 +0000142 * Resets to a copy of a C array.
143 */
144 void reset(const T* array, int count) {
145 for (int i = 0; i < fCount; ++i) {
146 fItemArray[i].~T();
147 }
148 int delta = count - fCount;
149 this->checkRealloc(delta);
150 fCount = count;
bungeman@google.com95ebd172014-03-21 19:39:02 +0000151 SkTArrayExt::copy(this, array);
152 }
153
154 void removeShuffle(int n) {
155 SkASSERT(n < fCount);
156 int newCount = fCount - 1;
157 fCount = newCount;
158 fItemArray[n].~T();
159 if (n != newCount) {
160 SkTArrayExt::copy(this, n, newCount);
161 fItemArray[newCount].~T();
jvanverth@google.com054ae992013-04-01 20:06:51 +0000162 }
163 }
164
165 /**
bsalomon@google.com49313f62011-09-14 13:54:05 +0000166 * Number of elements in the array.
167 */
168 int count() const { return fCount; }
169
170 /**
171 * Is the array empty.
172 */
173 bool empty() const { return !fCount; }
174
175 /**
bungeman@google.comd58a8562014-03-24 15:55:01 +0000176 * Adds 1 new default-initialized T value and returns it by reference. Note
bsalomon@google.com49313f62011-09-14 13:54:05 +0000177 * the reference only remains valid until the next call that adds or removes
178 * elements.
179 */
180 T& push_back() {
bsalomon@google.comd5104142013-06-13 15:13:46 +0000181 T* newT = reinterpret_cast<T*>(this->push_back_raw(1));
182 SkNEW_PLACEMENT(newT, T);
183 return *newT;
bsalomon@google.com49313f62011-09-14 13:54:05 +0000184 }
185
186 /**
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000187 * Version of above that uses a copy constructor to initialize the new item
188 */
189 T& push_back(const T& t) {
bsalomon@google.comd5104142013-06-13 15:13:46 +0000190 T* newT = reinterpret_cast<T*>(this->push_back_raw(1));
191 SkNEW_PLACEMENT_ARGS(newT, T, (t));
192 return *newT;
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000193 }
194
195 /**
bungeman@google.comd58a8562014-03-24 15:55:01 +0000196 * Allocates n more default-initialized T values, and returns the address of
197 * the start of that new range. Note: this address is only valid until the
198 * next API call made on the array that might add or remove elements.
bsalomon@google.com49313f62011-09-14 13:54:05 +0000199 */
200 T* push_back_n(int n) {
201 SkASSERT(n >= 0);
bsalomon@google.comd5104142013-06-13 15:13:46 +0000202 T* newTs = reinterpret_cast<T*>(this->push_back_raw(n));
bsalomon@google.com49313f62011-09-14 13:54:05 +0000203 for (int i = 0; i < n; ++i) {
bsalomon@google.comd5104142013-06-13 15:13:46 +0000204 SkNEW_PLACEMENT(newTs + i, T);
bsalomon@google.com49313f62011-09-14 13:54:05 +0000205 }
bsalomon@google.comd5104142013-06-13 15:13:46 +0000206 return newTs;
bsalomon@google.com49313f62011-09-14 13:54:05 +0000207 }
208
209 /**
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000210 * Version of above that uses a copy constructor to initialize all n items
211 * to the same T.
212 */
213 T* push_back_n(int n, const T& t) {
214 SkASSERT(n >= 0);
bsalomon@google.comd5104142013-06-13 15:13:46 +0000215 T* newTs = reinterpret_cast<T*>(this->push_back_raw(n));
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000216 for (int i = 0; i < n; ++i) {
bsalomon@google.comd5104142013-06-13 15:13:46 +0000217 SkNEW_PLACEMENT_ARGS(newTs[i], T, (t));
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000218 }
bsalomon@google.comd5104142013-06-13 15:13:46 +0000219 return newTs;
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000220 }
221
222 /**
223 * Version of above that uses a copy constructor to initialize the n items
224 * to separate T values.
225 */
226 T* push_back_n(int n, const T t[]) {
227 SkASSERT(n >= 0);
commit-bot@chromium.orgb4a8d972013-06-05 15:40:59 +0000228 this->checkRealloc(n);
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000229 for (int i = 0; i < n; ++i) {
commit-bot@chromium.orgb4a8d972013-06-05 15:40:59 +0000230 SkNEW_PLACEMENT_ARGS(fItemArray + fCount + i, T, (t[i]));
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000231 }
232 fCount += n;
233 return fItemArray + fCount - n;
234 }
235
236 /**
bsalomon@google.com49313f62011-09-14 13:54:05 +0000237 * Removes the last element. Not safe to call when count() == 0.
238 */
239 void pop_back() {
240 SkASSERT(fCount > 0);
241 --fCount;
242 fItemArray[fCount].~T();
commit-bot@chromium.orgb4a8d972013-06-05 15:40:59 +0000243 this->checkRealloc(0);
bsalomon@google.com49313f62011-09-14 13:54:05 +0000244 }
245
246 /**
247 * Removes the last n elements. Not safe to call when count() < n.
248 */
249 void pop_back_n(int n) {
250 SkASSERT(n >= 0);
251 SkASSERT(fCount >= n);
252 fCount -= n;
253 for (int i = 0; i < n; ++i) {
bsalomon@google.comd5104142013-06-13 15:13:46 +0000254 fItemArray[fCount + i].~T();
bsalomon@google.com49313f62011-09-14 13:54:05 +0000255 }
commit-bot@chromium.orgb4a8d972013-06-05 15:40:59 +0000256 this->checkRealloc(0);
bsalomon@google.com49313f62011-09-14 13:54:05 +0000257 }
258
259 /**
260 * Pushes or pops from the back to resize. Pushes will be default
261 * initialized.
262 */
263 void resize_back(int newCount) {
264 SkASSERT(newCount >= 0);
265
266 if (newCount > fCount) {
commit-bot@chromium.orgb4a8d972013-06-05 15:40:59 +0000267 this->push_back_n(newCount - fCount);
bsalomon@google.com49313f62011-09-14 13:54:05 +0000268 } else if (newCount < fCount) {
commit-bot@chromium.orgb4a8d972013-06-05 15:40:59 +0000269 this->pop_back_n(fCount - newCount);
bsalomon@google.com49313f62011-09-14 13:54:05 +0000270 }
271 }
272
bsalomon23e619c2015-02-06 11:54:28 -0800273 /** Swaps the contents of this array with that array. Does a pointer swap if possible,
274 otherwise copies the T values. */
275 void swap(SkTArray* that) {
276 if (this->fPreAllocMemArray != this->fItemArray &&
277 that->fPreAllocMemArray != that->fItemArray) {
278 // If neither is using a preallocated array then just swap.
279 SkTSwap(fItemArray, that->fItemArray);
280 SkTSwap(fCount, that->fCount);
281 SkTSwap(fAllocCount, that->fAllocCount);
282 } else {
283 // This could be more optimal...
284 SkTArray copy(*that);
285 *that = *this;
286 *this = copy;
287 }
288 }
289
jvanverth@google.com9b855c72013-03-01 18:21:22 +0000290 T* begin() {
291 return fItemArray;
292 }
293 const T* begin() const {
294 return fItemArray;
295 }
296 T* end() {
297 return fItemArray ? fItemArray + fCount : NULL;
298 }
299 const T* end() const {
300 return fItemArray ? fItemArray + fCount : NULL;;
301 }
302
303 /**
bsalomon@google.com49313f62011-09-14 13:54:05 +0000304 * Get the i^th element.
305 */
306 T& operator[] (int i) {
307 SkASSERT(i < fCount);
308 SkASSERT(i >= 0);
309 return fItemArray[i];
310 }
311
312 const T& operator[] (int i) const {
313 SkASSERT(i < fCount);
314 SkASSERT(i >= 0);
315 return fItemArray[i];
316 }
317
318 /**
319 * equivalent to operator[](0)
320 */
321 T& front() { SkASSERT(fCount > 0); return fItemArray[0];}
322
323 const T& front() const { SkASSERT(fCount > 0); return fItemArray[0];}
324
325 /**
326 * equivalent to operator[](count() - 1)
327 */
328 T& back() { SkASSERT(fCount); return fItemArray[fCount - 1];}
329
330 const T& back() const { SkASSERT(fCount > 0); return fItemArray[fCount - 1];}
331
332 /**
333 * equivalent to operator[](count()-1-i)
334 */
335 T& fromBack(int i) {
336 SkASSERT(i >= 0);
337 SkASSERT(i < fCount);
338 return fItemArray[fCount - i - 1];
339 }
340
341 const T& fromBack(int i) const {
342 SkASSERT(i >= 0);
343 SkASSERT(i < fCount);
344 return fItemArray[fCount - i - 1];
345 }
346
commit-bot@chromium.orgff6ea262013-03-12 12:26:08 +0000347 bool operator==(const SkTArray<T, MEM_COPY>& right) const {
348 int leftCount = this->count();
349 if (leftCount != right.count()) {
350 return false;
351 }
352 for (int index = 0; index < leftCount; ++index) {
353 if (fItemArray[index] != right.fItemArray[index]) {
354 return false;
355 }
356 }
357 return true;
358 }
359
360 bool operator!=(const SkTArray<T, MEM_COPY>& right) const {
361 return !(*this == right);
362 }
363
bsalomon@google.com92669012011-09-27 19:10:05 +0000364protected:
365 /**
366 * Creates an empty array that will use the passed storage block until it
367 * is insufficiently large to hold the entire array.
368 */
369 template <int N>
370 SkTArray(SkAlignedSTStorage<N,T>* storage) {
371 this->init(NULL, 0, storage->get(), N);
372 }
373
374 /**
375 * Copy another array, using preallocated storage if preAllocCount >=
376 * array.count(). Otherwise storage will only be used when array shrinks
377 * to fit.
378 */
379 template <int N>
380 SkTArray(const SkTArray& array, SkAlignedSTStorage<N,T>* storage) {
381 this->init(array.fItemArray, array.fCount, storage->get(), N);
382 }
383
384 /**
385 * Copy a C array, using preallocated storage if preAllocCount >=
386 * count. Otherwise storage will only be used when array shrinks
387 * to fit.
388 */
389 template <int N>
390 SkTArray(const T* array, int count, SkAlignedSTStorage<N,T>* storage) {
391 this->init(array, count, storage->get(), N);
392 }
393
394 void init(const T* array, int count,
bsalomon23e619c2015-02-06 11:54:28 -0800395 void* preAllocStorage, int preAllocOrReserveCount) {
junov@chromium.orgd80a5092011-11-30 18:35:19 +0000396 SkASSERT(count >= 0);
397 SkASSERT(preAllocOrReserveCount >= 0);
bsalomon@google.com92669012011-09-27 19:10:05 +0000398 fCount = count;
399 fReserveCount = (preAllocOrReserveCount > 0) ?
400 preAllocOrReserveCount :
401 gMIN_ALLOC_COUNT;
402 fPreAllocMemArray = preAllocStorage;
403 if (fReserveCount >= fCount &&
bsalomon49f085d2014-09-05 13:34:00 -0700404 preAllocStorage) {
bsalomon@google.com92669012011-09-27 19:10:05 +0000405 fAllocCount = fReserveCount;
406 fMemArray = preAllocStorage;
407 } else {
junov@chromium.orgd80a5092011-11-30 18:35:19 +0000408 fAllocCount = SkMax32(fCount, fReserveCount);
409 fMemArray = sk_malloc_throw(fAllocCount * sizeof(T));
bsalomon@google.com92669012011-09-27 19:10:05 +0000410 }
411
bungeman@google.coma12cc7f2011-10-07 20:54:15 +0000412 SkTArrayExt::copy(this, array);
bsalomon@google.com92669012011-09-27 19:10:05 +0000413 }
414
bsalomon@google.com49313f62011-09-14 13:54:05 +0000415private:
416
417 static const int gMIN_ALLOC_COUNT = 8;
418
bsalomon@google.comd5104142013-06-13 15:13:46 +0000419 // Helper function that makes space for n objects, adjusts the count, but does not initialize
420 // the new objects.
421 void* push_back_raw(int n) {
422 this->checkRealloc(n);
423 void* ptr = fItemArray + fCount;
424 fCount += n;
425 return ptr;
426 }
427
bsalomon@google.com49313f62011-09-14 13:54:05 +0000428 inline void checkRealloc(int delta) {
429 SkASSERT(fCount >= 0);
430 SkASSERT(fAllocCount >= 0);
431
432 SkASSERT(-delta <= fCount);
433
434 int newCount = fCount + delta;
bungeman@google.coma12cc7f2011-10-07 20:54:15 +0000435 int newAllocCount = fAllocCount;
bsalomon@google.com49313f62011-09-14 13:54:05 +0000436
bsalomon@google.com137209f2012-08-14 17:19:08 +0000437 if (newCount > fAllocCount || newCount < (fAllocCount / 3)) {
438 // whether we're growing or shrinking, we leave at least 50% extra space for future
439 // growth (clamped to the reserve count).
440 newAllocCount = SkMax32(newCount + ((newCount + 1) >> 1), fReserveCount);
bsalomon@google.com49313f62011-09-14 13:54:05 +0000441 }
bungeman@google.coma12cc7f2011-10-07 20:54:15 +0000442 if (newAllocCount != fAllocCount) {
bsalomon@google.com49313f62011-09-14 13:54:05 +0000443
bungeman@google.coma12cc7f2011-10-07 20:54:15 +0000444 fAllocCount = newAllocCount;
445 char* newMemArray;
bsalomon@google.com49313f62011-09-14 13:54:05 +0000446
bsalomon49f085d2014-09-05 13:34:00 -0700447 if (fAllocCount == fReserveCount && fPreAllocMemArray) {
bungeman@google.coma12cc7f2011-10-07 20:54:15 +0000448 newMemArray = (char*) fPreAllocMemArray;
bsalomon@google.com49313f62011-09-14 13:54:05 +0000449 } else {
bungeman@google.coma12cc7f2011-10-07 20:54:15 +0000450 newMemArray = (char*) sk_malloc_throw(fAllocCount*sizeof(T));
bsalomon@google.com49313f62011-09-14 13:54:05 +0000451 }
452
bungeman@google.coma12cc7f2011-10-07 20:54:15 +0000453 SkTArrayExt::copyAndDelete<T>(this, newMemArray);
bsalomon@google.com49313f62011-09-14 13:54:05 +0000454
455 if (fMemArray != fPreAllocMemArray) {
456 sk_free(fMemArray);
457 }
bungeman@google.coma12cc7f2011-10-07 20:54:15 +0000458 fMemArray = newMemArray;
bsalomon@google.com49313f62011-09-14 13:54:05 +0000459 }
460 }
461
bsalomon@google.comd5104142013-06-13 15:13:46 +0000462 friend void* operator new<T>(size_t, SkTArray*, int);
463
bungeman@google.com95ebd172014-03-21 19:39:02 +0000464 template<typename X> friend void SkTArrayExt::copy(SkTArray<X, true>* that, int dst, int src);
bungeman@google.comcf385232011-10-07 21:10:39 +0000465 template<typename X> friend void SkTArrayExt::copy(SkTArray<X, true>* that, const X*);
466 template<typename X> friend void SkTArrayExt::copyAndDelete(SkTArray<X, true>* that, char*);
bungeman@google.coma12cc7f2011-10-07 20:54:15 +0000467
bungeman@google.com95ebd172014-03-21 19:39:02 +0000468 template<typename X> friend void SkTArrayExt::copy(SkTArray<X, false>* that, int dst, int src);
bungeman@google.comcf385232011-10-07 21:10:39 +0000469 template<typename X> friend void SkTArrayExt::copy(SkTArray<X, false>* that, const X*);
470 template<typename X> friend void SkTArrayExt::copyAndDelete(SkTArray<X, false>* that, char*);
bungeman@google.coma12cc7f2011-10-07 20:54:15 +0000471
bsalomon23e619c2015-02-06 11:54:28 -0800472 int fReserveCount;
473 int fCount;
474 int fAllocCount;
475 void* fPreAllocMemArray;
bsalomon@google.com49313f62011-09-14 13:54:05 +0000476 union {
477 T* fItemArray;
478 void* fMemArray;
479 };
480};
481
bsalomon@google.comd5104142013-06-13 15:13:46 +0000482// Use the below macro (SkNEW_APPEND_TO_TARRAY) rather than calling this directly
483template <typename T, bool MEM_COPY>
djsollenc87dd2c2014-11-14 11:11:46 -0800484void* operator new(size_t, SkTArray<T, MEM_COPY>* array, int SkDEBUGCODE(atIndex)) {
bsalomon@google.comd5104142013-06-13 15:13:46 +0000485 // Currently, we only support adding to the end of the array. When the array class itself
486 // supports random insertion then this should be updated.
487 // SkASSERT(atIndex >= 0 && atIndex <= array->count());
488 SkASSERT(atIndex == array->count());
489 return array->push_back_raw(1);
490}
491
bsalomon@google.coma47347e2013-06-14 12:30:50 +0000492// Skia doesn't use C++ exceptions but it may be compiled with them enabled. Having an op delete
493// to match the op new silences warnings about missing op delete when a constructor throws an
494// exception.
skia.committer@gmail.comf85693d2013-06-15 07:00:53 +0000495template <typename T, bool MEM_COPY>
djsollenc87dd2c2014-11-14 11:11:46 -0800496void operator delete(void*, SkTArray<T, MEM_COPY>* /*array*/, int /*atIndex*/) {
bsalomon@google.coma47347e2013-06-14 12:30:50 +0000497 SK_CRASH();
498}
499
bsalomon@google.comd5104142013-06-13 15:13:46 +0000500// Constructs a new object as the last element of an SkTArray.
501#define SkNEW_APPEND_TO_TARRAY(array_ptr, type_name, args) \
502 (new ((array_ptr), (array_ptr)->count()) type_name args)
503
504
bsalomon@google.com92669012011-09-27 19:10:05 +0000505/**
506 * Subclass of SkTArray that contains a preallocated memory block for the array.
507 */
bsalomon@google.comf47dd742013-02-26 15:40:01 +0000508template <int N, typename T, bool MEM_COPY = false>
509class SkSTArray : public SkTArray<T, MEM_COPY> {
bsalomon@google.com92669012011-09-27 19:10:05 +0000510private:
bsalomon@google.comf47dd742013-02-26 15:40:01 +0000511 typedef SkTArray<T, MEM_COPY> INHERITED;
bsalomon@google.com92669012011-09-27 19:10:05 +0000512
513public:
514 SkSTArray() : INHERITED(&fStorage) {
515 }
516
517 SkSTArray(const SkSTArray& array)
518 : INHERITED(array, &fStorage) {
519 }
520
521 explicit SkSTArray(const INHERITED& array)
522 : INHERITED(array, &fStorage) {
523 }
524
commit-bot@chromium.org3390b9a2013-10-03 15:17:58 +0000525 explicit SkSTArray(int reserveCount)
526 : INHERITED(reserveCount) {
527 }
528
bsalomon@google.com92669012011-09-27 19:10:05 +0000529 SkSTArray(const T* array, int count)
530 : INHERITED(array, count, &fStorage) {
531 }
532
533 SkSTArray& operator= (const SkSTArray& array) {
534 return *this = *(const INHERITED*)&array;
535 }
536
537 SkSTArray& operator= (const INHERITED& array) {
538 INHERITED::operator=(array);
539 return *this;
540 }
541
542private:
543 SkAlignedSTStorage<N,T> fStorage;
544};
545
bsalomon@google.com49313f62011-09-14 13:54:05 +0000546#endif