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 | |
76 SkTSwap(fData, other.fData); | |
77 #endif | |
78 SkTSwap(fReserve, other.fReserve); | 55 SkTSwap(fReserve, other.fReserve); |
79 SkTSwap(fCount, other.fCount); | 56 SkTSwap(fCount, other.fCount); |
80 } | 57 } |
81 | 58 |
82 /** Return a ptr to the array of data, to be freed with sk_free. This also | 59 /** Return a ptr to the array of data, to be freed with sk_free. This also |
83 resets the SkTDArray to be empty. | 60 resets the SkTDArray to be empty. |
84 */ | 61 */ |
85 T* detach() { | 62 T* detach() { |
86 T* array = fArray; | 63 T* array = fArray; |
87 fArray = NULL; | 64 if (fArray == fPreAllocMemArray) { |
reed1
2013/04/26 16:06:52
&& fCount > 0 ?
bungeman-skia
2013/04/26 16:26:16
I did this equivalently in PS5 with '&& fArray !=
| |
88 fReserve = fCount = 0; | 65 array = (T*)sk_malloc_throw(fCount * sizeof(T)); |
89 SkDEBUGCODE(fData = NULL;) | 66 memcpy(array, fPreAllocMemArray, fCount * sizeof(T)); |
67 } | |
68 this->init(NULL, 0, fPreAllocMemArray, fPreAllocMemArraySize); | |
90 return array; | 69 return array; |
91 } | 70 } |
92 | 71 |
93 bool isEmpty() const { return fCount == 0; } | 72 bool isEmpty() const { return fCount == 0; } |
94 | 73 |
95 /** | 74 /** |
96 * Return the number of elements in the array | 75 * Return the number of elements in the array |
97 */ | 76 */ |
98 int count() const { return (int)fCount; } | 77 int count() const { return (int)fCount; } |
99 | 78 |
(...skipping 17 matching lines...) Expand all Loading... | |
117 } | 96 } |
118 | 97 |
119 T& getAt(int index) { | 98 T& getAt(int index) { |
120 return (*this)[index]; | 99 return (*this)[index]; |
121 } | 100 } |
122 const T& getAt(int index) const { | 101 const T& getAt(int index) const { |
123 return (*this)[index]; | 102 return (*this)[index]; |
124 } | 103 } |
125 | 104 |
126 void reset() { | 105 void reset() { |
127 if (fArray) { | 106 if (fArray != fPreAllocMemArray) { |
128 sk_free(fArray); | 107 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 } | 108 } |
109 this->init(NULL, 0, fPreAllocMemArray, fPreAllocMemArraySize); | |
137 } | 110 } |
138 | 111 |
139 void rewind() { | 112 void rewind() { |
140 // same as setCount(0) | 113 // same as setCount(0) |
141 fCount = 0; | 114 fCount = 0; |
142 } | 115 } |
143 | 116 |
144 void setCount(size_t count) { | 117 void setCount(size_t count) { |
145 if (count > fReserve) { | 118 if (count > fReserve) { |
146 this->growBy(count - fCount); | 119 this->growBy(count - fCount); |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
323 visitor(*curr); | 296 visitor(*curr); |
324 } | 297 } |
325 } | 298 } |
326 } | 299 } |
327 | 300 |
328 #ifdef SK_DEBUG | 301 #ifdef SK_DEBUG |
329 void validate() const { | 302 void validate() const { |
330 SkASSERT((fReserve == 0 && fArray == NULL) || | 303 SkASSERT((fReserve == 0 && fArray == NULL) || |
331 (fReserve > 0 && fArray != NULL)); | 304 (fReserve > 0 && fArray != NULL)); |
332 SkASSERT(fCount <= fReserve); | 305 SkASSERT(fCount <= fReserve); |
333 SkASSERT(fData == (ArrayT*)fArray); | |
334 } | 306 } |
335 #endif | 307 #endif |
336 | 308 |
309 protected: | |
310 template <size_t N> SkTDArray(SkAlignedSTStorage<N, T>* storage) { | |
311 this->init(NULL, 0, (T*)storage->get(), N); | |
312 } | |
313 template <size_t N> SkTDArray(const T src[], size_t count, SkAlignedSTStorag e<N, T>* storage) { | |
314 this->init(src, count, (T*)storage->get(), N); | |
315 } | |
316 template <size_t N> SkTDArray(const SkTDArray<T>& src, SkAlignedSTStorage<N, T>* storage) { | |
317 this->init(src.fData, src.fCount, (T*)storage->get(), N); | |
318 } | |
319 | |
320 void init(const T* src, size_t count, T* preAllocStorage, size_t preAllocCou nt) { | |
321 SkASSERT(src || count == 0); | |
322 | |
323 fCount = count; | |
324 fReserve = preAllocCount; | |
325 fPreAllocMemArray = preAllocStorage; | |
326 fPreAllocMemArraySize = preAllocCount; | |
327 fArray = preAllocStorage; | |
328 if (count) { | |
329 if (NULL == preAllocStorage || fCount > fReserve) { | |
330 fArray = (T*)sk_malloc_throw(fCount * sizeof(T)); | |
331 fReserve = fCount = count; | |
332 } | |
333 memcpy(fArray, src, sizeof(T) * count); | |
334 } | |
335 } | |
336 | |
337 private: | 337 private: |
338 #ifdef SK_DEBUG | 338 T* fArray; |
339 enum { | 339 T* fPreAllocMemArray; |
340 kDebugArraySize = 16 | 340 size_t fReserve, fCount, fPreAllocMemArraySize; |
341 }; | |
342 typedef T ArrayT[kDebugArraySize]; | |
343 ArrayT* fData; | |
bungeman-skia
2013/04/25 22:41:30
I removed fData here as it was somewhat of a pain
| |
344 #endif | |
345 T* fArray; | |
346 size_t fReserve, fCount; | |
347 | 341 |
348 void growBy(size_t extra) { | 342 void growBy(size_t extra) { |
349 SkASSERT(extra); | 343 SkASSERT(extra); |
350 | 344 |
351 if (fCount + extra > fReserve) { | 345 if (fCount + extra > fReserve) { |
352 size_t size = fCount + extra + 4; | 346 size_t size = fCount + extra + 4; |
353 size += size >> 2; | 347 size += size >> 2; |
354 | 348 |
355 fArray = (T*)sk_realloc_throw(fArray, size * sizeof(T)); | 349 if (fArray == fPreAllocMemArray) { |
356 #ifdef SK_DEBUG | 350 fArray = (T*)sk_malloc_throw(size * sizeof(T)); |
357 fData = (ArrayT*)fArray; | 351 memcpy(fArray, fPreAllocMemArray, fCount * sizeof(T)); |
358 #endif | 352 } else { |
353 fArray = (T*)sk_realloc_throw(fArray, size * sizeof(T)); | |
354 } | |
359 fReserve = size; | 355 fReserve = size; |
360 } | 356 } |
361 fCount += extra; | 357 fCount += extra; |
362 } | 358 } |
363 }; | 359 }; |
364 | 360 |
361 | |
362 /** | |
363 * Subclass of SkTDArray that contains a preallocated memory block for the array . | |
364 */ | |
365 template <size_t N, typename T> | |
reed1
2013/04/26 16:06:52
dox: N is the number of elements or the number of
bungeman-skia
2013/04/26 16:26:16
The number of elements. Will doc.
| |
366 class SkSTDArray : public SkTDArray<T> { | |
367 private: | |
368 typedef SkTDArray<T> INHERITED; | |
369 | |
370 public: | |
371 SkSTDArray() : INHERITED(&fStorage) { | |
372 } | |
373 | |
374 SkSTDArray(const T* src, int count) : INHERITED(src, count, &fStorage) { | |
375 } | |
376 | |
377 SkSTDArray(const SkSTDArray& src) : INHERITED(src, &fStorage) { | |
reed1
2013/04/26 16:06:52
Do we need to support copying from another S versi
bungeman-skia
2013/04/26 16:26:16
I modeled this after SkTArray/SkSTArray, which is
| |
378 } | |
379 | |
380 explicit SkSTDArray(const INHERITED& src) : INHERITED(src, &fStorage) { | |
381 } | |
382 | |
383 SkSTDArray& operator= (const SkSTDArray& that) { | |
384 return *this = *(const INHERITED*)&that; | |
385 } | |
386 | |
387 SkSTDArray& operator= (const INHERITED& that) { | |
388 INHERITED::operator=(that); | |
389 return *this; | |
390 } | |
391 | |
392 private: | |
393 SkAlignedSTStorage<N, T> fStorage; | |
394 }; | |
395 | |
365 #endif | 396 #endif |
OLD | NEW |