diff options
Diffstat (limited to 'src/gpu/GrTDArray.h')
-rw-r--r-- | src/gpu/GrTDArray.h | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/src/gpu/GrTDArray.h b/src/gpu/GrTDArray.h new file mode 100644 index 0000000..731001a --- /dev/null +++ b/src/gpu/GrTDArray.h @@ -0,0 +1,216 @@ + +/* + * Copyright 2010 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + + +#ifndef GrTDArray_DEFINED +#define GrTDArray_DEFINED + +#include "GrTypes.h" +#include "GrRefCnt.h" + +static int GrInitialArrayAllocationCount() { + return 4; +} + +static int GrNextArrayAllocationCount(int count) { + return count + ((count + 1) >> 1); +} + +template <typename T> class GrTDArray { +public: + GrTDArray() : fArray(NULL), fAllocated(0), fCount(0) {} + GrTDArray(const GrTDArray& src) { + fCount = fAllocated = src.fCount; + fArray = (T*)GrMalloc(fAllocated * sizeof(T)); + memcpy(fArray, src.fArray, fCount * sizeof(T)); + } + ~GrTDArray() { + if (fArray) { + GrFree(fArray); + } + } + + bool isEmpty() const { return 0 == fCount; } + int count() const { return fCount; } + + const T& at(int index) const { + GrAssert((unsigned)index < (unsigned)fCount); + return fArray[index]; + } + T& at(int index) { + GrAssert((unsigned)index < (unsigned)fCount); + return fArray[index]; + } + + const T& operator[](int index) const { return this->at(index); } + T& operator[](int index) { return this->at(index); } + + GrTDArray& operator=(const GrTDArray& src) { + if (fAllocated < src.fCount) { + fAllocated = src.fCount; + GrFree(fArray); + fArray = (T*)GrMalloc(fAllocated * sizeof(T)); + } + fCount = src.fCount; + memcpy(fArray, src.fArray, fCount * sizeof(T)); + return *this; + } + + void reset() { + if (fArray) { + GrFree(fArray); + fArray = NULL; + } + fAllocated = fCount = 0; + } + + T* begin() const { return fArray; } + T* end() const { return fArray + fCount; } + T* back() const { GrAssert(fCount); return fArray + (fCount - 1); } + + T* prepend() { + this->growAt(0); + return fArray; + } + + T* append() { + this->growAt(fCount); + return fArray + fCount - 1; + } + + /** + * index may be [0..count], so that you can insert at the end (like append) + */ + T* insert(int index) { + GrAssert((unsigned)index <= (unsigned)fCount); + this->growAt(index); + return fArray + index; + } + + void remove(int index) { + GrAssert((unsigned)index < (unsigned)fCount); + fCount -= 1; + if (index < fCount) { + int remaining = fCount - index; + memmove(fArray + index, fArray + index + 1, remaining * sizeof(T)); + } + } + + void removeShuffle(int index) { + GrAssert((unsigned)index < (unsigned)fCount); + fCount -= 1; + if (index < fCount) { + memmove(fArray + index, fArray + fCount, sizeof(T)); + } + } + + // Utility iterators + + /** + * Calls GrFree() on each element. Assumes each is NULL or was allocated + * with GrMalloc(). + */ + void freeAll() { + T* stop = this->end(); + for (T* curr = this->begin(); curr < stop; curr++) { + GrFree(*curr); + } + this->reset(); + } + + /** + * Calls delete on each element. Assumes each is NULL or was allocated + * with new. + */ + void deleteAll() { + T* stop = this->end(); + for (T* curr = this->begin(); curr < stop; curr++) { + delete *curr; + } + this->reset(); + } + + /** + * Calls GrSafeUnref() on each element. Assumes each is NULL or is a + * subclass of GrRefCnt. + */ + void unrefAll() { + T* stop = this->end(); + for (T* curr = this->begin(); curr < stop; curr++) { + GrSafeUnref(*curr); + } + this->reset(); + } + + void visit(void visitor(T&)) const { + T* stop = this->end(); + for (T* curr = this->begin(); curr < stop; curr++) { + if (*curr) { + visitor(*curr); + } + } + } + + int find(const T& elem) const { + int count = this->count(); + T* curr = this->begin(); + for (int i = 0; i < count; i++) { + if (elem == curr[i]) { + return i; + } + } + return -1; + } + + friend bool operator==(const GrTDArray<T>& a, const GrTDArray<T>& b) { + return a.count() == b.count() && + (0 == a.count() || + 0 == memcmp(a.begin(), b.begin(), a.count() * sizeof(T))); + } + friend bool operator!=(const GrTDArray<T>& a, const GrTDArray<T>& b) { + return !(a == b); + } + +private: + T* fArray; + int fAllocated, fCount; + + // growAt will increment fCount, reallocate fArray (as needed), and slide + // the contents of fArray to make a hole for new data at index. + void growAt(int index) { + GrAssert(fCount <= fAllocated); + if (0 == fAllocated) { + fAllocated = GrInitialArrayAllocationCount(); + fArray = (T*)GrMalloc(fAllocated * sizeof(T)); + } else if (fCount == fAllocated) { + fAllocated = GrNextArrayAllocationCount(fAllocated); + T* newArray = (T*)GrMalloc(fAllocated * sizeof(T)); + memcpy(newArray, fArray, index * sizeof(T)); + memcpy(newArray + index + 1, fArray + index, + (fCount - index) * sizeof(T)); + GrFree(fArray); + fArray = newArray; + } else { + // check that we're not just appending + if (index < fCount) { + memmove(fArray + index + 1, fArray + index, + (fCount - index) * sizeof(T)); + } + } + GrAssert(fCount < fAllocated); + fCount += 1; + } +}; + +extern void* GrTDArray_growAt(void*, int* allocated, int& count, int index, + size_t); + + +#endif + |