OLD | NEW |
---|---|
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 SK_API SkTDArray { | 16 template <typename T> class SK_API SkTDArray { |
16 public: | 17 public: |
17 SkTDArray() { | 18 SkTDArray() { |
18 fReserve = fCount = 0; | 19 this->init(NULL, 0, NULL, 0); |
19 fArray = NULL; | |
20 #ifdef SK_DEBUG | |
21 fData = NULL; | |
22 #endif | |
23 } | 20 } |
24 SkTDArray(const T src[], size_t count) { | 21 SkTDArray(const T src[], size_t count) { |
25 SkASSERT(src || count == 0); | 22 this->init(src, count, NULL, 0); |
26 | |
27 fReserve = fCount = 0; | |
28 fArray = NULL; | |
29 #ifdef SK_DEBUG | |
30 fData = NULL; | |
31 #endif | |
32 if (count) { | |
33 fArray = (T*)sk_malloc_throw(count * sizeof(T)); | |
34 #ifdef SK_DEBUG | |
35 fData = (ArrayT*)fArray; | |
36 #endif | |
37 memcpy(fArray, src, sizeof(T) * count); | |
38 fReserve = fCount = count; | |
39 } | |
40 } | 23 } |
41 SkTDArray(const SkTDArray<T>& src) { | 24 SkTDArray(const SkTDArray<T>& src) { |
42 fReserve = fCount = 0; | 25 this->init(src.fArray, src.fCount, NULL, 0); |
43 fArray = NULL; | |
44 #ifdef SK_DEBUG | |
45 fData = NULL; | |
46 #endif | |
47 SkTDArray<T> tmp(src.fArray, src.fCount); | |
48 this->swap(tmp); | |
49 } | 26 } |
27 | |
50 ~SkTDArray() { | 28 ~SkTDArray() { |
51 sk_free(fArray); | 29 if (fArray != fPreAllocMemArray) { |
30 sk_free(fArray); | |
31 } | |
52 } | 32 } |
53 | 33 |
54 SkTDArray<T>& operator=(const SkTDArray<T>& src) { | 34 SkTDArray<T>& operator=(const SkTDArray<T>& src) { |
55 if (this != &src) { | 35 if (this != &src) { |
56 if (src.fCount > fReserve) { | 36 if (src.fCount > fReserve) { |
57 SkTDArray<T> tmp(src.fArray, src.fCount); | 37 SkTDArray<T> tmp(src.fArray, src.fCount); |
58 this->swap(tmp); | 38 this->swap(tmp); |
59 } else { | 39 } else { |
60 memcpy(fArray, src.fArray, sizeof(T) * src.fCount); | 40 memcpy(fArray, src.fArray, sizeof(T) * src.fCount); |
61 fCount = src.fCount; | 41 fCount = src.fCount; |
62 } | 42 } |
63 } | 43 } |
64 return *this; | 44 return *this; |
65 } | 45 } |
66 | 46 |
67 friend bool operator==(const SkTDArray<T>& a, const SkTDArray<T>& b) { | 47 friend bool operator==(const SkTDArray<T>& a, const SkTDArray<T>& b) { |
68 return a.fCount == b.fCount && | 48 return a.fCount == b.fCount && |
69 (a.fCount == 0 || | 49 (a.fCount == 0 || |
70 !memcmp(a.fArray, b.fArray, a.fCount * sizeof(T))); | 50 !memcmp(a.fArray, b.fArray, a.fCount * sizeof(T))); |
71 } | 51 } |
72 | 52 |
73 void swap(SkTDArray<T>& other) { | 53 void swap(SkTDArray<T>& other) { |
74 SkTSwap(fArray, other.fArray); | 54 SkTSwap(fArray, other.fArray); |
75 #ifdef SK_DEBUG | 55 SkTSwap(fPreAllocMemArray, other.fPreAllocMemArray); |
76 SkTSwap(fData, other.fData); | |
77 #endif | |
78 SkTSwap(fReserve, other.fReserve); | 56 SkTSwap(fReserve, other.fReserve); |
79 SkTSwap(fCount, other.fCount); | 57 SkTSwap(fCount, other.fCount); |
58 SkTSwap(fPreAllocMemArraySize, other.fPreAllocMemArraySize); | |
80 } | 59 } |
81 | 60 |
82 /** Return a ptr to the array of data, to be freed with sk_free. This also | 61 /** Return a ptr to the array of data, to be freed with sk_free. This also |
83 resets the SkTDArray to be empty. | 62 resets the SkTDArray to be empty. |
84 */ | 63 */ |
85 T* detach() { | 64 T* detach() { |
86 T* array = fArray; | 65 T* array = fArray; |
87 fArray = NULL; | 66 if (NULL != fArray && fArray == fPreAllocMemArray) { |
88 fReserve = fCount = 0; | 67 array = (T*)sk_malloc_throw(fCount * sizeof(T)); |
89 SkDEBUGCODE(fData = NULL;) | 68 memcpy(array, fPreAllocMemArray, fCount * sizeof(T)); |
69 } | |
70 this->init(NULL, 0, fPreAllocMemArray, fPreAllocMemArraySize); | |
90 return array; | 71 return array; |
91 } | 72 } |
92 | 73 |
93 bool isEmpty() const { return fCount == 0; } | 74 bool isEmpty() const { return fCount == 0; } |
94 | 75 |
95 /** | 76 /** |
96 * Return the number of elements in the array | 77 * Return the number of elements in the array |
97 */ | 78 */ |
98 int count() const { return (int)fCount; } | 79 int count() const { return (int)fCount; } |
99 | 80 |
(...skipping 17 matching lines...) Expand all Loading... | |
117 } | 98 } |
118 | 99 |
119 T& getAt(int index) { | 100 T& getAt(int index) { |
120 return (*this)[index]; | 101 return (*this)[index]; |
121 } | 102 } |
122 const T& getAt(int index) const { | 103 const T& getAt(int index) const { |
123 return (*this)[index]; | 104 return (*this)[index]; |
124 } | 105 } |
125 | 106 |
126 void reset() { | 107 void reset() { |
127 if (fArray) { | 108 if (fArray != fPreAllocMemArray) { |
128 sk_free(fArray); | 109 sk_free(fArray); |
129 fArray = NULL; | |
130 #ifdef SK_DEBUG | |
131 fData = NULL; | |
132 #endif | |
133 fReserve = fCount = 0; | |
134 } else { | |
135 SkASSERT(fReserve == 0 && fCount == 0); | |
136 } | 110 } |
111 this->init(NULL, 0, fPreAllocMemArray, fPreAllocMemArraySize); | |
137 } | 112 } |
138 | 113 |
139 void rewind() { | 114 void rewind() { |
140 // same as setCount(0) | 115 // same as setCount(0) |
141 fCount = 0; | 116 fCount = 0; |
142 } | 117 } |
143 | 118 |
144 void setCount(size_t count) { | 119 void setCount(size_t count) { |
145 if (count > fReserve) { | 120 if (count > fReserve) { |
146 this->growBy(count - fCount); | 121 this->growBy(count - fCount); |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
323 visitor(*curr); | 298 visitor(*curr); |
324 } | 299 } |
325 } | 300 } |
326 } | 301 } |
327 | 302 |
328 #ifdef SK_DEBUG | 303 #ifdef SK_DEBUG |
329 void validate() const { | 304 void validate() const { |
330 SkASSERT((fReserve == 0 && fArray == NULL) || | 305 SkASSERT((fReserve == 0 && fArray == NULL) || |
331 (fReserve > 0 && fArray != NULL)); | 306 (fReserve > 0 && fArray != NULL)); |
332 SkASSERT(fCount <= fReserve); | 307 SkASSERT(fCount <= fReserve); |
333 SkASSERT(fData == (ArrayT*)fArray); | |
334 } | 308 } |
335 #endif | 309 #endif |
336 | 310 |
311 protected: | |
312 template <size_t N> SkTDArray(SkAlignedSTStorage<N, T>* storage) { | |
313 this->init(NULL, 0, (T*)storage->get(), N); | |
314 } | |
315 template <size_t N> SkTDArray(const T src[], size_t count, SkAlignedSTStorag e<N, T>* storage) { | |
316 this->init(src, count, (T*)storage->get(), N); | |
317 } | |
318 template <size_t N> SkTDArray(const SkTDArray<T>& src, SkAlignedSTStorage<N, T>* storage) { | |
319 this->init(src.fData, src.fCount, (T*)storage->get(), N); | |
320 } | |
321 | |
322 void init(const T* src, size_t count, T* preAllocStorage, size_t preAllocCou nt) { | |
323 SkASSERT(src || count == 0); | |
324 | |
325 fArray = NULL; | |
326 fPreAllocMemArray = preAllocStorage; | |
327 fReserve = 0; | |
328 fCount = 0; | |
329 fPreAllocMemArraySize = preAllocCount; | |
330 | |
331 if (count) { | |
332 fArray = fPreAllocMemArray; | |
333 fReserve = fPreAllocMemArraySize; | |
334 fCount = count; | |
335 if (NULL == fArray || fCount > fReserve) { | |
336 fArray = (T*)sk_malloc_throw(fCount * sizeof(T)); | |
337 fReserve = fCount = count; | |
338 } | |
339 memcpy(fArray, src, sizeof(T) * count); | |
340 } | |
341 } | |
342 | |
337 private: | 343 private: |
338 #ifdef SK_DEBUG | 344 T* fArray; |
339 enum { | 345 T* fPreAllocMemArray; |
340 kDebugArraySize = 16 | 346 size_t fReserve, fCount, fPreAllocMemArraySize; |
341 }; | |
342 typedef T ArrayT[kDebugArraySize]; | |
343 ArrayT* fData; | |
344 #endif | |
345 T* fArray; | |
346 size_t fReserve, fCount; | |
347 | 347 |
348 void growBy(size_t extra) { | 348 void growBy(size_t extra) { |
349 SkASSERT(extra); | 349 SkASSERT(extra); |
350 | 350 |
351 if (fCount + extra > fReserve) { | 351 if (fCount + extra > fReserve) { |
352 if (NULL == fArray && fCount + extra <= fPreAllocMemArraySize) { | |
bungeman-skia
2013/04/26 16:26:17
Note that the same effect can be had by placing
i
| |
353 fArray = fPreAllocMemArray; | |
354 fReserve = fPreAllocMemArraySize; | |
355 fCount += extra; | |
356 return; | |
357 } | |
358 | |
352 size_t size = fCount + extra + 4; | 359 size_t size = fCount + extra + 4; |
353 size += size >> 2; | 360 size += size >> 2; |
354 | 361 |
355 fArray = (T*)sk_realloc_throw(fArray, size * sizeof(T)); | 362 if (fArray == fPreAllocMemArray) { |
356 #ifdef SK_DEBUG | 363 fArray = (T*)sk_malloc_throw(size * sizeof(T)); |
357 fData = (ArrayT*)fArray; | 364 memcpy(fArray, fPreAllocMemArray, fCount * sizeof(T)); |
358 #endif | 365 } else { |
366 fArray = (T*)sk_realloc_throw(fArray, size * sizeof(T)); | |
367 } | |
359 fReserve = size; | 368 fReserve = size; |
360 } | 369 } |
361 fCount += extra; | 370 fCount += extra; |
362 } | 371 } |
363 }; | 372 }; |
364 | 373 |
374 | |
375 /** | |
376 * Subclass of SkTDArray that contains a preallocated memory block for the array . | |
377 */ | |
378 template <size_t N, typename T> | |
379 class SkSTDArray : public SkTDArray<T> { | |
380 private: | |
381 typedef SkTDArray<T> INHERITED; | |
382 | |
383 public: | |
384 SkSTDArray() : INHERITED(&fStorage) { | |
385 } | |
386 | |
387 SkSTDArray(const T* src, int count) : INHERITED(src, count, &fStorage) { | |
388 } | |
389 | |
390 SkSTDArray(const SkSTDArray& src) : INHERITED(src, &fStorage) { | |
391 } | |
392 | |
393 explicit SkSTDArray(const INHERITED& src) : INHERITED(src, &fStorage) { | |
394 } | |
395 | |
396 SkSTDArray& operator= (const SkSTDArray& that) { | |
397 return *this = *(const INHERITED*)&that; | |
398 } | |
399 | |
400 SkSTDArray& operator= (const INHERITED& that) { | |
401 INHERITED::operator=(that); | |
402 return *this; | |
403 } | |
404 | |
405 private: | |
406 SkAlignedSTStorage<N, T> fStorage; | |
407 }; | |
408 | |
365 #endif | 409 #endif |
OLD | NEW |