}
+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,
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;
* 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;
}
/**
*/
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;
}
/**
*/
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;
}
/**
SkASSERT(fCount >= n);
fCount -= n;
for (int i = 0; i < n; ++i) {
- fItemArray[i].~T();
+ fItemArray[fCount + i].~T();
}
this->checkRealloc(0);
}
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);
}
}
+ 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*);
};
};
+// 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.
*/
*/
template <size_t N, typename T> class SkAutoSTArray : SkNoncopyable {
public:
+ /** Initialize with no objects */
+ SkAutoSTArray() {
+ fArray = NULL;
+ fCount = 0;
+ }
+
/** Allocate count number of T elements
*/
SkAutoSTArray(size_t count) {
- fCount = count;
- if (count > N) {
- fArray = (T*) sk_malloc_throw(count * sizeof(T));
- } else if (count > 0) {
- fArray = (T*) fStorage;
- } else {
- fArray = NULL;
- return;
- }
- T* iter = fArray;
- T* stop = fArray + count;
- while (iter < stop) {
- SkNEW_PLACEMENT(iter++, T);
- }
+ fArray = NULL;
+ fCount = 0;
+ this->reset(count);
}
~SkAutoSTArray() {
+ this->reset(0);
+ }
+
+ /** Destroys previous objects in the array and default constructs count number of objects */
+ void reset(size_t count) {
T* start = fArray;
T* iter = start + fCount;
while (iter > start) {
(--iter)->~T();
}
- if (fCount > N) {
- sk_free(fArray);
+
+ if (fCount != count) {
+ if (count > N) {
+ sk_free(fArray);
+ }
+
+ if (count > N) {
+ fArray = (T*) sk_malloc_throw(count * sizeof(T));
+ } else if (count > 0) {
+ fArray = (T*) fStorage;
+ } else {
+ fArray = NULL;
+ return;
+ }
+
+ fCount = count;
+ }
+
+ iter = fArray;
+ T* stop = fArray + count;
+ while (iter < stop) {
+ SkNEW_PLACEMENT(iter++, T);
}
}