Index: include/core/SkTArray.h |
diff --git a/include/core/SkTArray.h b/include/core/SkTArray.h |
index 46e66871f401e7259728a2154d7f875a4812809a..13c0d71abb4e4ffb92cd5da99dd121622a789e7c 100644 |
--- a/include/core/SkTArray.h |
+++ b/include/core/SkTArray.h |
@@ -41,6 +41,8 @@ inline void copyAndDelete(SkTArray<T, false>* self, char* newMemArray) { |
} |
+template <typename T, bool MEM_COPY> void* operator new(size_t, SkTArray<T, MEM_COPY>*, int); |
+ |
/** When MEM_COPY is true T will be bit copied when moved. |
When MEM_COPY is false, T will be copy constructed / destructed. |
In all cases T's constructor will be called on allocation, |
@@ -91,7 +93,7 @@ public: |
fItemArray[i].~T(); |
} |
fCount = 0; |
- checkRealloc((int)array.count()); |
+ this->checkRealloc((int)array.count()); |
fCount = array.count(); |
SkTArrayExt::copy(this, static_cast<const T*>(array.fMemArray)); |
return *this; |
@@ -159,20 +161,18 @@ public: |
* elements. |
*/ |
T& push_back() { |
- this->checkRealloc(1); |
- SkNEW_PLACEMENT((char*)fMemArray + sizeof(T) * fCount, T); |
- ++fCount; |
- return fItemArray[fCount-1]; |
+ T* newT = reinterpret_cast<T*>(this->push_back_raw(1)); |
+ SkNEW_PLACEMENT(newT, T); |
+ return *newT; |
} |
/** |
* Version of above that uses a copy constructor to initialize the new item |
*/ |
T& push_back(const T& t) { |
- this->checkRealloc(1); |
- SkNEW_PLACEMENT_ARGS((char*)fMemArray + sizeof(T) * fCount, T, (t)); |
- ++fCount; |
- return fItemArray[fCount-1]; |
+ T* newT = reinterpret_cast<T*>(this->push_back_raw(1)); |
+ SkNEW_PLACEMENT_ARGS(newT, T, (t)); |
+ return *newT; |
} |
/** |
@@ -182,12 +182,11 @@ public: |
*/ |
T* push_back_n(int n) { |
SkASSERT(n >= 0); |
- this->checkRealloc(n); |
+ T* newTs = reinterpret_cast<T*>(this->push_back_raw(n)); |
for (int i = 0; i < n; ++i) { |
- SkNEW_PLACEMENT(fItemArray + fCount + i, T); |
+ SkNEW_PLACEMENT(newTs + i, T); |
} |
- fCount += n; |
- return fItemArray + fCount - n; |
+ return newTs; |
} |
/** |
@@ -196,12 +195,11 @@ public: |
*/ |
T* push_back_n(int n, const T& t) { |
SkASSERT(n >= 0); |
- this->checkRealloc(n); |
+ T* newTs = reinterpret_cast<T*>(this->push_back_raw(n)); |
for (int i = 0; i < n; ++i) { |
- SkNEW_PLACEMENT_ARGS(fItemArray + fCount + i, T, (t)); |
+ SkNEW_PLACEMENT_ARGS(newTs[i], T, (t)); |
} |
- fCount += n; |
- return fItemArray + fCount - n; |
+ return newTs; |
} |
/** |
@@ -236,7 +234,7 @@ public: |
SkASSERT(fCount >= n); |
fCount -= n; |
for (int i = 0; i < n; ++i) { |
- fItemArray[i].~T(); |
+ fItemArray[fCount + i].~T(); |
} |
this->checkRealloc(0); |
} |
@@ -384,6 +382,15 @@ private: |
static const int gMIN_ALLOC_COUNT = 8; |
+ // Helper function that makes space for n objects, adjusts the count, but does not initialize |
+ // the new objects. |
+ void* push_back_raw(int n) { |
+ this->checkRealloc(n); |
+ void* ptr = fItemArray + fCount; |
+ fCount += n; |
+ return ptr; |
+ } |
+ |
inline void checkRealloc(int delta) { |
SkASSERT(fCount >= 0); |
SkASSERT(fAllocCount >= 0); |
@@ -418,6 +425,8 @@ private: |
} |
} |
+ friend void* operator new<T>(size_t, SkTArray*, int); |
+ |
template<typename X> friend void SkTArrayExt::copy(SkTArray<X, true>* that, const X*); |
template<typename X> friend void SkTArrayExt::copyAndDelete(SkTArray<X, true>* that, char*); |
@@ -434,6 +443,21 @@ private: |
}; |
}; |
+// Use the below macro (SkNEW_APPEND_TO_TARRAY) rather than calling this directly |
+template <typename T, bool MEM_COPY> |
+void* operator new(size_t, SkTArray<T, MEM_COPY>* array, int atIndex) { |
+ // Currently, we only support adding to the end of the array. When the array class itself |
+ // supports random insertion then this should be updated. |
+ // SkASSERT(atIndex >= 0 && atIndex <= array->count()); |
+ SkASSERT(atIndex == array->count()); |
+ return array->push_back_raw(1); |
+} |
+ |
+// Constructs a new object as the last element of an SkTArray. |
+#define SkNEW_APPEND_TO_TARRAY(array_ptr, type_name, args) \ |
+ (new ((array_ptr), (array_ptr)->count()) type_name args) |
+ |
+ |
/** |
* Subclass of SkTArray that contains a preallocated memory block for the array. |
*/ |