1 /* 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 GrTDArray_DEFINED 19 #define GrTDArray_DEFINED 20 21 #include "GrTypes.h" 22 23 static int GrInitialArrayAllocationCount() { 24 return 4; 25 } 26 27 static int GrNextArrayAllocationCount(int count) { 28 return count + ((count + 1) >> 1); 29 } 30 31 template <typename T> class GrTDArray { 32 public: 33 GrTDArray() : fArray(NULL), fAllocated(0), fCount(0) {} 34 GrTDArray(const GrTDArray& src) { 35 fCount = fAllocated = src.fCount; 36 fArray = (T*)GrMalloc(fAllocated * sizeof(T)); 37 memcpy(fArray, src.fArray, fCount * sizeof(T)); 38 } 39 ~GrTDArray() { 40 if (fArray) { 41 GrFree(fArray); 42 } 43 } 44 45 bool isEmpty() const { return 0 == fCount; } 46 int count() const { return fCount; } 47 48 const T& at(int index) const { 49 GrAssert((unsigned)index < (unsigned)fCount); 50 return fArray[index]; 51 } 52 T& at(int index) { 53 GrAssert((unsigned)index < (unsigned)fCount); 54 return fArray[index]; 55 } 56 57 const T& operator[](int index) const { return this->at(index); } 58 T& operator[](int index) { return this->at(index); } 59 60 GrTDArray& operator=(const GrTDArray& src) { 61 if (fAllocated < src.fCount) { 62 fAllocated = src.fCount; 63 GrFree(fArray); 64 fArray = (T*)GrMalloc(fAllocated * sizeof(T)); 65 } 66 fCount = src.fCount; 67 memcpy(fArray, src.fArray, fCount * sizeof(T)); 68 return *this; 69 } 70 71 void reset() { 72 if (fArray) { 73 GrFree(fArray); 74 fArray = NULL; 75 } 76 fAllocated = fCount = 0; 77 } 78 79 T* begin() const { return fArray; } 80 T* end() const { return fArray + fCount; } 81 T* back() const { GrAssert(fCount); return fArray + (fCount - 1); } 82 83 T* prepend() { 84 this->growAt(0); 85 return fArray; 86 } 87 88 T* append() { 89 this->growAt(fCount); 90 return fArray + fCount - 1; 91 } 92 93 /** 94 * index may be [0..count], so that you can insert at the end (like append) 95 */ 96 T* insert(int index) { 97 GrAssert((unsigned)index <= (unsigned)fCount); 98 this->growAt(index); 99 return fArray + index; 100 } 101 102 void remove(int index) { 103 GrAssert((unsigned)index < (unsigned)fCount); 104 fCount -= 1; 105 if (index < fCount) { 106 int remaining = fCount - index; 107 memmove(fArray + index, fArray + index + 1, remaining * sizeof(T)); 108 } 109 } 110 111 void removeShuffle(int index) { 112 GrAssert((unsigned)index < (unsigned)fCount); 113 fCount -= 1; 114 if (index < fCount) { 115 memmove(fArray + index, fArray + fCount, sizeof(T)); 116 } 117 } 118 119 // Utility iterators 120 121 /** 122 * Calls GrFree() on each element. Assumes each is NULL or was allocated 123 * with GrMalloc(). 124 */ 125 void freeAll() { 126 T* stop = this->end(); 127 for (T* curr = this->begin(); curr < stop; curr++) { 128 GrFree(*curr); 129 } 130 this->reset(); 131 } 132 133 /** 134 * Calls delete on each element. Assumes each is NULL or was allocated 135 * with new. 136 */ 137 void deleteAll() { 138 T* stop = this->end(); 139 for (T* curr = this->begin(); curr < stop; curr++) { 140 delete *curr; 141 } 142 this->reset(); 143 } 144 145 /** 146 * Calls GrSafeUnref() on each element. Assumes each is NULL or is a 147 * subclass of GrRefCnt. 148 */ 149 void unrefAll() { 150 T* stop = this->end(); 151 for (T* curr = this->begin(); curr < stop; curr++) { 152 GrSafeUnref(*curr); 153 } 154 this->reset(); 155 } 156 157 void visit(void visitor(T&)) const { 158 T* stop = this->end(); 159 for (T* curr = this->begin(); curr < stop; curr++) { 160 if (*curr) { 161 visitor(*curr); 162 } 163 } 164 } 165 166 int find(const T& elem) const { 167 int count = this->count(); 168 T* curr = this->begin(); 169 for (int i = 0; i < count; i++) { 170 if (elem == curr[i]) { 171 return i; 172 } 173 } 174 return -1; 175 } 176 177 friend bool operator==(const GrTDArray<T>& a, const GrTDArray<T>& b) { 178 return a.count() == b.count() && 179 (0 == a.count() || 180 0 == memcmp(a.begin(), b.begin(), a.count() * sizeof(T))); 181 } 182 friend bool operator!=(const GrTDArray<T>& a, const GrTDArray<T>& b) { 183 return !(a == b); 184 } 185 186 private: 187 T* fArray; 188 int fAllocated, fCount; 189 190 // growAt will increment fCount, reallocate fArray (as needed), and slide 191 // the contents of fArray to make a hole for new data at index. 192 void growAt(int index) { 193 GrAssert(fCount <= fAllocated); 194 if (0 == fAllocated) { 195 fAllocated = GrInitialArrayAllocationCount(); 196 fArray = (T*)GrMalloc(fAllocated * sizeof(T)); 197 } else if (fCount == fAllocated) { 198 fAllocated = GrNextArrayAllocationCount(fAllocated); 199 T* newArray = (T*)GrMalloc(fAllocated * sizeof(T)); 200 memcpy(newArray, fArray, index * sizeof(T)); 201 memcpy(newArray + index + 1, fArray + index, 202 (fCount - index) * sizeof(T)); 203 GrFree(fArray); 204 fArray = newArray; 205 } else { 206 // check that we're not just appending 207 if (index < fCount) { 208 memmove(fArray + index + 1, fArray + index, 209 (fCount - index) * sizeof(T)); 210 } 211 } 212 GrAssert(fCount < fAllocated); 213 fCount += 1; 214 } 215 }; 216 217 extern void* GrTDArray_growAt(void*, int* allocated, int& count, int index, 218 size_t); 219 220 221 #endif 222 223