d38f137e9b
Review URL: http://codereview.appspot.com/5250070/ git-svn-id: http://skia.googlecode.com/svn/trunk@2471 2bbb7eff-a529-9590-31e7-b0007b416f81
217 lines
5.7 KiB
C++
217 lines
5.7 KiB
C++
|
|
/*
|
|
* 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
|
|
|