GrTArray->SkTArray & docs
Review URL: http://codereview.appspot.com/5005045/
git-svn-id: http://skia.googlecode.com/svn/trunk@2265 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/include/GrAllocator.h b/gpu/include/GrAllocator.h
index ae46938..7652be3 100755
--- a/gpu/include/GrAllocator.h
+++ b/gpu/include/GrAllocator.h
@@ -12,7 +12,7 @@
#define GrAllocator_DEFINED
#include "GrConfig.h"
-#include "GrTArray.h"
+#include "SkTArray.h"
class GrAllocator {
public:
@@ -128,7 +128,7 @@
private:
static const int NUM_INIT_BLOCK_PTRS = 8;
- GrTArray<void*> fBlocks;
+ SkTArray<void*> fBlocks;
size_t fBlockSize;
char fBlockInitialStorage[NUM_INIT_BLOCK_PTRS*sizeof(void*)];
size_t fItemSize;
@@ -163,7 +163,7 @@
* and the size of subsequent blocks.
*/
template <int N>
- GrTAllocator(GrAlignedSTStorage<N,T>* initialBlock)
+ GrTAllocator(SkAlignedSTStorage<N,T>* initialBlock)
: fAllocator(sizeof(T), N, initialBlock->get()) {}
/**
diff --git a/gpu/include/GrClip.h b/gpu/include/GrClip.h
index 4abd8da..9e235bf 100644
--- a/gpu/include/GrClip.h
+++ b/gpu/include/GrClip.h
@@ -14,9 +14,9 @@
#include "GrClipIterator.h"
#include "GrRect.h"
#include "GrPath.h"
-#include "GrTArray.h"
#include "GrTemplates.h"
+#include "SkTArray.h"
class GrClip {
public:
@@ -135,8 +135,8 @@
enum {
kPreAllocElements = 4,
};
- GrAlignedSTStorage<kPreAllocElements, Element> fListStorage;
- GrTArray<Element> fList;
+ SkAlignedSTStorage<kPreAllocElements, Element> fListStorage;
+ SkTArray<Element> fList;
};
#endif
diff --git a/gpu/include/GrTArray.h b/gpu/include/GrTArray.h
deleted file mode 100644
index 5477d25..0000000
--- a/gpu/include/GrTArray.h
+++ /dev/null
@@ -1,335 +0,0 @@
-
-/*
- * Copyright 2010 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-
-#ifndef GrTArray_DEFINED
-#define GrTArray_DEFINED
-
-#include <new>
-#include "GrTypes.h"
-#include "GrTemplates.h"
-
-// DATA_TYPE indicates that T has a trivial cons, destructor
-// and can be shallow-copied
-template <typename T, bool DATA_TYPE = false> class GrTArray {
-public:
- GrTArray() {
- fCount = 0;
- fReserveCount = MIN_ALLOC_COUNT;
- fAllocCount = 0;
- fMemArray = NULL;
- fPreAllocMemArray = NULL;
- }
-
- explicit GrTArray(int reserveCount) {
- GrAssert(reserveCount >= 0);
- fCount = 0;
- fReserveCount = reserveCount > MIN_ALLOC_COUNT ? reserveCount :
- MIN_ALLOC_COUNT;
- fAllocCount = fReserveCount;
- fMemArray = GrMalloc(sizeof(T) * fReserveCount);
- fPreAllocMemArray = NULL;
- }
-
- template <int N>
- GrTArray(GrAlignedSTStorage<N,T>* storage) {
- GrAssert(N > 0);
- fCount = 0;
- fReserveCount = N;
- fAllocCount = N;
- fMemArray = storage->get();
- fPreAllocMemArray = storage->get();
- }
-
- GrTArray(void* preAllocStorage, int preAllocCount) {
- GrAssert(preAllocCount >= 0);
- // we allow NULL,0 args and revert to the default cons. behavior
- // this makes it possible for a owner-object to use same constructor
- // to get either prealloc or nonprealloc behavior based using same line
- GrAssert((NULL == preAllocStorage) == !preAllocCount);
-
- fCount = 0;
- fReserveCount = preAllocCount > 0 ? preAllocCount :
- MIN_ALLOC_COUNT;
- fAllocCount = preAllocCount;
- fMemArray = preAllocStorage;
- fPreAllocMemArray = preAllocStorage;
- }
-
- explicit GrTArray(const GrTArray& array) {
- fCount = array.count();
- fReserveCount = MIN_ALLOC_COUNT;
- fAllocCount = GrMax(fReserveCount, fCount);
- fMemArray = GrMalloc(sizeof(T) * fAllocCount);
- fPreAllocMemArray = NULL;
-
- if (DATA_TYPE) {
- memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
- } else {
- for (int i = 0; i < fCount; ++i) {
- new (fItemArray + i) T(array[i]);
- }
- }
- }
-
- GrTArray(const T* array, int count) {
- GrAssert(count >= 0);
- fCount = count;
- fReserveCount = MIN_ALLOC_COUNT;
- fAllocCount = GrMax(fReserveCount, fCount);
- fMemArray = GrMalloc(sizeof(T) * fAllocCount);
- fPreAllocMemArray = NULL;
- if (DATA_TYPE) {
- memcpy(fMemArray, array, sizeof(T) * fCount);
- } else {
- for (int i = 0; i < fCount; ++i) {
- new (fItemArray + i) T(array[i]);
- }
- }
- }
-
- GrTArray(const GrTArray& array,
- void* preAllocStorage, int preAllocCount) {
-
- GrAssert(preAllocCount >= 0);
-
- // for same reason as non-copying cons we allow NULL, 0 for prealloc
- GrAssert((NULL == preAllocStorage) == !preAllocCount);
-
- fCount = array.count();
- fReserveCount = preAllocCount > 0 ? preAllocCount :
- MIN_ALLOC_COUNT;
- fPreAllocMemArray = preAllocStorage;
-
- if (fReserveCount >= fCount && preAllocCount) {
- fAllocCount = fReserveCount;
- fMemArray = preAllocStorage;
- } else {
- fAllocCount = GrMax(fCount, fReserveCount);
- fMemArray = GrMalloc(fAllocCount * sizeof(T));
- }
-
- if (DATA_TYPE) {
- memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
- } else {
- for (int i = 0; i < fCount; ++i) {
- new (fItemArray + i) T(array[i]);
- }
- }
- }
-
- GrTArray(const T* array, int count,
- void* preAllocStorage, int preAllocCount) {
-
- GrAssert(count >= 0);
- GrAssert(preAllocCount >= 0);
-
- // for same reason as non-copying cons we allow NULL, 0 for prealloc
- GrAssert((NULL == preAllocStorage) == !preAllocCount);
-
- fCount = count;
- fReserveCount = (preAllocCount > 0) ? preAllocCount :
- MIN_ALLOC_COUNT;
- fPreAllocMemArray = preAllocStorage;
-
- if (fReserveCount >= fCount && preAllocCount) {
- fAllocCount = fReserveCount;
- fMemArray = preAllocStorage;
- } else {
- fAllocCount = GrMax(fCount, fReserveCount);
- fMemArray = GrMalloc(fAllocCount * sizeof(T));
- }
-
- if (DATA_TYPE) {
- memcpy(fMemArray, array, sizeof(T) * fCount);
- } else {
- for (int i = 0; i < fCount; ++i) {
- new (fItemArray + i) T(array[i]);
- }
- }
- }
-
- GrTArray& operator =(const GrTArray& array) {
- for (int i = 0; i < fCount; ++i) {
- fItemArray[i].~T();
- }
- fCount = 0;
- checkRealloc((int)array.count());
- fCount = array.count();
- if (DATA_TYPE) {
- memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
- } else {
- for (int i = 0; i < fCount; ++i) {
- new (fItemArray + i) T(array[i]);
- }
- }
- return *this;
- }
-
- ~GrTArray() {
- for (int i = 0; i < fCount; ++i) {
- fItemArray[i].~T();
- }
- if (fMemArray != fPreAllocMemArray) {
- GrFree(fMemArray);
- }
- }
-
- void reset() { this->pop_back_n(fCount); }
-
- int count() const { return fCount; }
-
- bool empty() const { return !fCount; }
-
- /**
- * Adds 1 new default-constructed T value and returns in by reference. Note
- * the reference only remains valid until the next call that adds or removes
- * elements.
- */
- T& push_back() {
- checkRealloc(1);
- new ((char*)fMemArray+sizeof(T)*fCount) T;
- ++fCount;
- return fItemArray[fCount-1];
- }
-
- /**
- * Allocates n more default T values, and returns the address of the start
- * of that new range. Note: this address is only valid until the next API
- * call made on the array that might add or remove elements.
- */
- T* push_back_n(int n) {
- GrAssert(n >= 0);
- checkRealloc(n);
- for (int i = 0; i < n; ++i) {
- new (fItemArray + fCount + i) T;
- }
- fCount += n;
- return fItemArray + fCount - n;
- }
-
- void pop_back() {
- GrAssert(fCount > 0);
- --fCount;
- fItemArray[fCount].~T();
- checkRealloc(0);
- }
-
- void pop_back_n(int n) {
- GrAssert(n >= 0);
- GrAssert(fCount >= n);
- fCount -= n;
- for (int i = 0; i < n; ++i) {
- fItemArray[i].~T();
- }
- checkRealloc(0);
- }
-
- // pushes or pops from the back to resize
- void resize_back(int newCount) {
- GrAssert(newCount >= 0);
-
- if (newCount > fCount) {
- push_back_n(newCount - fCount);
- } else if (newCount < fCount) {
- pop_back_n(fCount - newCount);
- }
- }
-
- T& operator[] (int i) {
- GrAssert(i < fCount);
- GrAssert(i >= 0);
- return fItemArray[i];
- }
-
- const T& operator[] (int i) const {
- GrAssert(i < fCount);
- GrAssert(i >= 0);
- return fItemArray[i];
- }
-
- T& front() { GrAssert(fCount > 0); return fItemArray[0];}
-
- const T& front() const { GrAssert(fCount > 0); return fItemArray[0];}
-
- T& back() { GrAssert(fCount); return fItemArray[fCount - 1];}
-
- const T& back() const { GrAssert(fCount > 0); return fItemArray[fCount - 1];}
-
- T& fromBack(int i) {
- GrAssert(i >= 0);
- GrAssert(i < fCount);
- return fItemArray[fCount - i - 1];
- }
-
- const T& fromBack(int i) const {
- GrAssert(i >= 0);
- GrAssert(i < fCount);
- return fItemArray[fCount - i - 1];
- }
-
-private:
-
- static const int MIN_ALLOC_COUNT = 8;
-
- inline void checkRealloc(int delta) {
- GrAssert(fCount >= 0);
- GrAssert(fAllocCount >= 0);
-
- GrAssert(-delta <= fCount);
-
- int newCount = fCount + delta;
- int fNewAllocCount = fAllocCount;
-
- if (newCount > fAllocCount) {
- fNewAllocCount = GrMax(newCount + ((newCount + 1) >> 1),
- fReserveCount);
- } else if (newCount < fAllocCount / 3) {
- fNewAllocCount = GrMax(fAllocCount / 2, fReserveCount);
- }
-
- if (fNewAllocCount != fAllocCount) {
-
- fAllocCount = fNewAllocCount;
- char* fNewMemArray;
-
- if (fAllocCount == fReserveCount && NULL != fPreAllocMemArray) {
- fNewMemArray = (char*) fPreAllocMemArray;
- } else {
- fNewMemArray = (char*) GrMalloc(fAllocCount*sizeof(T));
- }
-
- if (DATA_TYPE) {
- memcpy(fNewMemArray, fMemArray, fCount * sizeof(T));
- } else {
- for (int i = 0; i < fCount; ++i) {
- new (fNewMemArray + sizeof(T) * i) T(fItemArray[i]);
- fItemArray[i].~T();
- }
- }
-
- if (fMemArray != fPreAllocMemArray) {
- GrFree(fMemArray);
- }
- fMemArray = fNewMemArray;
- }
- }
-
- int fReserveCount;
- int fCount;
- int fAllocCount;
- void* fPreAllocMemArray;
- union {
- T* fItemArray;
- void* fMemArray;
- };
-};
-
-#endif
-
diff --git a/gpu/include/GrTemplates.h b/gpu/include/GrTemplates.h
index 9ffa51b..63e43ee 100644
--- a/gpu/include/GrTemplates.h
+++ b/gpu/include/GrTemplates.h
@@ -25,38 +25,6 @@
}
/**
- * Reserves memory that is aligned on double and pointer boundaries.
- * Hopefully this is sufficient for all practical purposes.
- */
-template <size_t N> class GrAlignedSStorage : GrNoncopyable {
-public:
- void* get() { return fData; }
-private:
- union {
- void* fPtr;
- double fDouble;
- char fData[N];
- };
-};
-
-/**
- * Reserves memory that is aligned on double and pointer boundaries.
- * Hopefully this is sufficient for all practical purposes. Otherwise,
- * we have to do some arcane trickery to determine alignment of non-POD
- * types. Lifetime of the memory is the lifetime of the object.
- */
-template <int N, typename T> class GrAlignedSTStorage : GrNoncopyable {
-public:
- /**
- * Returns void* because this object does not initialize the
- * memory. Use placement new for types that require a cons.
- */
- void* get() { return fStorage.get(); }
-private:
- GrAlignedSStorage<sizeof(T)*N> fStorage;
-};
-
-/**
* saves value of T* in and restores in destructor
* e.g.:
* {
diff --git a/gpu/src/GrAAHairLinePathRenderer.cpp b/gpu/src/GrAAHairLinePathRenderer.cpp
index f60e7cf..d57aa3a 100644
--- a/gpu/src/GrAAHairLinePathRenderer.cpp
+++ b/gpu/src/GrAAHairLinePathRenderer.cpp
@@ -137,8 +137,8 @@
namespace {
-typedef GrTArray<SkPoint, true> PtArray;
-typedef GrTArray<int, true> IntArray;
+typedef SkTArray<SkPoint, true> PtArray;
+typedef SkTArray<int, true> IntArray;
/**
* We convert cubics to quadratics (for now).
@@ -633,8 +633,8 @@
GrMatrix viewM = fTarget->getViewMatrix();
- GrAlignedSTStorage<128, GrPoint> lineStorage;
- GrAlignedSTStorage<128, GrPoint> quadStorage;
+ SkAlignedSTStorage<128, GrPoint> lineStorage;
+ SkAlignedSTStorage<128, GrPoint> quadStorage;
PtArray lines(&lineStorage);
PtArray quads(&quadStorage);
IntArray qSubdivs;
diff --git a/gpu/src/GrBufferAllocPool.h b/gpu/src/GrBufferAllocPool.h
index f9d9e19..acf0289 100644
--- a/gpu/src/GrBufferAllocPool.h
+++ b/gpu/src/GrBufferAllocPool.h
@@ -13,7 +13,8 @@
#include "GrNoncopyable.h"
#include "GrTDArray.h"
-#include "GrTArray.h"
+
+#include "SkTArray.h"
class GrGeometryBuffer;
class GrGpu;
@@ -173,7 +174,7 @@
size_t fMinBlockSize;
BufferType fBufferType;
- GrTArray<BufferBlock> fBlocks;
+ SkTArray<BufferBlock> fBlocks;
int fPreallocBuffersInUse;
int fFirstPreallocBuffer;
SkAutoMalloc fCpuData;
diff --git a/gpu/src/GrDrawTarget.h b/gpu/src/GrDrawTarget.h
index 42723f6..1d61a18 100644
--- a/gpu/src/GrDrawTarget.h
+++ b/gpu/src/GrDrawTarget.h
@@ -1315,10 +1315,10 @@
enum {
kPreallocGeoSrcStateStackCnt = 4,
};
- GrAlignedSTStorage<kPreallocGeoSrcStateStackCnt,
+ SkAlignedSTStorage<kPreallocGeoSrcStateStackCnt,
GeometrySrcState>
fGeoSrcStateStackStorage;
- GrTArray<GeometrySrcState, true> fGeoSrcStateStack;
+ SkTArray<GeometrySrcState, true> fGeoSrcStateStack;
};
diff --git a/gpu/src/GrGpu.h b/gpu/src/GrGpu.h
index 88b50b1..e970554 100644
--- a/gpu/src/GrGpu.h
+++ b/gpu/src/GrGpu.h
@@ -509,9 +509,9 @@
enum {
kPreallocGeomPoolStateStackCnt = 4,
};
- GrAlignedSTStorage<kPreallocGeomPoolStateStackCnt,
+ SkAlignedSTStorage<kPreallocGeomPoolStateStackCnt,
GeometryPoolState> fGeoSrcStateStackStorage;
- GrTArray<GeometryPoolState, true> fGeomPoolStateStack;
+ SkTArray<GeometryPoolState, true> fGeomPoolStateStack;
mutable GrIndexBuffer* fQuadIndexBuffer; // mutable so it can be
// created on-demand
diff --git a/gpu/src/GrGpuGL.h b/gpu/src/GrGpuGL.h
index 47aca3c..b1accf6 100644
--- a/gpu/src/GrGpuGL.h
+++ b/gpu/src/GrGpuGL.h
@@ -194,7 +194,7 @@
friend class GrGLRenderTarget;
- GrTArray<GrGLStencilBuffer::Format, true> fStencilFormats;
+ SkTArray<GrGLStencilBuffer::Format, true> fStencilFormats;
// we want to clear stencil buffers when they are created. We want to clear
// the entire buffer even if it is larger than the color attachment. We
// attach it to this fbo with no color attachment to do the initial clear.
diff --git a/gpu/src/GrInOrderDrawBuffer.h b/gpu/src/GrInOrderDrawBuffer.h
index dbf6144..f0b5c9e 100644
--- a/gpu/src/GrInOrderDrawBuffer.h
+++ b/gpu/src/GrInOrderDrawBuffer.h
@@ -172,7 +172,7 @@
size_t fUsedPoolVertexBytes;
size_t fUsedPoolIndexBytes;
};
- GrTArray<GeometryPoolState> fGeoPoolStateStack;
+ SkTArray<GeometryPoolState> fGeoPoolStateStack;
enum {
@@ -183,11 +183,11 @@
kGeoPoolStatePreAllocCnt = 4,
};
- GrAlignedSTStorage<kDrawPreallocCnt, Draw> fDrawStorage;
- GrAlignedSTStorage<kStatePreallocCnt, SavedDrawState> fStateStorage;
- GrAlignedSTStorage<kClipPreallocCnt, GrClip> fClipStorage;
- GrAlignedSTStorage<kClearPreallocCnt, Clear> fClearStorage;
- GrAlignedSTStorage<kGeoPoolStatePreAllocCnt,
+ SkAlignedSTStorage<kDrawPreallocCnt, Draw> fDrawStorage;
+ SkAlignedSTStorage<kStatePreallocCnt, SavedDrawState> fStateStorage;
+ SkAlignedSTStorage<kClipPreallocCnt, GrClip> fClipStorage;
+ SkAlignedSTStorage<kClearPreallocCnt, Clear> fClearStorage;
+ SkAlignedSTStorage<kGeoPoolStatePreAllocCnt,
GeometryPoolState> fGeoStackStorage;
typedef GrDrawTarget INHERITED;
diff --git a/gpu/src/GrPathRenderer.h b/gpu/src/GrPathRenderer.h
index 815da47..b8e7a4c 100644
--- a/gpu/src/GrPathRenderer.h
+++ b/gpu/src/GrPathRenderer.h
@@ -11,9 +11,10 @@
#define GrPathRenderer_DEFINED
#include "GrDrawTarget.h"
-#include "GrTArray.h"
#include "GrPathRendererChain.h"
+#include "SkTArray.h"
+
class SkPath;
struct GrPoint;
diff --git a/gpu/src/GrPathRendererChain.h b/gpu/src/GrPathRendererChain.h
index 0f4305b..24abda4 100644
--- a/gpu/src/GrPathRendererChain.h
+++ b/gpu/src/GrPathRendererChain.h
@@ -11,7 +11,7 @@
#define GrPathRendererChain_DEFINED
#include "GrRefCnt.h"
-#include "GrTArray.h"
+#include "SkTArray.h"
class GrContext;
class GrDrawTarget;
@@ -55,8 +55,8 @@
bool fInit;
GrContext* fOwner;
UsageFlags fFlags;
- GrAlignedSTStorage<kPreAllocCount, GrPathRenderer*> fStorage;
- GrTArray<GrPathRenderer*, true> fChain;
+ SkAlignedSTStorage<kPreAllocCount, GrPathRenderer*> fStorage;
+ SkTArray<GrPathRenderer*, true> fChain;
};
GR_MAKE_BITFIELD_OPS(GrPathRendererChain::UsageFlags)
diff --git a/gyp/gpu.gyp b/gyp/gpu.gyp
index ae05baa..dc113d1 100644
--- a/gyp/gpu.gyp
+++ b/gyp/gpu.gyp
@@ -115,7 +115,6 @@
'../gpu/include/GrStencil.h',
'../gpu/include/GrStopwatch.h',
'../gpu/include/GrStringBuilder.h',
- '../gpu/include/GrTArray.h',
'../gpu/include/GrTBSearch.h',
'../gpu/include/GrTDArray.h',
'../gpu/include/GrTextContext.h',
diff --git a/include/core/SkTArray.h b/include/core/SkTArray.h
new file mode 100644
index 0000000..7d74b6a
--- /dev/null
+++ b/include/core/SkTArray.h
@@ -0,0 +1,402 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+
+#ifndef SkTArray_DEFINED
+#define SkTArray_DEFINED
+
+#include <new>
+#include "SkTypes.h"
+#include "SkTemplates.h"
+
+// DATA_TYPE indicates that T has a trivial cons, destructor
+// and can be shallow-copied
+template <typename T, bool DATA_TYPE = false> class SkTArray {
+public:
+ /**
+ * Creates an empty array with no initial storage
+ */
+ SkTArray() {
+ fCount = 0;
+ fReserveCount = gMIN_ALLOC_COUNT;
+ fAllocCount = 0;
+ fMemArray = NULL;
+ fPreAllocMemArray = NULL;
+ }
+
+ /**
+ * Creates an empty array that will preallocate space for reserveCount
+ * elements.
+ */
+ explicit SkTArray(int reserveCount) {
+ SkASSERT(reserveCount >= 0);
+ fCount = 0;
+ fReserveCount = reserveCount > gMIN_ALLOC_COUNT ? reserveCount :
+ gMIN_ALLOC_COUNT;
+ fAllocCount = fReserveCount;
+ fMemArray = sk_malloc_throw(sizeof(T) * fReserveCount);
+ fPreAllocMemArray = NULL;
+ }
+
+ /**
+ * Creates an empty array that will use the passed storage block until it
+ * is insufficiently large to hold the entire array.
+ */
+ template <int N>
+ SkTArray(SkAlignedSTStorage<N,T>* storage) {
+ SkASSERT(N > 0);
+ fCount = 0;
+ fReserveCount = N;
+ fAllocCount = N;
+ fMemArray = storage->get();
+ fPreAllocMemArray = storage->get();
+ }
+
+ /**
+ * Creates an empty array that will use the passed memory block until the
+ * count exceeds preAllocCount. Be careful not to use this constructor
+ * when you really want the (T*, int) version.
+ */
+ SkTArray(void* preAllocStorage, int preAllocCount) {
+ SkASSERT(preAllocCount >= 0);
+ // we allow NULL,0 args and revert to the default cons. behavior
+ // this makes it possible for a owner-object to use same constructor
+ // to get either prealloc or nonprealloc behavior based using same line
+ SkASSERT((NULL == preAllocStorage) == !preAllocCount);
+
+ fCount = 0;
+ fReserveCount = preAllocCount > 0 ? preAllocCount :
+ gMIN_ALLOC_COUNT;
+ fAllocCount = preAllocCount;
+ fMemArray = preAllocStorage;
+ fPreAllocMemArray = preAllocStorage;
+ }
+
+ /**
+ * Copies one array to another. The new array will be heap allocated.
+ */
+ explicit SkTArray(const SkTArray& array) {
+ fCount = array.count();
+ fReserveCount = gMIN_ALLOC_COUNT;
+ fAllocCount = SkMax32(fReserveCount, fCount);
+ fMemArray = sk_malloc(sizeof(T) * fAllocCount);
+ fPreAllocMemArray = NULL;
+
+ if (DATA_TYPE) {
+ memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
+ } else {
+ for (int i = 0; i < fCount; ++i) {
+ new (fItemArray + i) T(array[i]);
+ }
+ }
+ }
+
+ /**
+ * Creates a SkTArray by copying contents of a standard C array. The new
+ * array will be heap allocated. Be careful not to use this constructor
+ * when you really want the (void*, int) version.
+ */
+ SkTArray(const T* array, int count) {
+ SkASSERT(count >= 0);
+ fCount = count;
+ fReserveCount = gMIN_ALLOC_COUNT;
+ fAllocCount = SkMax32(fReserveCount, fCount);
+ fMemArray = sk_malloc(sizeof(T) * fAllocCount);
+ fPreAllocMemArray = NULL;
+ if (DATA_TYPE) {
+ memcpy(fMemArray, array, sizeof(T) * fCount);
+ } else {
+ for (int i = 0; i < fCount; ++i) {
+ new (fItemArray + i) T(array[i]);
+ }
+ }
+ }
+
+ /**
+ * Copy another array, using preallocated storage if preAllocCount >=
+ * array.count(). Otherwise preAllocStorage is only used if the array
+ * shrinks to fit.
+ */
+ SkTArray(const SkTArray& array,
+ void* preAllocStorage, int preAllocCount) {
+
+ SkASSERT(preAllocCount >= 0);
+
+ // for same reason as non-copying cons we allow NULL, 0 for prealloc
+ SkASSERT((NULL == preAllocStorage) == !preAllocCount);
+
+ fCount = array.count();
+ fReserveCount = preAllocCount > 0 ? preAllocCount :
+ gMIN_ALLOC_COUNT;
+ fPreAllocMemArray = preAllocStorage;
+
+ if (fReserveCount >= fCount && preAllocCount) {
+ fAllocCount = fReserveCount;
+ fMemArray = preAllocStorage;
+ } else {
+ fAllocCount = SkMax32(fCount, fReserveCount);
+ fMemArray = sk_malloc_throw(fAllocCount * sizeof(T));
+ }
+
+ if (DATA_TYPE) {
+ memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
+ } else {
+ for (int i = 0; i < fCount; ++i) {
+ new (fItemArray + i) T(array[i]);
+ }
+ }
+ }
+
+ /**
+ * Copy C array to SkTArray, using preallocated storage if preAllocCount >=
+ * preAllocCount. Otherwise preAllocStorage is only used if the array
+ * shrinks to fit.
+ */
+ SkTArray(const T* array, int count,
+ void* preAllocStorage, int preAllocCount) {
+
+ SkASSERT(count >= 0);
+ SkASSERT(preAllocCount >= 0);
+
+ // for same reason as non-copying cons we allow NULL, 0 for prealloc
+ SkASSERT((NULL == preAllocStorage) == !preAllocCount);
+
+ fCount = count;
+ fReserveCount = (preAllocCount > 0) ? preAllocCount :
+ gMIN_ALLOC_COUNT;
+ fPreAllocMemArray = preAllocStorage;
+
+ if (fReserveCount >= fCount && preAllocCount) {
+ fAllocCount = fReserveCount;
+ fMemArray = preAllocStorage;
+ } else {
+ fAllocCount = SkMax32(fCount, fReserveCount);
+ fMemArray = sk_malloc_throw(fAllocCount * sizeof(T));
+ }
+
+ if (DATA_TYPE) {
+ memcpy(fMemArray, array, sizeof(T) * fCount);
+ } else {
+ for (int i = 0; i < fCount; ++i) {
+ new (fItemArray + i) T(array[i]);
+ }
+ }
+ }
+
+ /**
+ * assign copy of array to this
+ */
+ SkTArray& operator =(const SkTArray& array) {
+ for (int i = 0; i < fCount; ++i) {
+ fItemArray[i].~T();
+ }
+ fCount = 0;
+ checkRealloc((int)array.count());
+ fCount = array.count();
+ if (DATA_TYPE) {
+ memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
+ } else {
+ for (int i = 0; i < fCount; ++i) {
+ new (fItemArray + i) T(array[i]);
+ }
+ }
+ return *this;
+ }
+
+ ~SkTArray() {
+ for (int i = 0; i < fCount; ++i) {
+ fItemArray[i].~T();
+ }
+ if (fMemArray != fPreAllocMemArray) {
+ sk_free(fMemArray);
+ }
+ }
+
+ /**
+ * Resets to count() == 0
+ */
+ void reset() { this->pop_back_n(fCount); }
+
+ /**
+ * Number of elements in the array.
+ */
+ int count() const { return fCount; }
+
+ /**
+ * Is the array empty.
+ */
+ bool empty() const { return !fCount; }
+
+ /**
+ * Adds 1 new default-constructed T value and returns in by reference. Note
+ * the reference only remains valid until the next call that adds or removes
+ * elements.
+ */
+ T& push_back() {
+ checkRealloc(1);
+ new ((char*)fMemArray+sizeof(T)*fCount) T;
+ ++fCount;
+ return fItemArray[fCount-1];
+ }
+
+ /**
+ * Allocates n more default T values, and returns the address of the start
+ * of that new range. Note: this address is only valid until the next API
+ * call made on the array that might add or remove elements.
+ */
+ T* push_back_n(int n) {
+ SkASSERT(n >= 0);
+ checkRealloc(n);
+ for (int i = 0; i < n; ++i) {
+ new (fItemArray + fCount + i) T;
+ }
+ fCount += n;
+ return fItemArray + fCount - n;
+ }
+
+ /**
+ * Removes the last element. Not safe to call when count() == 0.
+ */
+ void pop_back() {
+ SkASSERT(fCount > 0);
+ --fCount;
+ fItemArray[fCount].~T();
+ checkRealloc(0);
+ }
+
+ /**
+ * Removes the last n elements. Not safe to call when count() < n.
+ */
+ void pop_back_n(int n) {
+ SkASSERT(n >= 0);
+ SkASSERT(fCount >= n);
+ fCount -= n;
+ for (int i = 0; i < n; ++i) {
+ fItemArray[i].~T();
+ }
+ checkRealloc(0);
+ }
+
+ /**
+ * Pushes or pops from the back to resize. Pushes will be default
+ * initialized.
+ */
+ void resize_back(int newCount) {
+ SkASSERT(newCount >= 0);
+
+ if (newCount > fCount) {
+ push_back_n(newCount - fCount);
+ } else if (newCount < fCount) {
+ pop_back_n(fCount - newCount);
+ }
+ }
+
+ /**
+ * Get the i^th element.
+ */
+ T& operator[] (int i) {
+ SkASSERT(i < fCount);
+ SkASSERT(i >= 0);
+ return fItemArray[i];
+ }
+
+ const T& operator[] (int i) const {
+ SkASSERT(i < fCount);
+ SkASSERT(i >= 0);
+ return fItemArray[i];
+ }
+
+ /**
+ * equivalent to operator[](0)
+ */
+ T& front() { SkASSERT(fCount > 0); return fItemArray[0];}
+
+ const T& front() const { SkASSERT(fCount > 0); return fItemArray[0];}
+
+ /**
+ * equivalent to operator[](count() - 1)
+ */
+ T& back() { SkASSERT(fCount); return fItemArray[fCount - 1];}
+
+ const T& back() const { SkASSERT(fCount > 0); return fItemArray[fCount - 1];}
+
+ /**
+ * equivalent to operator[](count()-1-i)
+ */
+ T& fromBack(int i) {
+ SkASSERT(i >= 0);
+ SkASSERT(i < fCount);
+ return fItemArray[fCount - i - 1];
+ }
+
+ const T& fromBack(int i) const {
+ SkASSERT(i >= 0);
+ SkASSERT(i < fCount);
+ return fItemArray[fCount - i - 1];
+ }
+
+private:
+
+ static const int gMIN_ALLOC_COUNT = 8;
+
+ inline void checkRealloc(int delta) {
+ SkASSERT(fCount >= 0);
+ SkASSERT(fAllocCount >= 0);
+
+ SkASSERT(-delta <= fCount);
+
+ int newCount = fCount + delta;
+ int fNewAllocCount = fAllocCount;
+
+ if (newCount > fAllocCount) {
+ fNewAllocCount = SkMax32(newCount + ((newCount + 1) >> 1),
+ fReserveCount);
+ } else if (newCount < fAllocCount / 3) {
+ fNewAllocCount = SkMax32(fAllocCount / 2, fReserveCount);
+ }
+
+ if (fNewAllocCount != fAllocCount) {
+
+ fAllocCount = fNewAllocCount;
+ char* fNewMemArray;
+
+ if (fAllocCount == fReserveCount && NULL != fPreAllocMemArray) {
+ fNewMemArray = (char*) fPreAllocMemArray;
+ } else {
+ fNewMemArray = (char*) sk_malloc_throw(fAllocCount*sizeof(T));
+ }
+
+ if (DATA_TYPE) {
+ memcpy(fNewMemArray, fMemArray, fCount * sizeof(T));
+ } else {
+ for (int i = 0; i < fCount; ++i) {
+ new (fNewMemArray + sizeof(T) * i) T(fItemArray[i]);
+ fItemArray[i].~T();
+ }
+ }
+
+ if (fMemArray != fPreAllocMemArray) {
+ sk_free(fMemArray);
+ }
+ fMemArray = fNewMemArray;
+ }
+ }
+
+ int fReserveCount;
+ int fCount;
+ int fAllocCount;
+ void* fPreAllocMemArray;
+ union {
+ T* fItemArray;
+ void* fMemArray;
+ };
+};
+
+#endif
+
diff --git a/include/core/SkTemplates.h b/include/core/SkTemplates.h
index 75a8b42..03f0892 100644
--- a/include/core/SkTemplates.h
+++ b/include/core/SkTemplates.h
@@ -262,5 +262,37 @@
};
};
+/**
+ * Reserves memory that is aligned on double and pointer boundaries.
+ * Hopefully this is sufficient for all practical purposes.
+ */
+template <size_t N> class SkAlignedSStorage : SkNoncopyable {
+public:
+ void* get() { return fData; }
+private:
+ union {
+ void* fPtr;
+ double fDouble;
+ char fData[N];
+ };
+};
+
+/**
+ * Reserves memory that is aligned on double and pointer boundaries.
+ * Hopefully this is sufficient for all practical purposes. Otherwise,
+ * we have to do some arcane trickery to determine alignment of non-POD
+ * types. Lifetime of the memory is the lifetime of the object.
+ */
+template <int N, typename T> class SkAlignedSTStorage : SkNoncopyable {
+public:
+ /**
+ * Returns void* because this object does not initialize the
+ * memory. Use placement new for types that require a cons.
+ */
+ void* get() { return fStorage.get(); }
+private:
+ SkAlignedSStorage<sizeof(T)*N> fStorage;
+};
+
#endif