aboutsummaryrefslogtreecommitdiffhomepage
path: root/gpu/include/GrTArray.h
diff options
context:
space:
mode:
Diffstat (limited to 'gpu/include/GrTArray.h')
-rw-r--r--gpu/include/GrTArray.h298
1 files changed, 298 insertions, 0 deletions
diff --git a/gpu/include/GrTArray.h b/gpu/include/GrTArray.h
new file mode 100644
index 0000000000..f0d94943a9
--- /dev/null
+++ b/gpu/include/GrTArray.h
@@ -0,0 +1,298 @@
+/*
+ Copyright 2010 Google Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+
+#ifndef GrTArray_DEFINED
+#define GrTArray_DEFINED
+
+#include <new>
+#include "GrTypes.h"
+
+// TODO: convert from uint32_t to int.
+
+// DATA_TYPE indicates that T has a trivial cons, destructor
+// and can be shallow-copied
+template <typename T, bool DATA_TYPE = false> class GrTArray {
+public:
+ GrTArray() {
+ fCount = 0;
+ fReserveCount = MIN_ALLOC_COUNT;
+ fAllocCount = 0;
+ fMemArray = NULL;
+ fPreAllocMemArray = NULL;
+ }
+
+ GrTArray(uint32_t reserveCount) {
+ fCount = 0;
+ fReserveCount = GrMax(reserveCount, (uint32_t)MIN_ALLOC_COUNT);
+ fAllocCount = fReserveCount;
+ fMemArray = GrMalloc(sizeof(T) * fReserveCount);
+ fPreAllocMemArray = NULL;
+ }
+
+ GrTArray(void* preAllocStorage, uint32_t preAllocCount) {
+ // we allow NULL,0 args and revert to the default cons. behavior
+ // this makes it possible for a owner-object to use same constructor
+ // to get either prealloc or nonprealloc behavior based using same line
+ GrAssert((NULL == preAllocStorage) == !preAllocCount);
+
+ fCount = 0;
+ fReserveCount = preAllocCount > 0 ? preAllocCount :
+ MIN_ALLOC_COUNT;
+ fAllocCount = preAllocCount;
+ fMemArray = preAllocStorage;
+ fPreAllocMemArray = preAllocStorage;
+ }
+
+ GrTArray(const GrTArray& array) {
+ fCount = array.count();
+ fReserveCount = MIN_ALLOC_COUNT;
+ fAllocCount = GrMax(fReserveCount, fCount);
+ fMemArray = GrMalloc(sizeof(T) * fAllocCount);
+ fPreAllocMemArray = NULL;
+ if (DATA_TYPE) {
+ memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
+ } else {
+ for (uint32_t i = 0; i < fCount; ++i) {
+ new (fItemArray + i) T(array[i]);
+ }
+ }
+ }
+
+ GrTArray(const T* array, uint32_t count) {
+ fCount = count;
+ fReserveCount = MIN_ALLOC_COUNT;
+ fAllocCount = GrMax(fReserveCount, fCount);
+ fMemArray = GrMalloc(sizeof(T) * fAllocCount);
+ fPreAllocMemArray = NULL;
+ if (DATA_TYPE) {
+ memcpy(fMemArray, array, sizeof(T) * fCount);
+ } else {
+ for (uint32_t i = 0; i < fCount; ++i) {
+ new (fItemArray + i) T(array[i]);
+ }
+ }
+ }
+
+ GrTArray(const GrTArray& array,
+ void* preAllocStorage, uint32_t preAllocCount) {
+
+ // for same reason as non-copying cons we allow NULL, 0 for prealloc
+ GrAssert((NULL == preAllocStorage) == !preAllocCount);
+
+ fCount = array.count();
+ fReserveCount = preAllocCount > 0 ? preAllocCount :
+ MIN_ALLOC_COUNT;
+ fPreAllocMemArray = preAllocStorage;
+
+ if (fReserveCount >= fCount && preAllocCount) {
+ fAllocCount = fReserveCount;
+ fMemArray = preAllocStorage;
+ } else {
+ fAllocCount = GrMax(fCount, fReserveCount);
+ fMemArray = GrMalloc(fAllocCount * sizeof(T));
+ }
+
+ if (DATA_TYPE) {
+ memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
+ } else {
+ for (uint32_t i = 0; i < fCount; ++i) {
+ new (fItemArray + i) T(array[i]);
+ }
+ }
+ }
+
+ GrTArray(const T* array, uint32_t count,
+ void* preAllocStorage, uint32_t preAllocCount) {
+
+ // for same reason as non-copying cons we allow NULL, 0 for prealloc
+ GrAssert((NULL == preAllocStorage) == !preAllocCount);
+
+ fCount = count;
+ fReserveCount = (preAllocCount > 0) ? preAllocCount :
+ MIN_ALLOC_COUNT;
+ fPreAllocMemArray = preAllocStorage;
+
+ if (fReserveCount >= fCount && preAllocCount) {
+ fAllocCount = fReserveCount;
+ fMemArray = preAllocStorage;
+ } else {
+ fAllocCount = GrMax(fCount, fReserveCount);
+ fMemArray = GrMalloc(fAllocCount * sizeof(T));
+ }
+
+ if (DATA_TYPE) {
+ memcpy(fMemArray, array, sizeof(T) * fCount);
+ } else {
+ for (uint32_t i = 0; i < fCount; ++i) {
+ new (fItemArray + i) T(array[i]);
+ }
+ }
+ }
+
+ GrTArray& operator =(const GrTArray& array) {
+ for (uint32_t i = 0; i < fCount; ++i) {
+ fItemArray[i].~T();
+ }
+ fCount = 0;
+ checkRealloc((int)array.count());
+ fCount = array.count();
+ if (DATA_TYPE) {
+ memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
+ } else {
+ for (uint32_t i = 0; i < fCount; ++i) {
+ new (fItemArray + i) T(array[i]);
+ }
+ }
+ return *this;
+ }
+
+ ~GrTArray() {
+ for (uint32_t i = 0; i < fCount; ++i) {
+ fItemArray[i].~T();
+ }
+ if (fMemArray != fPreAllocMemArray) {
+ GrFree(fMemArray);
+ }
+ }
+
+ uint32_t count() const { return fCount; }
+
+ bool empty() const { return !fCount; }
+
+ T& push_back() {
+ checkRealloc(1);
+ new ((char*)fMemArray+sizeof(T)*fCount) T;
+ ++fCount;
+ return fItemArray[fCount-1];
+ }
+
+ void push_back_n(uint32_t n) {
+ checkRealloc(n);
+ for (uint32_t i = 0; i < n; ++i) {
+ new (fItemArray + fCount + i) T;
+ }
+ fCount += n;
+ }
+
+ void pop_back() {
+ GrAssert(0 != fCount);
+ --fCount;
+ fItemArray[fCount].~T();
+ checkRealloc(0);
+ }
+
+ void pop_back_n(uint32_t n) {
+ GrAssert(fCount >= n);
+ fCount -= n;
+ for (uint32_t i = 0; i < n; ++i) {
+ fItemArray[i].~T();
+ }
+ checkRealloc(0);
+ }
+
+ // pushes or pops from the back to resize
+ void resize_back(uint32_t newCount) {
+ if (newCount > fCount) {
+ push_back_n(newCount - fCount);
+ } else if (newCount < fCount) {
+ pop_back_n(fCount - newCount);
+ }
+ }
+
+ T& operator[] (uint32_t i) {
+ GrAssert(i < fCount);
+ return fItemArray[i];
+ }
+
+ const T& operator[] (uint32_t i) const {
+ GrAssert(i < fCount);
+ return fItemArray[i];
+ }
+
+ T& front() { GrAssert(fCount); return fItemArray[0];}
+
+ const T& front() const { GrAssert(fCount); return fItemArray[0];}
+
+ T& back() { GrAssert(fCount); return fItemArray[fCount - 1];}
+
+ const T& back() const { GrAssert(fCount); return fItemArray[fCount - 1];}
+
+ T& fromBack(uint32_t i) {
+ GrAssert(i < fCount);
+ return fItemArray[fCount - i - 1];
+ }
+
+ const T& fromBack(uint32_t i) const {
+ GrAssert(i < fCount);
+ return fItemArray[fCount - i - 1];
+ }
+
+private:
+ static const uint32_t MIN_ALLOC_COUNT = 8;
+
+ inline void checkRealloc(int32_t delta) {
+ GrAssert(-delta <= (int32_t)fCount);
+
+ uint32_t newCount = fCount + delta;
+ uint32_t fNewAllocCount = fAllocCount;
+
+ if (newCount > fAllocCount) {
+ fNewAllocCount = GrMax(newCount + ((newCount + 1) >> 1),
+ fReserveCount);
+ } else if (newCount < fAllocCount / 3) {
+ fNewAllocCount = GrMax(fAllocCount / 2, fReserveCount);
+ }
+
+ if (fNewAllocCount != fAllocCount) {
+
+ fAllocCount = fNewAllocCount;
+ char* fNewMemArray;
+
+ if (fAllocCount == fReserveCount && NULL != fPreAllocMemArray) {
+ fNewMemArray = (char*) fPreAllocMemArray;
+ } else {
+ fNewMemArray = (char*) GrMalloc(fAllocCount*sizeof(T));
+ }
+
+ if (DATA_TYPE) {
+ memcpy(fNewMemArray, fMemArray, fCount * sizeof(T));
+ } else {
+ for (uint32_t i = 0; i < fCount; ++i) {
+ new (fNewMemArray + sizeof(T) * i) T(fItemArray[i]);
+ fItemArray[i].~T();
+ }
+ }
+
+ if (fMemArray != fPreAllocMemArray) {
+ GrFree(fMemArray);
+ }
+ fMemArray = fNewMemArray;
+ }
+ }
+
+ uint32_t fReserveCount;
+ uint32_t fCount;
+ uint32_t fAllocCount;
+ void* fPreAllocMemArray;
+ union {
+ T* fItemArray;
+ void* fMemArray;
+ };
+};
+
+#endif
+