OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #ifndef SkTArray_DEFINED | 8 #ifndef SkTArray_DEFINED |
9 #define SkTArray_DEFINED | 9 #define SkTArray_DEFINED |
10 | 10 |
(...skipping 23 matching lines...) Expand all Loading... |
34 template<typename T> | 34 template<typename T> |
35 inline void copyAndDelete(SkTArray<T, false>* self, char* newMemArray) { | 35 inline void copyAndDelete(SkTArray<T, false>* self, char* newMemArray) { |
36 for (int i = 0; i < self->fCount; ++i) { | 36 for (int i = 0; i < self->fCount; ++i) { |
37 SkNEW_PLACEMENT_ARGS(newMemArray + sizeof(T) * i, T, (self->fItemArray[i
])); | 37 SkNEW_PLACEMENT_ARGS(newMemArray + sizeof(T) * i, T, (self->fItemArray[i
])); |
38 self->fItemArray[i].~T(); | 38 self->fItemArray[i].~T(); |
39 } | 39 } |
40 } | 40 } |
41 | 41 |
42 } | 42 } |
43 | 43 |
| 44 template <typename T, bool MEM_COPY> void* operator new(size_t, SkTArray<T, MEM_
COPY>*, int); |
| 45 |
44 /** When MEM_COPY is true T will be bit copied when moved. | 46 /** When MEM_COPY is true T will be bit copied when moved. |
45 When MEM_COPY is false, T will be copy constructed / destructed. | 47 When MEM_COPY is false, T will be copy constructed / destructed. |
46 In all cases T's constructor will be called on allocation, | 48 In all cases T's constructor will be called on allocation, |
47 and its destructor will be called from this object's destructor. | 49 and its destructor will be called from this object's destructor. |
48 */ | 50 */ |
49 template <typename T, bool MEM_COPY> class SkTArray { | 51 template <typename T, bool MEM_COPY> class SkTArray { |
50 public: | 52 public: |
51 /** | 53 /** |
52 * Creates an empty array with no initial storage | 54 * Creates an empty array with no initial storage |
53 */ | 55 */ |
(...skipping 30 matching lines...) Expand all Loading... |
84 } | 86 } |
85 | 87 |
86 /** | 88 /** |
87 * assign copy of array to this | 89 * assign copy of array to this |
88 */ | 90 */ |
89 SkTArray& operator =(const SkTArray& array) { | 91 SkTArray& operator =(const SkTArray& array) { |
90 for (int i = 0; i < fCount; ++i) { | 92 for (int i = 0; i < fCount; ++i) { |
91 fItemArray[i].~T(); | 93 fItemArray[i].~T(); |
92 } | 94 } |
93 fCount = 0; | 95 fCount = 0; |
94 checkRealloc((int)array.count()); | 96 this->checkRealloc((int)array.count()); |
95 fCount = array.count(); | 97 fCount = array.count(); |
96 SkTArrayExt::copy(this, static_cast<const T*>(array.fMemArray)); | 98 SkTArrayExt::copy(this, static_cast<const T*>(array.fMemArray)); |
97 return *this; | 99 return *this; |
98 } | 100 } |
99 | 101 |
100 virtual ~SkTArray() { | 102 virtual ~SkTArray() { |
101 for (int i = 0; i < fCount; ++i) { | 103 for (int i = 0; i < fCount; ++i) { |
102 fItemArray[i].~T(); | 104 fItemArray[i].~T(); |
103 } | 105 } |
104 if (fMemArray != fPreAllocMemArray) { | 106 if (fMemArray != fPreAllocMemArray) { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 * Is the array empty. | 154 * Is the array empty. |
153 */ | 155 */ |
154 bool empty() const { return !fCount; } | 156 bool empty() const { return !fCount; } |
155 | 157 |
156 /** | 158 /** |
157 * Adds 1 new default-constructed T value and returns in by reference. Note | 159 * Adds 1 new default-constructed T value and returns in by reference. Note |
158 * the reference only remains valid until the next call that adds or removes | 160 * the reference only remains valid until the next call that adds or removes |
159 * elements. | 161 * elements. |
160 */ | 162 */ |
161 T& push_back() { | 163 T& push_back() { |
162 this->checkRealloc(1); | 164 T* newT = reinterpret_cast<T*>(this->push_back_raw(1)); |
163 SkNEW_PLACEMENT((char*)fMemArray + sizeof(T) * fCount, T); | 165 SkNEW_PLACEMENT(newT, T); |
164 ++fCount; | 166 return *newT; |
165 return fItemArray[fCount-1]; | |
166 } | 167 } |
167 | 168 |
168 /** | 169 /** |
169 * Version of above that uses a copy constructor to initialize the new item | 170 * Version of above that uses a copy constructor to initialize the new item |
170 */ | 171 */ |
171 T& push_back(const T& t) { | 172 T& push_back(const T& t) { |
172 this->checkRealloc(1); | 173 T* newT = reinterpret_cast<T*>(this->push_back_raw(1)); |
173 SkNEW_PLACEMENT_ARGS((char*)fMemArray + sizeof(T) * fCount, T, (t)); | 174 SkNEW_PLACEMENT_ARGS(newT, T, (t)); |
174 ++fCount; | 175 return *newT; |
175 return fItemArray[fCount-1]; | |
176 } | 176 } |
177 | 177 |
178 /** | 178 /** |
179 * Allocates n more default T values, and returns the address of the start | 179 * Allocates n more default T values, and returns the address of the start |
180 * of that new range. Note: this address is only valid until the next API | 180 * of that new range. Note: this address is only valid until the next API |
181 * call made on the array that might add or remove elements. | 181 * call made on the array that might add or remove elements. |
182 */ | 182 */ |
183 T* push_back_n(int n) { | 183 T* push_back_n(int n) { |
184 SkASSERT(n >= 0); | 184 SkASSERT(n >= 0); |
185 this->checkRealloc(n); | 185 T* newTs = reinterpret_cast<T*>(this->push_back_raw(n)); |
186 for (int i = 0; i < n; ++i) { | 186 for (int i = 0; i < n; ++i) { |
187 SkNEW_PLACEMENT(fItemArray + fCount + i, T); | 187 SkNEW_PLACEMENT(newTs + i, T); |
188 } | 188 } |
189 fCount += n; | 189 return newTs; |
190 return fItemArray + fCount - n; | |
191 } | 190 } |
192 | 191 |
193 /** | 192 /** |
194 * Version of above that uses a copy constructor to initialize all n items | 193 * Version of above that uses a copy constructor to initialize all n items |
195 * to the same T. | 194 * to the same T. |
196 */ | 195 */ |
197 T* push_back_n(int n, const T& t) { | 196 T* push_back_n(int n, const T& t) { |
198 SkASSERT(n >= 0); | 197 SkASSERT(n >= 0); |
199 this->checkRealloc(n); | 198 T* newTs = reinterpret_cast<T*>(this->push_back_raw(n)); |
200 for (int i = 0; i < n; ++i) { | 199 for (int i = 0; i < n; ++i) { |
201 SkNEW_PLACEMENT_ARGS(fItemArray + fCount + i, T, (t)); | 200 SkNEW_PLACEMENT_ARGS(newTs[i], T, (t)); |
202 } | 201 } |
203 fCount += n; | 202 return newTs; |
204 return fItemArray + fCount - n; | |
205 } | 203 } |
206 | 204 |
207 /** | 205 /** |
208 * Version of above that uses a copy constructor to initialize the n items | 206 * Version of above that uses a copy constructor to initialize the n items |
209 * to separate T values. | 207 * to separate T values. |
210 */ | 208 */ |
211 T* push_back_n(int n, const T t[]) { | 209 T* push_back_n(int n, const T t[]) { |
212 SkASSERT(n >= 0); | 210 SkASSERT(n >= 0); |
213 this->checkRealloc(n); | 211 this->checkRealloc(n); |
214 for (int i = 0; i < n; ++i) { | 212 for (int i = 0; i < n; ++i) { |
(...skipping 14 matching lines...) Expand all Loading... |
229 } | 227 } |
230 | 228 |
231 /** | 229 /** |
232 * Removes the last n elements. Not safe to call when count() < n. | 230 * Removes the last n elements. Not safe to call when count() < n. |
233 */ | 231 */ |
234 void pop_back_n(int n) { | 232 void pop_back_n(int n) { |
235 SkASSERT(n >= 0); | 233 SkASSERT(n >= 0); |
236 SkASSERT(fCount >= n); | 234 SkASSERT(fCount >= n); |
237 fCount -= n; | 235 fCount -= n; |
238 for (int i = 0; i < n; ++i) { | 236 for (int i = 0; i < n; ++i) { |
239 fItemArray[i].~T(); | 237 fItemArray[fCount + i].~T(); |
240 } | 238 } |
241 this->checkRealloc(0); | 239 this->checkRealloc(0); |
242 } | 240 } |
243 | 241 |
244 /** | 242 /** |
245 * Pushes or pops from the back to resize. Pushes will be default | 243 * Pushes or pops from the back to resize. Pushes will be default |
246 * initialized. | 244 * initialized. |
247 */ | 245 */ |
248 void resize_back(int newCount) { | 246 void resize_back(int newCount) { |
249 SkASSERT(newCount >= 0); | 247 SkASSERT(newCount >= 0); |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
377 fMemArray = sk_malloc_throw(fAllocCount * sizeof(T)); | 375 fMemArray = sk_malloc_throw(fAllocCount * sizeof(T)); |
378 } | 376 } |
379 | 377 |
380 SkTArrayExt::copy(this, array); | 378 SkTArrayExt::copy(this, array); |
381 } | 379 } |
382 | 380 |
383 private: | 381 private: |
384 | 382 |
385 static const int gMIN_ALLOC_COUNT = 8; | 383 static const int gMIN_ALLOC_COUNT = 8; |
386 | 384 |
| 385 // Helper function that makes space for n objects, adjusts the count, but do
es not initialize |
| 386 // the new objects. |
| 387 void* push_back_raw(int n) { |
| 388 this->checkRealloc(n); |
| 389 void* ptr = fItemArray + fCount; |
| 390 fCount += n; |
| 391 return ptr; |
| 392 } |
| 393 |
387 inline void checkRealloc(int delta) { | 394 inline void checkRealloc(int delta) { |
388 SkASSERT(fCount >= 0); | 395 SkASSERT(fCount >= 0); |
389 SkASSERT(fAllocCount >= 0); | 396 SkASSERT(fAllocCount >= 0); |
390 | 397 |
391 SkASSERT(-delta <= fCount); | 398 SkASSERT(-delta <= fCount); |
392 | 399 |
393 int newCount = fCount + delta; | 400 int newCount = fCount + delta; |
394 int newAllocCount = fAllocCount; | 401 int newAllocCount = fAllocCount; |
395 | 402 |
396 if (newCount > fAllocCount || newCount < (fAllocCount / 3)) { | 403 if (newCount > fAllocCount || newCount < (fAllocCount / 3)) { |
(...skipping 14 matching lines...) Expand all Loading... |
411 | 418 |
412 SkTArrayExt::copyAndDelete<T>(this, newMemArray); | 419 SkTArrayExt::copyAndDelete<T>(this, newMemArray); |
413 | 420 |
414 if (fMemArray != fPreAllocMemArray) { | 421 if (fMemArray != fPreAllocMemArray) { |
415 sk_free(fMemArray); | 422 sk_free(fMemArray); |
416 } | 423 } |
417 fMemArray = newMemArray; | 424 fMemArray = newMemArray; |
418 } | 425 } |
419 } | 426 } |
420 | 427 |
| 428 friend void* operator new<T>(size_t, SkTArray*, int); |
| 429 |
421 template<typename X> friend void SkTArrayExt::copy(SkTArray<X, true>* that,
const X*); | 430 template<typename X> friend void SkTArrayExt::copy(SkTArray<X, true>* that,
const X*); |
422 template<typename X> friend void SkTArrayExt::copyAndDelete(SkTArray<X, true
>* that, char*); | 431 template<typename X> friend void SkTArrayExt::copyAndDelete(SkTArray<X, true
>* that, char*); |
423 | 432 |
424 template<typename X> friend void SkTArrayExt::copy(SkTArray<X, false>* that,
const X*); | 433 template<typename X> friend void SkTArrayExt::copy(SkTArray<X, false>* that,
const X*); |
425 template<typename X> friend void SkTArrayExt::copyAndDelete(SkTArray<X, fals
e>* that, char*); | 434 template<typename X> friend void SkTArrayExt::copyAndDelete(SkTArray<X, fals
e>* that, char*); |
426 | 435 |
427 int fReserveCount; | 436 int fReserveCount; |
428 int fCount; | 437 int fCount; |
429 int fAllocCount; | 438 int fAllocCount; |
430 void* fPreAllocMemArray; | 439 void* fPreAllocMemArray; |
431 union { | 440 union { |
432 T* fItemArray; | 441 T* fItemArray; |
433 void* fMemArray; | 442 void* fMemArray; |
434 }; | 443 }; |
435 }; | 444 }; |
436 | 445 |
| 446 // Use the below macro (SkNEW_APPEND_TO_TARRAY) rather than calling this directl
y |
| 447 template <typename T, bool MEM_COPY> |
| 448 void* operator new(size_t, SkTArray<T, MEM_COPY>* array, int atIndex) { |
| 449 // Currently, we only support adding to the end of the array. When the array
class itself |
| 450 // supports random insertion then this should be updated. |
| 451 // SkASSERT(atIndex >= 0 && atIndex <= array->count()); |
| 452 SkASSERT(atIndex == array->count()); |
| 453 return array->push_back_raw(1); |
| 454 } |
| 455 |
| 456 // Constructs a new object as the last element of an SkTArray. |
| 457 #define SkNEW_APPEND_TO_TARRAY(array_ptr, type_name, args) \ |
| 458 (new ((array_ptr), (array_ptr)->count()) type_name args) |
| 459 |
| 460 |
437 /** | 461 /** |
438 * Subclass of SkTArray that contains a preallocated memory block for the array. | 462 * Subclass of SkTArray that contains a preallocated memory block for the array. |
439 */ | 463 */ |
440 template <int N, typename T, bool MEM_COPY = false> | 464 template <int N, typename T, bool MEM_COPY = false> |
441 class SkSTArray : public SkTArray<T, MEM_COPY> { | 465 class SkSTArray : public SkTArray<T, MEM_COPY> { |
442 private: | 466 private: |
443 typedef SkTArray<T, MEM_COPY> INHERITED; | 467 typedef SkTArray<T, MEM_COPY> INHERITED; |
444 | 468 |
445 public: | 469 public: |
446 SkSTArray() : INHERITED(&fStorage) { | 470 SkSTArray() : INHERITED(&fStorage) { |
(...skipping 18 matching lines...) Expand all Loading... |
465 SkSTArray& operator= (const INHERITED& array) { | 489 SkSTArray& operator= (const INHERITED& array) { |
466 INHERITED::operator=(array); | 490 INHERITED::operator=(array); |
467 return *this; | 491 return *this; |
468 } | 492 } |
469 | 493 |
470 private: | 494 private: |
471 SkAlignedSTStorage<N,T> fStorage; | 495 SkAlignedSTStorage<N,T> fStorage; |
472 }; | 496 }; |
473 | 497 |
474 #endif | 498 #endif |
OLD | NEW |