| 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 |