Bug 90545. nsVoidArray and nsSupportsArray cleanup. Patch submitted by rjesup@wgate.com, r=jst, sr=waterson.

This commit is contained in:
waterson%netscape.com 2001-08-07 06:23:40 +00:00
parent a26a6ba8d2
commit ec45d8212e
5 changed files with 978 additions and 313 deletions

View File

@ -87,6 +87,18 @@ interface nsISupportsArray : nsICollection {
in voidPtr aData);
nsISupportsArray clone();
[notxpcom] boolean MoveElement(in long aFrom,
in long aTo);
[notxpcom] boolean InsertElementsAt(in nsISupportsArray aOther,
in unsigned long aIndex);
[notxpcom] boolean RemoveElementsAt(in unsigned long aIndex,
in unsigned long aCount);
[notxpcom] boolean SizeTo(in long aSize);
%{C++
private:
// NS_IMETHOD_(nsISupportsArray&) operator=(const nsISupportsArray& other) = 0;

View File

@ -27,6 +27,74 @@
#include "nsSupportsArrayEnumerator.h"
#include "nsIObjectInputStream.h"
#include "nsIObjectOutputStream.h"
#include <string.h>
#if DEBUG_SUPPORTSARRAY
#define MAXSUPPORTS 20
class SupportsStats {
public:
SupportsStats();
~SupportsStats();
};
static int sizesUsed; // number of the elements of the arrays used
static int sizesAlloced[MAXSUPPORTS]; // sizes of the allocations. sorted
static int NumberOfSize[MAXSUPPORTS]; // number of this allocation size (1 per array)
static int AllocedOfSize[MAXSUPPORTS]; // number of this allocation size (each size for array used)
static int GrowInPlace[MAXSUPPORTS];
// these are per-allocation
static int MaxElements[3000];
// very evil
#define ADD_TO_STATS(x,size) do {int i; for (i = 0; i < sizesUsed; i++) \
{ \
if (sizesAlloced[i] == (int)(size)) \
{ ((x)[i])++; break; } \
} \
if (i >= sizesUsed && sizesUsed < MAXSUPPORTS) \
{ sizesAlloced[sizesUsed] = (size); \
((x)[sizesUsed++])++; break; \
} \
} while (0);
#define SUB_FROM_STATS(x,size) do {int i; for (i = 0; i < sizesUsed; i++) \
{ \
if (sizesAlloced[i] == (int)(size)) \
{ ((x)[i])--; break; } \
} \
} while (0);
SupportsStats::SupportsStats()
{
sizesUsed = 1;
sizesAlloced[0] = 0;
}
SupportsStats::~SupportsStats()
{
int i;
for (i = 0; i < sizesUsed; i++)
{
printf("Size %d:\n",sizesAlloced[i]);
printf("\tNumber of SupportsArrays this size (max): %d\n",NumberOfSize[i]);
printf("\tNumber of allocations this size (total): %d\n",AllocedOfSize[i]);
printf("\tNumber of GrowsInPlace this size (total): %d\n",GrowInPlace[i]);
}
printf("Max Size of SupportsArray:\n");
for (i = 0; i < (int)(sizeof(MaxElements)/sizeof(MaxElements[0])); i++)
{
if (MaxElements[i])
printf("\t%d: %d\n",i,MaxElements[i]);
}
}
// Just so constructor/destructor get called
SupportsStats gSupportsStats;
#endif
nsresult
nsQueryElementAt::operator()( const nsIID& aIID, void** aResult ) const
@ -41,7 +109,8 @@ nsQueryElementAt::operator()( const nsIID& aIID, void** aResult ) const
return status;
}
static const PRUint32 kGrowArrayBy = 8;
static const PRInt32 kGrowArrayBy = 8;
static const PRInt32 kLinearThreshold = 16 * sizeof(nsISupports *);
nsSupportsArray::nsSupportsArray()
{
@ -49,6 +118,12 @@ nsSupportsArray::nsSupportsArray()
mArray = mAutoArray;
mArraySize = kAutoArraySize;
mCount = 0;
#if DEBUG_SUPPORTSARRAY
mMaxCount = 0;
mMaxSize = 0;
ADD_TO_STATS(NumberOfSize,kAutoArraySize*sizeof(mArray[0]));
MaxElements[0]++;
#endif
}
nsSupportsArray::~nsSupportsArray()
@ -56,6 +131,82 @@ nsSupportsArray::~nsSupportsArray()
DeleteArray();
}
PRBool nsSupportsArray::GrowArrayBy(PRInt32 aGrowBy)
{
// We have to grow the array. Grow by kGrowArrayBy slots if we're smaller
// than kLinearThreshold bytes, or a power of two if we're larger.
// This is much more efficient with most memory allocators, especially
// if it's very large, or of the allocator is binned.
if (aGrowBy < kGrowArrayBy)
aGrowBy = kGrowArrayBy;
PRUint32 newCount = mArraySize + aGrowBy; // Minimum increase
PRUint32 newSize = sizeof(mArray[0]) * newCount;
if (newSize >= (PRUint32) kLinearThreshold)
{
// newCount includes enough space for at least kGrowArrayBy new slots.
// Select the next power-of-two size in bytes above that.
// It's painful to find the biggest 1 bit. We check for a
// power-of-two here, and then double if it is one.
PRUint32 oldSize = sizeof(mArray[0]) * mArraySize;
if ((oldSize & (oldSize-1)) == 0) // oldSize = 2^n for some n
{
newSize = oldSize << 1; // easy 2^(n+1)
}
else // count bits and stuff.
{
PRUint32 bits = 0;
while (newSize >>= 1)
{
bits++;
}
bits++; // bump to the next power of two;
newSize = 1 << bits;
}
// Make sure we have enough space -- the array can grow by a lot
while (newSize/sizeof(mArray[0]) < newCount)
newSize <<= 1;
// inverse of equation above.
newCount = newSize/sizeof(mArray[0]);
}
// XXX This would be far more efficient in many allocators if we used
// XXX PR_Realloc(), etc
nsISupports** oldArray = mArray;
mArray = new nsISupports*[newCount];
if (!mArray) { // ran out of memory
mArray = oldArray;
return PR_FALSE;
}
mArraySize = newCount;
#if DEBUG_SUPPORTSARRAY
if (oldArray == mArray) // can't happen without use of realloc
ADD_TO_STATS(GrowInPlace,mCount);
ADD_TO_STATS(AllocedOfSize,mArraySize*sizeof(mArray[0]));
if (mArraySize > mMaxSize)
{
ADD_TO_STATS(NumberOfSize,mArraySize*sizeof(mArray[0]));
if (oldArray != &(mAutoArray[0]))
SUB_FROM_STATS(NumberOfSize,mCount*sizeof(mArray[0]));
mMaxSize = mArraySize;
}
#endif
if (oldArray) { // need to move old data
if (0 < mCount) {
::memcpy(mArray, oldArray, mCount * sizeof(nsISupports*));
}
if (oldArray != &(mAutoArray[0])) {
delete[] oldArray;
}
}
return PR_TRUE;
}
NS_METHOD
nsSupportsArray::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
{
@ -84,7 +235,7 @@ nsSupportsArray::Read(nsIObjectInputStream *aStream)
if (newArraySize <= kAutoArraySize) {
if (mArray != mAutoArray) {
delete mArray;
delete[] mArray;
mArray = mAutoArray;
newArraySize = kAutoArraySize;
}
@ -99,7 +250,7 @@ nsSupportsArray::Read(nsIObjectInputStream *aStream)
if (!array)
return NS_ERROR_OUT_OF_MEMORY;
if (mArray != mAutoArray)
delete mArray;
delete[] mArray;
mArray = array;
}
}
@ -164,15 +315,9 @@ nsSupportsArray::operator=(nsISupportsArray const& aOther)
if (otherCount > mArraySize) {
DeleteArray();
nsISupports** array = new nsISupports*[otherCount];
if (!array) {
// Can't grow mArray, can't return an error -- copy mCount elements.
otherCount = mCount;
}
else {
mArraySize = otherCount;
mArray = array;
}
if (!GrowArrayBy(otherCount - mArraySize))
// Can't grow mArray, can't return an error -- copy mArraySize elements.
otherCount = mArraySize;
}
else {
Clear();
@ -181,6 +326,15 @@ nsSupportsArray::operator=(nsISupportsArray const& aOther)
while (0 < otherCount--) {
mArray[otherCount] = ((nsISupportsArray&)aOther).ElementAt(otherCount);
}
#if DEBUG_SUPPORTSARRAY
if (mCount > mMaxCount &&
mCount < (PRInt32)(sizeof(MaxElements)/sizeof(MaxElements[0])))
{
MaxElements[mCount]++;
MaxElements[mMaxCount]--;
mMaxCount = mCount;
}
#endif
return *this;
}
@ -267,38 +421,77 @@ nsSupportsArray::InsertElementAt(nsISupports* aElement, PRUint32 aIndex)
return PR_FALSE;
}
if (aIndex <= mCount) {
if (mArraySize < (mCount + 1)) { // need to grow the array
mArraySize += kGrowArrayBy;
nsISupports** oldArray = mArray;
mArray = new nsISupports*[mArraySize];
if (!mArray) { // ran out of memory
mArray = oldArray;
mArraySize -= kGrowArrayBy;
if (mArraySize < (mCount + 1)) {
// need to grow the array
if (!GrowArrayBy(1))
return PR_FALSE;
}
if (oldArray) { // need to move old data
if (0 < aIndex) {
::memcpy(mArray, oldArray, aIndex * sizeof(nsISupports*));
}
PRUint32 slide = (mCount - aIndex);
if (0 < slide) {
::memcpy(mArray + aIndex + 1, oldArray + aIndex, slide * sizeof(nsISupports*));
}
if (oldArray != &(mAutoArray[0])) {
delete[] oldArray;
}
}
}
else {
PRUint32 slide = (mCount - aIndex);
if (0 < slide) {
::memmove(mArray + aIndex + 1, mArray + aIndex, slide * sizeof(nsISupports*));
}
// Could be slightly more efficient if GrowArrayBy knew about the
// split, but the difference is trivial.
PRUint32 slide = (mCount - aIndex);
if (0 < slide) {
::memmove(mArray + aIndex + 1, mArray + aIndex, slide * sizeof(nsISupports*));
}
mArray[aIndex] = aElement;
NS_ADDREF(aElement);
mCount++;
#if DEBUG_SUPPORTSARRAY
if (mCount > mMaxCount &&
mCount < (PRInt32)(sizeof(MaxElements)/sizeof(MaxElements[0])))
{
MaxElements[mCount]++;
MaxElements[mMaxCount]--;
mMaxCount = mCount;
}
#endif
return PR_TRUE;
}
return PR_FALSE;
}
NS_IMETHODIMP_(PRBool)
nsSupportsArray::InsertElementsAt(nsISupportsArray* aElements, PRUint32 aIndex)
{
if (!aElements) {
return PR_FALSE;
}
PRUint32 countElements;
if (NS_FAILED( aElements->Count( &countElements ) ))
return PR_FALSE;
if (aIndex <= mCount) {
if (mArraySize < (mCount + countElements)) {
// need to grow the array
if (!GrowArrayBy(countElements))
return PR_FALSE;
}
// Could be slightly more efficient if GrowArrayBy knew about the
// split, but the difference is trivial.
PRUint32 slide = (mCount - aIndex);
if (0 < slide) {
::memmove(mArray + aIndex + countElements, mArray + aIndex,
slide * sizeof(nsISupports*));
}
for (PRUint32 i = 0; i < countElements; ++i, ++mCount) {
// use GetElementAt to copy and do AddRef for us
if (NS_FAILED( aElements->GetElementAt( i, mArray + aIndex + i) ))
return PR_FALSE;
}
#if DEBUG_SUPPORTSARRAY
if (mCount > mMaxCount &&
mCount < (PRInt32)(sizeof(MaxElements)/sizeof(MaxElements[0])))
{
MaxElements[mCount]++;
MaxElements[mMaxCount]--;
mMaxCount = mCount;
}
#endif
return PR_TRUE;
}
return PR_FALSE;
@ -317,14 +510,17 @@ nsSupportsArray::ReplaceElementAt(nsISupports* aElement, PRUint32 aIndex)
}
NS_IMETHODIMP_(PRBool)
nsSupportsArray::RemoveElementAt(PRUint32 aIndex)
nsSupportsArray::RemoveElementsAt(PRUint32 aIndex, PRUint32 aCount)
{
if (aIndex < mCount) {
NS_RELEASE(mArray[aIndex]);
mCount--;
for (PRUint32 i = 0; i < aCount; i++)
{
NS_RELEASE(mArray[aIndex+i]);
}
mCount -= aCount;
PRInt32 slide = (mCount - aIndex);
if (0 < slide) {
::memmove(mArray + aIndex, mArray + aIndex + 1,
::memmove(mArray + aIndex, mArray + aIndex + aCount,
slide * sizeof(nsISupports*));
}
return PR_TRUE;
@ -335,76 +531,55 @@ nsSupportsArray::RemoveElementAt(PRUint32 aIndex)
NS_IMETHODIMP_(PRBool)
nsSupportsArray::RemoveElement(const nsISupports* aElement, PRUint32 aStartIndex)
{
if (aStartIndex < mCount) {
nsISupports** ep = mArray;
nsISupports** end = ep + mCount;
while (ep < end) {
if (*ep == aElement) {
return RemoveElementAt(PRUint32(ep - mArray));
}
ep++;
}
}
PRInt32 theIndex = IndexOfStartingAt(aElement,aStartIndex);
if (theIndex >= 0)
return RemoveElementAt(theIndex);
return PR_FALSE;
}
NS_IMETHODIMP_(PRBool)
nsSupportsArray::RemoveLastElement(const nsISupports* aElement)
{
if (0 < mCount) {
nsISupports** ep = (mArray + mCount);
while (mArray <= --ep) {
if (*ep == aElement) {
return RemoveElementAt(PRUint32(ep - mArray));
}
}
}
PRInt32 theIndex = LastIndexOf(aElement);
if (theIndex >= 0)
return RemoveElementAt(theIndex);
return PR_FALSE;
}
NS_IMETHODIMP_(PRBool)
nsSupportsArray::AppendElements(nsISupportsArray* aElements)
nsSupportsArray::MoveElement(PRInt32 aFrom, PRInt32 aTo)
{
if (!aElements)
return PR_FALSE;
nsISupports *tempElement;
PRUint32 countElements;
if (NS_FAILED( aElements->Count( &countElements ) ))
return PR_FALSE;
if (0 < countElements) {
if (mArraySize < (mCount + countElements)) { // need to grow the array
PRUint32 count = mCount + countElements;
PRUint32 oldSize = mArraySize;
// growth is linear; consider geometric (e.g., doubling) to avoid the n^2
// (amortized) cost we are paying to copy elements now
mArraySize += ((count - mArraySize + kGrowArrayBy - 1) / kGrowArrayBy) * kGrowArrayBy;
nsISupports** oldArray = mArray;
mArray = new nsISupports*[mArraySize];
if (!mArray) { // ran out of memory
mArray = oldArray;
mArraySize = oldSize;
return PR_FALSE;
}
if (oldArray) { // need to move old data
if (0 < mCount) {
::memcpy(mArray, oldArray, mCount * sizeof(nsISupports*));
}
if (oldArray != &(mAutoArray[0])) {
delete[] oldArray;
}
}
}
PRUint32 i = 0;
for (i = 0; i < countElements; ++i, ++mCount) {
// use GetElementAt to copy and do AddRef for us
if (NS_FAILED( aElements->GetElementAt( i, mArray + mCount) ))
return PR_FALSE;
}
if (aTo == aFrom)
return PR_TRUE;
if (aTo < 0 || aFrom < 0 ||
(PRUint32) aTo >= mCount || (PRUint32) aFrom >= mCount)
{
// can't extend the array when moving an element. Also catches mImpl = null
return PR_FALSE;
}
return PR_FALSE;
tempElement = mArray[aFrom];
if (aTo < aFrom)
{
// Moving one element closer to the head; the elements inbetween move down
::memmove(mArray + aTo + 1, mArray + aTo,
(aFrom-aTo) * sizeof(mArray[0]));
mArray[aTo] = tempElement;
}
else // already handled aFrom == aTo
{
// Moving one element closer to the tail; the elements inbetween move up
::memmove(mArray + aFrom, mArray + aFrom + 1,
(aTo-aFrom) * sizeof(mArray[0]));
mArray[aTo] = tempElement;
}
return PR_TRUE;
}
NS_IMETHODIMP
@ -422,6 +597,9 @@ nsSupportsArray::Clear(void)
NS_IMETHODIMP
nsSupportsArray::Compact(void)
{
#if DEBUG_SUPPORTSARRAY
PRUint32 oldArraySize = mArraySize;
#endif
if ((mArraySize != mCount) && (kAutoArraySize < mArraySize)) {
nsISupports** oldArray = mArray;
if (mCount <= kAutoArraySize) {
@ -436,12 +614,57 @@ nsSupportsArray::Compact(void)
}
mArraySize = mCount;
}
#if DEBUG_SUPPORTSARRAY
if (oldArray == mArray &&
oldArray != &(mAutoArray[0])) // can't happen without use of realloc
ADD_TO_STATS(GrowInPlace,oldArraySize);
if (oldArray != &(mAutoArray[0]))
ADD_TO_STATS(AllocedOfSize,mArraySize*sizeof(mArray[0]));
#endif
::memcpy(mArray, oldArray, mCount * sizeof(nsISupports*));
delete[] oldArray;
}
return NS_OK;
}
NS_IMETHODIMP_(PRBool)
nsSupportsArray::SizeTo(PRInt32 aSize)
{
#if DEBUG_SUPPORTSARRAY
PRUint32 oldArraySize = mArraySize;
#endif
// XXX for aSize < mCount we could resize to mCount
if (mArraySize == aSize || aSize < mCount) // nothing to do
return PR_TRUE;
// switch back to autoarray if possible
nsISupports** oldArray = mArray;
if (kAutoArraySize <= aSize) {
mArray = mAutoArray;
mArraySize = kAutoArraySize;
}
else {
mArray = new nsISupports*[aSize];
if (!mArray) {
mArray = oldArray;
return PR_FALSE;
}
mArraySize = aSize;
}
#if DEBUG_SUPPORTSARRAY
if (oldArray == mArray &&
oldArray != &(mAutoArray[0])) // can't happen without use of realloc
ADD_TO_STATS(GrowInPlace,oldArraySize);
if (oldArray != &(mAutoArray[0]))
ADD_TO_STATS(AllocedOfSize,mArraySize*sizeof(mArray[0]));
#endif
::memcpy(mArray, oldArray, mCount * sizeof(nsISupports*));
if (oldArray != mAutoArray)
delete[] oldArray;
return PR_TRUE;
}
NS_IMETHODIMP_(PRBool)
nsSupportsArray::EnumerateForwards(nsISupportsArrayEnumFunc aFunc, void* aData)
{

View File

@ -23,9 +23,11 @@
#ifndef nsSupportsArray_h__
#define nsSupportsArray_h__
//#define DEBUG_SUPPORTSARRAY 1
#include "nsISupportsArray.h"
static const PRUint32 kAutoArraySize = 4;
static const PRUint32 kAutoArraySize = 8;
class NS_COM nsSupportsArray : public nsISupportsArray {
public:
@ -65,6 +67,7 @@ public:
// XXX This incorrectly returns a PRBool instead of an nsresult.
return RemoveElement(aElement, 0);
}
NS_IMETHOD_(PRBool) MoveElement(PRInt32 aFrom, PRInt32 aTo);
NS_IMETHOD Enumerate(nsIEnumerator* *result);
NS_IMETHOD Clear(void);
@ -98,7 +101,9 @@ public:
NS_IMETHOD_(PRBool) ReplaceElementAt(nsISupports* aElement, PRUint32 aIndex);
NS_IMETHOD_(PRBool) RemoveElementAt(PRUint32 aIndex);
NS_IMETHOD_(PRBool) RemoveElementAt(PRUint32 aIndex) {
return RemoveElementsAt(aIndex,1);
}
NS_IMETHOD_(PRBool) RemoveElement(const nsISupports* aElement, PRUint32 aStartIndex = 0);
NS_IMETHOD_(PRBool) RemoveLastElement(const nsISupports* aElement);
@ -110,7 +115,9 @@ public:
return (RemoveElementAt(aIndex) ? NS_OK : NS_ERROR_FAILURE);
}
NS_IMETHOD_(PRBool) AppendElements(nsISupportsArray* aElements);
NS_IMETHOD_(PRBool) AppendElements(nsISupportsArray* aElements) {
return InsertElementsAt(aElements,mCount);
}
NS_IMETHOD Compact(void);
@ -119,6 +126,11 @@ public:
NS_IMETHOD Clone(nsISupportsArray **_retval);
NS_IMETHOD_(PRBool) InsertElementsAt(nsISupportsArray *aOther, PRUint32 aIndex);
NS_IMETHOD_(PRBool) RemoveElementsAt(PRUint32 aIndex, PRUint32 aCount);
NS_IMETHOD_(PRBool) SizeTo(PRInt32 aSize);
protected:
NS_IMETHOD_(nsISupportsArray&) operator=(const nsISupportsArray& aOther);
NS_IMETHOD_(PRBool) operator==(const nsISupportsArray& aOther) { return Equals(&aOther); }
@ -126,10 +138,16 @@ protected:
void DeleteArray(void);
NS_IMETHOD_(PRBool) GrowArrayBy(PRInt32 aGrowBy);
nsISupports** mArray;
PRUint32 mArraySize;
PRUint32 mCount;
nsISupports* mAutoArray[kAutoArraySize];
#if DEBUG_SUPPORTSARRAY
PRUint32 mMaxCount;
PRUint32 mMaxSize;
#endif
private:
// Copy constructors are not allowed

File diff suppressed because it is too large Load Diff

View File

@ -23,6 +23,8 @@
#ifndef nsVoidArray_h___
#define nsVoidArray_h___
//#define DEBUG_VOIDARRAY 1
#include "nscore.h"
#include "nsAWritableString.h"
#include "nsQuickSort.h"
@ -45,11 +47,15 @@ public:
nsVoidArray& operator=(const nsVoidArray& other);
void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
virtual void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
PRInt32 Count() const {
inline PRInt32 Count() const {
return mImpl ? mImpl->mCount : 0;
}
// returns the max number that can be held without allocating
inline PRInt32 GetArraySize() const {
return mImpl ? PRInt32(mImpl->mBits & kArraySizeMask) : 0;
}
void* ElementAt(PRInt32 aIndex) const;
void* operator[](PRInt32 aIndex) const { return ElementAt(aIndex); }
@ -57,18 +63,27 @@ public:
PRInt32 IndexOf(void* aPossibleElement) const;
PRBool InsertElementAt(void* aElement, PRInt32 aIndex);
PRBool InsertElementsAt(const nsVoidArray &other, PRInt32 aIndex);
PRBool ReplaceElementAt(void* aElement, PRInt32 aIndex);
// useful for doing LRU arrays, sorting, etc
PRBool MoveElement(PRInt32 aFrom, PRInt32 aTo);
PRBool AppendElement(void* aElement) {
return InsertElementAt(aElement, Count());
}
PRBool RemoveElement(void* aElement);
PRBool RemoveElementAt(PRInt32 aIndex);
void Clear();
PRBool RemoveElementsAt(PRInt32 aIndex, PRInt32 aCount);
PRBool RemoveElementAt(PRInt32 aIndex) { return RemoveElementsAt(aIndex,1); }
void Compact();
virtual void Clear();
virtual PRBool SizeTo(PRInt32 aMin);
// Subtly different - Compact() tries to be smart about whether we
// should reallocate the array; SizeTo() just does it.
virtual void Compact();
void Sort(nsVoidArrayComparatorFunc aFunc, void* aData);
@ -76,10 +91,12 @@ public:
PRBool EnumerateBackwards(nsVoidArrayEnumFunc aFunc, void* aData);
protected:
virtual PRBool GrowArrayBy(PRInt32 aGrowBy);
struct Impl {
/**
* Packed bits. The highest 31 bits are the array's size, which must
* always be 0 mod 2. The lowest bit is a flag that indicates
* Packed bits. The low 31 bits are the array's size.
* The highest bit is a flag that indicates
* whether or not we "own" mArray, and must free() it when
* destroyed.
*/
@ -97,6 +114,11 @@ protected:
};
Impl* mImpl;
#if DEBUG_VOIDARRAY
PRInt32 mMaxCount;
PRInt32 mMaxSize;
PRBool mIsAuto;
#endif
enum {
kArrayOwnerMask = 1 << 31,
@ -105,10 +127,10 @@ protected:
// bit twiddlers
PRInt32 GetArraySize() const;
void SetArraySize(PRInt32 aSize);
PRBool IsArrayOwner() const;
void SetArrayOwner(PRBool aOwner);
void SetArray(Impl *newImpl, PRInt32 aSize, PRInt32 aCount, PRBool owner);
inline PRBool IsArrayOwner() const {
return mImpl ? PRBool(mImpl->mBits & kArrayOwnerMask) : PR_FALSE;
}
private:
/// Copy constructors are not allowed
@ -120,10 +142,13 @@ private:
class NS_COM nsAutoVoidArray : public nsVoidArray {
public:
nsAutoVoidArray();
void Clear();
virtual PRBool SizeTo(PRInt32 aMin);
virtual void Compact();
protected:
// The internal storage. Note that this value must be divisible by
// two because we use the LSB of mInfo to indicate array ownership.
// The internal storage
enum { kAutoBufSize = 8 };
char mAutoBuf[sizeof(Impl) + (kAutoBufSize - 1) * sizeof(void*)];
};
@ -140,6 +165,7 @@ class NS_COM nsStringArray: protected nsVoidArray
{
public:
nsStringArray(void);
nsStringArray(PRInt32 aCount); // Storage for aCount elements will be pre-allocated
virtual ~nsStringArray(void);
nsStringArray& operator=(const nsStringArray& other);
@ -198,6 +224,7 @@ class NS_COM nsCStringArray: protected nsVoidArray
{
public:
nsCStringArray(void);
nsCStringArray(PRInt32 aCount); // Storage for aCount elements will be pre-allocated
virtual ~nsCStringArray(void);
nsCStringArray& operator=(const nsCStringArray& other);