Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(663)

Side by Side Diff: include/core/SkTDArray.h

Issue 14502003: Add SkSTDArray. Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Clean up. Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « gyp/tests.gypi ('k') | tests/TDArrayTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 1
2 /* 2 /*
3 * Copyright 2006 The Android Open Source Project 3 * Copyright 2006 The Android Open Source Project
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 8
9 9
10 #ifndef SkTDArray_DEFINED 10 #ifndef SkTDArray_DEFINED
11 #define SkTDArray_DEFINED 11 #define SkTDArray_DEFINED
12 12
13 #include "SkTypes.h" 13 #include "SkTypes.h"
14 #include "SkTemplates.h"
14 15
15 template <typename T> class SkTDArray { 16 template <typename T> class SkTDArray {
16 public: 17 public:
17 SkTDArray() { 18 SkTDArray() {
18 fReserve = fCount = 0; 19 this->init(NULL, 0, NULL, 0);
19 fArray = NULL;
20 } 20 }
21 SkTDArray(const T src[], int count) { 21 SkTDArray(const T src[], size_t count) {
22 SkASSERT(src || count == 0); 22 this->init(src, count, NULL, 0);
23 }
24 SkTDArray(const SkTDArray<T>& that) {
25 this->init(that.fArray, that.fCount, NULL, 0);
26 }
23 27
24 fReserve = fCount = 0; 28 ~SkTDArray() {
25 fArray = NULL; 29 if (fArray != fPreAllocMemArray) {
26 if (count) { 30 sk_free(fArray);
27 fArray = (T*)sk_malloc_throw(count * sizeof(T));
28 memcpy(fArray, src, sizeof(T) * count);
29 fReserve = fCount = count;
30 } 31 }
31 } 32 }
32 SkTDArray(const SkTDArray<T>& src) {
33 fReserve = fCount = 0;
34 fArray = NULL;
35 SkTDArray<T> tmp(src.fArray, src.fCount);
36 this->swap(tmp);
37 }
38 ~SkTDArray() {
39 sk_free(fArray);
40 }
41 33
42 SkTDArray<T>& operator=(const SkTDArray<T>& src) { 34 SkTDArray<T>& operator=(const SkTDArray<T>& that) {
43 if (this != &src) { 35 if (this != &that) {
44 if (src.fCount > fReserve) { 36 if (that.fCount > fReserve) {
45 SkTDArray<T> tmp(src.fArray, src.fCount); 37 T* oldArray = fArray;
46 this->swap(tmp); 38
39 T* newArray = (T*)sk_malloc_throw(that.fCount * sizeof(T));
40 memcpy(newArray, that.fArray, sizeof(T) * that.fCount);
41 SkTSwap(newArray, fArray);
42 fReserve = that.fCount;
43
44 if (oldArray != fPreAllocMemArray) {
45 sk_free(oldArray);
46 }
47 } else { 47 } else {
48 memcpy(fArray, src.fArray, sizeof(T) * src.fCount); 48 memcpy(fArray, that.fArray, sizeof(T) * that.fCount);
49 fCount = src.fCount;
50 } 49 }
50 fCount = that.fCount;
51 } 51 }
52 return *this; 52 return *this;
53 } 53 }
54 54
55 friend bool operator==(const SkTDArray<T>& a, const SkTDArray<T>& b) { 55 friend bool operator==(const SkTDArray<T>& a, const SkTDArray<T>& b) {
56 return a.fCount == b.fCount && 56 return a.fCount == b.fCount &&
57 (a.fCount == 0 || 57 (a.fCount == 0 ||
58 !memcmp(a.fArray, b.fArray, a.fCount * sizeof(T))); 58 !memcmp(a.fArray, b.fArray, a.fCount * sizeof(T)));
59 } 59 }
60 friend bool operator!=(const SkTDArray<T>& a, const SkTDArray<T>& b) { 60 friend bool operator!=(const SkTDArray<T>& a, const SkTDArray<T>& b) {
61 return !(a == b); 61 return !(a == b);
62 } 62 }
63 63
64 void swap(SkTDArray<T>& other) { 64 void swap(SkTDArray<T>& other) {
bungeman-skia 2015/04/22 22:20:29 This swap is wrong for any STD versions, haven't t
65 SkTSwap(fArray, other.fArray); 65 SkTSwap(fArray, other.fArray);
66 SkTSwap(fReserve, other.fReserve); 66 SkTSwap(fReserve, other.fReserve);
67 SkTSwap(fCount, other.fCount); 67 SkTSwap(fCount, other.fCount);
68 } 68 }
69 69
70 /** Return a ptr to the array of data, to be freed with sk_free. This also 70 /** Returns a pointer to the array of data, to be freed with sk_free.
71 resets the SkTDArray to be empty. 71 * This also resets the SkTDArray to be empty.
72 * Note that the value returned may differ from begin().
72 */ 73 */
73 T* detach() { 74 T* detach() {
74 T* array = fArray; 75 T* array = fArray;
75 fArray = NULL; 76 if (fArray == fPreAllocMemArray && fCount > 0) {
76 fReserve = fCount = 0; 77 array = (T*)sk_malloc_throw(fCount * sizeof(T));
78 memcpy(array, fPreAllocMemArray, fCount * sizeof(T));
79 }
80 // The following line will not throw because the second parameter is 0.
81 this->init(NULL, 0, fPreAllocMemArray, fPreAllocMemArraySize);
77 return array; 82 return array;
78 } 83 }
79 84
80 bool isEmpty() const { return fCount == 0; } 85 bool isEmpty() const { return fCount == 0; }
81 86
82 /** 87 /**
83 * Return the number of elements in the array 88 * Return the number of elements in the array
84 */ 89 */
85 int count() const { return fCount; } 90 int count() const { return fCount; }
86 91
87 /** 92 /**
88 * Return the total number of elements allocated. 93 * Return the total number of elements allocated.
89 * reserved() - count() gives you the number of elements you can add 94 * reserved() - count() gives you the number of elements you can add
90 * without causing an allocation. 95 * without causing an allocation.
91 */ 96 */
92 int reserved() const { return fReserve; } 97 int reserved() const { return fReserve; }
93 98
94 /** 99 /**
95 * return the number of bytes in the array: count * sizeof(T) 100 * return the number of bytes in the array: count * sizeof(T)
96 */ 101 */
97 size_t bytes() const { return fCount * sizeof(T); } 102 size_t bytes() const { return fCount * sizeof(T); }
98 103
99 T* begin() { return fArray; } 104 T* begin() { return fArray; }
100 const T* begin() const { return fArray; } 105 const T* begin() const { return fArray; }
101 T* end() { return fArray ? fArray + fCount : NULL; } 106 T* end() { return fArray ? fArray + fCount : NULL; }
102 const T* end() const { return fArray ? fArray + fCount : NULL; } 107 const T* end() const { return fArray ? fArray + fCount : NULL; }
103 108
104 T& operator[](int index) { 109 T& operator[](int index) {
105 SkASSERT(index < fCount); 110 SkASSERT((size_t)index < fCount);
106 return fArray[index]; 111 return fArray[index];
107 } 112 }
108 const T& operator[](int index) const { 113 const T& operator[](int index) const {
109 SkASSERT(index < fCount); 114 SkASSERT((size_t)index < fCount);
110 return fArray[index]; 115 return fArray[index];
111 } 116 }
112 117
113 T& getAt(int index) { 118 T& getAt(int index) {
114 return (*this)[index]; 119 return (*this)[index];
115 } 120 }
116 const T& getAt(int index) const { 121 const T& getAt(int index) const {
117 return (*this)[index]; 122 return (*this)[index];
118 } 123 }
119 124
120 void reset() { 125 void reset() {
121 if (fArray) { 126 T* oldArray = fArray;
122 sk_free(fArray); 127 this->init(NULL, 0, fPreAllocMemArray, fPreAllocMemArraySize);
123 fArray = NULL; 128 if (oldArray != fPreAllocMemArray) {
124 fReserve = fCount = 0; 129 sk_free(oldArray);
125 } else {
126 SkASSERT(fReserve == 0 && fCount == 0);
127 } 130 }
128 } 131 }
129 132
130 void rewind() { 133 void rewind() {
131 // same as setCount(0) 134 // same as setCount(0)
132 fCount = 0; 135 fCount = 0;
133 } 136 }
134 137
135 /** 138 /**
136 * Sets the number of elements in the array. 139 * Sets the number of elements in the array.
137 * If the array does not have space for count elements, it will increase 140 * If the array does not have space for count elements, it will increase
138 * the storage allocated to some amount greater than that required. 141 * the storage allocated to some amount greater than that required.
139 * It will never shrink the shrink the storage. 142 * It will never shrink the shrink the storage.
140 */ 143 */
141 void setCount(int count) { 144 void setCount(int count) {
142 SkASSERT(count >= 0); 145 SkASSERT(count >= 0);
143 if (count > fReserve) { 146 if ((size_t)count > fReserve) {
144 this->resizeStorageToAtLeast(count); 147 this->growReserveTo(count);
145 } 148 }
146 fCount = count; 149 fCount = count;
147 } 150 }
148 151
149 void setReserve(int reserve) { 152 void setReserve(int reserve) {
150 if (reserve > fReserve) { 153 if ((size_t)reserve > fReserve) {
151 this->resizeStorageToAtLeast(reserve); 154 SkASSERT((size_t)reserve > fCount);
155 this->growReserveTo(reserve);
152 } 156 }
153 } 157 }
154 158
155 T* prepend() { 159 T* prepend() {
156 this->adjustCount(1); 160 this->growBy(1);
157 memmove(fArray + 1, fArray, (fCount - 1) * sizeof(T)); 161 memmove(fArray + 1, fArray, (fCount - 1) * sizeof(T));
158 return fArray; 162 return fArray;
159 } 163 }
160 164
161 T* append() { 165 T* append() {
162 return this->append(1, NULL); 166 return this->append(1, NULL);
163 } 167 }
164 T* append(int count, const T* src = NULL) { 168 T* append(int count, const T* src = NULL) {
165 int oldCount = fCount; 169 int oldCount = fCount;
166 if (count) { 170 if (count) {
167 SkASSERT(src == NULL || fArray == NULL || 171 SkASSERT(src == NULL || fArray == NULL ||
168 src + count <= fArray || fArray + oldCount <= src); 172 src + count <= fArray || fArray + oldCount <= src);
169 173
170 this->adjustCount(count); 174 this->growBy(count);
171 if (src) { 175 if (src) {
172 memcpy(fArray + oldCount, src, sizeof(T) * count); 176 memcpy(fArray + oldCount, src, sizeof(T) * count);
173 } 177 }
174 } 178 }
175 return fArray + oldCount; 179 return fArray + oldCount;
176 } 180 }
177 181
178 T* appendClear() { 182 T* appendClear() {
179 T* result = this->append(); 183 T* result = this->append();
180 *result = 0; 184 *result = 0;
181 return result; 185 return result;
182 } 186 }
183 187
184 T* insert(int index) { 188 T* insert(int index) {
185 return this->insert(index, 1, NULL); 189 return this->insert(index, 1, NULL);
186 } 190 }
187 T* insert(int index, int count, const T* src = NULL) { 191 T* insert(int index, int count, const T* src = NULL) {
188 SkASSERT(count); 192 SkASSERT(count);
189 SkASSERT(index <= fCount); 193 SkASSERT((size_t)index <= fCount);
190 size_t oldCount = fCount; 194 size_t oldCount = fCount;
191 this->adjustCount(count); 195 this->growBy(count);
192 T* dst = fArray + index; 196 T* dst = fArray + index;
193 memmove(dst + count, dst, sizeof(T) * (oldCount - index)); 197 memmove(dst + count, dst, sizeof(T) * (oldCount - index));
194 if (src) { 198 if (src) {
195 memcpy(dst, src, sizeof(T) * count); 199 memcpy(dst, src, sizeof(T) * count);
196 } 200 }
197 return dst; 201 return dst;
198 } 202 }
199 203
200 void remove(int index, int count = 1) { 204 void remove(int index, int count = 1) {
201 SkASSERT(index + count <= fCount); 205 SkASSERT((size_t)(index + count) <= fCount);
202 fCount = fCount - count; 206 fCount = fCount - count;
203 memmove(fArray + index, fArray + index + count, sizeof(T) * (fCount - in dex)); 207 memmove(fArray + index, fArray + index + count, sizeof(T) * (fCount - in dex));
204 } 208 }
205 209
206 void removeShuffle(int index) { 210 void removeShuffle(int index) {
207 SkASSERT(index < fCount); 211 SkASSERT((size_t)index < fCount);
208 int newCount = fCount - 1; 212 int newCount = fCount - 1;
209 fCount = newCount; 213 fCount = newCount;
210 if (index != newCount) { 214 if (index != newCount) {
211 memcpy(fArray + index, fArray + newCount, sizeof(T)); 215 memcpy(fArray + index, fArray + newCount, sizeof(T));
212 } 216 }
213 } 217 }
214 218
215 int find(const T& elem) const { 219 int find(const T& elem) const {
216 const T* iter = fArray; 220 const T* iter = fArray;
217 const T* stop = fArray + fCount; 221 const T* stop = fArray + fCount;
(...skipping 25 matching lines...) Expand all
243 return (this->find(elem) >= 0); 247 return (this->find(elem) >= 0);
244 } 248 }
245 249
246 /** 250 /**
247 * Copies up to max elements into dst. The number of items copied is 251 * Copies up to max elements into dst. The number of items copied is
248 * capped by count - index. The actual number copied is returned. 252 * capped by count - index. The actual number copied is returned.
249 */ 253 */
250 int copyRange(T* dst, int index, int max) const { 254 int copyRange(T* dst, int index, int max) const {
251 SkASSERT(max >= 0); 255 SkASSERT(max >= 0);
252 SkASSERT(!max || dst); 256 SkASSERT(!max || dst);
253 if (index >= fCount) { 257 if ((size_t)index >= fCount) {
254 return 0; 258 return 0;
255 } 259 }
256 int count = SkMin32(max, fCount - index); 260 int count = SkMin32(max, fCount - index);
257 memcpy(dst, fArray + index, sizeof(T) * count); 261 memcpy(dst, fArray + index, sizeof(T) * count);
258 return count; 262 return count;
259 } 263 }
260 264
261 void copy(T* dst) const { 265 void copy(T* dst) const {
262 this->copyRange(dst, 0, fCount); 266 this->copyRange(dst, 0, fCount);
263 } 267 }
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
314 T* stop = this->end(); 318 T* stop = this->end();
315 for (T* curr = this->begin(); curr < stop; curr++) { 319 for (T* curr = this->begin(); curr < stop; curr++) {
316 if (*curr) { 320 if (*curr) {
317 visitor(*curr); 321 visitor(*curr);
318 } 322 }
319 } 323 }
320 } 324 }
321 325
322 #ifdef SK_DEBUG 326 #ifdef SK_DEBUG
323 void validate() const { 327 void validate() const {
324 SkASSERT((fReserve == 0 && fArray == NULL) || 328 SkASSERT((fArray == NULL && fReserve == 0) ||
325 (fReserve > 0 && fArray != NULL)); 329 (fArray == fPreAllocMemArray && fReserve == fPreAllocMemArraySi ze) ||
330 (fArray != NULL && fArray != fPreAllocMemArray && fReserve > 0) );
326 SkASSERT(fCount <= fReserve); 331 SkASSERT(fCount <= fReserve);
332 SkASSERT(fReserve <= fPreAllocMemArraySize || fArray != fPreAllocMemArra y);
327 } 333 }
328 #endif 334 #endif
329 335
330 void shrinkToFit() { 336 protected:
331 fReserve = fCount; 337 template <int N> SkTDArray(SkAlignedSTStorage<N, T>* storage) {
332 fArray = (T*)sk_realloc_throw(fArray, fReserve * sizeof(T)); 338 this->init(NULL, 0, (T*)storage->get(), N);
339 }
340 template <int N> SkTDArray(const T src[], size_t count, SkAlignedSTStorage<N , T>* storage) {
341 this->init(src, count, (T*)storage->get(), N);
342 }
343 template <int N> SkTDArray(const SkTDArray<T>& that, SkAlignedSTStorage<N, T >* storage) {
344 this->init(that.fArray, that.fCount, (T*)storage->get(), N);
345 }
346
347 void init(const T* src, size_t count, T* preAllocStorage, size_t preAllocCou nt) {
348 SkASSERT(src || count == 0);
349
350 fArray = preAllocStorage;
351 fPreAllocMemArray = preAllocStorage;
352 fReserve = preAllocCount;
353 fCount = count;
354 fPreAllocMemArraySize = preAllocCount;
355
356 // The following is almost equivalent to calling this->append(count, src ).
357 // This creates a tight fit instead of allocating extra room.
358 if (count) {
359 if (NULL == fArray || count > fReserve) {
360 fArray = (T*)sk_malloc_throw(count * sizeof(T));
361 fReserve = count;
362 }
363 memcpy(fArray, src, sizeof(T) * count);
364 fCount = count;
365 }
333 } 366 }
334 367
335 private: 368 private:
336 T* fArray; 369 /** The underlying storage.
337 int fReserve; 370 * If fArray == NULL; fReserve == 0, fCount == 0.
338 int fCount; 371 * If fArray == fPreAllocMemArray; fReserve = fPreAllocMemArraySize.
372 * Otherwise fArray points to sk_malloc memory.
373 */
374 T* fArray;
375
376 /** Fixed-size storage which may be used as underlying storage.
377 * Once out of init, this value is constant.
378 * If fPreAllocMemArray == NULL; fPreAllocMemArraySize == 0.
379 * If fPreAllocMemArray == fArray; fReserve = fPreAllocMemArraySize.
380 */
381 T* fPreAllocMemArray;
382
383 /** The current total size of the underlying storage in elements.
384 * If fReserve == 0; fArray == NULL, fCount == 0.
385 * If fReserve > 0; fArray != NULL.
386 * If fReserve > fPreAllocMemArraySize; fArray != fPreAllocMemArray.
387 * fReserve >= fCount.
388 */
389 size_t fReserve;
reed1 2015/04/22 23:02:12 Why change fReserve and fCount from int to size_t?
390
391 /** The current logical number of elements.
392 * fCount <= fReserve.
393 * Note that 'If fCount == 0; fArray == NULL' is not maintained.
394 */
395 size_t fCount;
396
397 /** The total size of the fixed size storage in elements.
398 * Once out of init, this value is constant.
399 * If fPreAllocMemArraySize == 0; fPreAllocMemArray == NULL.
400 */
401 size_t fPreAllocMemArraySize;
339 402
340 /** 403 /**
341 * Adjusts the number of elements in the array. 404 * Adjusts the number of elements in the array.
342 * This is the same as calling setCount(count() + delta). 405 * This is the same as calling setCount(count() + extra).
343 */ 406 */
344 void adjustCount(int delta) { 407 void growBy(size_t extra) {
345 this->setCount(fCount + delta); 408 SkASSERT(extra);
409
410 size_t newCount = fCount + extra;
411 if (newCount > fReserve) {
412 size_t size = newCount + 4;
413 size += size >> 2;
414
415 growReserveTo(size);
416 }
417 fCount = newCount;
346 } 418 }
347 419
348 /** 420 /**
349 * Increase the storage allocation such that it can hold (fCount + extra) 421 * Increase the storage allocation such that it can hold size) elements.
350 * elements.
351 * It never shrinks the allocation, and it may increase the allocation by 422 * It never shrinks the allocation, and it may increase the allocation by
352 * more than is strictly required, based on a private growth heuristic. 423 * more than is strictly required, based on a private growth heuristic.
353 * 424 *
354 * note: does NOT modify fCount 425 * Note: does NOT modify fCount.
355 */ 426 */
356 void resizeStorageToAtLeast(int count) { 427 void growReserveTo(size_t size) {
357 SkASSERT(count > fReserve); 428 SkASSERT(size > fReserve);
358 fReserve = count + 4; 429
359 fReserve += fReserve / 4; 430 if (fArray == fPreAllocMemArray) {
360 fArray = (T*)sk_realloc_throw(fArray, fReserve * sizeof(T)); 431 fArray = (T*)sk_malloc_throw(size * sizeof(T));
432 memcpy(fArray, fPreAllocMemArray, fCount * sizeof(T));
433 } else {
434 fArray = (T*)sk_realloc_throw(fArray, size * sizeof(T));
435 }
436 fReserve = size;
361 } 437 }
362 }; 438 };
363 439
440
441 /**
442 * Subclass of SkTDArray that contains a preallocated memory block for the array .
443 * @param N the number of T elements to store in the preallocated memory block.
444 */
445 template <size_t N, typename T>
446 class SkSTDArray : public SkTDArray<T> {
447 private:
448 typedef SkTDArray<T> INHERITED;
449
450 public:
451 SkSTDArray() : INHERITED(&fStorage) { }
452 SkSTDArray(const T* src, int count) : INHERITED(src, count, &fStorage) { }
453 SkSTDArray(const SkSTDArray& that) : INHERITED(that, &fStorage) { }
454
455 explicit SkSTDArray(const INHERITED& that) : INHERITED(that, &fStorage) { }
456
457 SkSTDArray& operator= (const SkSTDArray& that) {
458 return *this = *(const INHERITED*)&that;
459 }
460
461 SkSTDArray& operator= (const INHERITED& that) {
462 INHERITED::operator=(that);
463 return *this;
464 }
465
466 private:
467 SkAlignedSTStorage<N, T> fStorage;
468 };
469
364 #endif 470 #endif
OLDNEW
« no previous file with comments | « gyp/tests.gypi ('k') | tests/TDArrayTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698