Add nsAutoTArray and nsAutoTPtrArray. b=356299 r/sr=darin

This commit is contained in:
cvshook%sicking.cc 2006-11-02 19:33:10 +00:00
Родитель d29b5d7174
Коммит 480afae792
5 изменённых файлов: 166 добавлений и 23 удалений

Просмотреть файл

@ -138,6 +138,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
#include "nsIDOMUserDataHandler.h"
#include "nsIFragmentContentSink.h"
#include "nsContentCreatorFunctions.h"
#include "nsTPtrArray.h"
#ifdef IBMBIDI
#include "nsIBidiKeyboard.h"
@ -1228,7 +1229,7 @@ nsContentUtils::GetCommonAncestor(nsINode* aNode1,
}
// Build the chain of parents
nsAutoVoidArray parents1, parents2;
nsAutoTPtrArray<nsINode, 30> parents1, parents2;
do {
parents1.AppendElement(aNode1);
aNode1 = aNode1->GetNodeParent();
@ -1239,13 +1240,13 @@ nsContentUtils::GetCommonAncestor(nsINode* aNode1,
} while (aNode2);
// Find where the parent chain differs
PRUint32 pos1 = parents1.Count();
PRUint32 pos2 = parents2.Count();
PRUint32 pos1 = parents1.Length();
PRUint32 pos2 = parents2.Length();
nsINode* parent = nsnull;
PRUint32 len;
for (len = PR_MIN(pos1, pos2); len > 0; --len) {
nsINode* child1 = NS_STATIC_CAST(nsINode*, parents1.FastElementAt(--pos1));
nsINode* child2 = NS_STATIC_CAST(nsINode*, parents2.FastElementAt(--pos2));
nsINode* child1 = parents1.ElementAt(--pos1);
nsINode* child2 = parents2.ElementAt(--pos2);
if (child1 != child2) {
break;
}
@ -1265,7 +1266,7 @@ nsContentUtils::ComparePosition(nsINode* aNode1,
return 0;
}
nsAutoVoidArray parents1, parents2;
nsAutoTPtrArray<nsINode, 30> parents1, parents2;
// Check if either node is an attribute
nsIAttribute* attr1 = nsnull;
@ -1276,7 +1277,7 @@ nsContentUtils::ComparePosition(nsINode* aNode1,
// to the chain and walk up to the element
if (elem) {
aNode1 = elem;
parents1.AppendElement(attr1);
parents1.AppendElement(NS_STATIC_CAST(nsINode*, attr1));
}
}
if (aNode2->IsNodeOfType(nsINode::eATTRIBUTE)) {
@ -1306,7 +1307,7 @@ nsContentUtils::ComparePosition(nsINode* aNode1,
if (elem) {
aNode2 = elem;
parents2.AppendElement(attr2);
parents2.AppendElement(NS_STATIC_CAST(nsINode*, attr2));
}
}
@ -1326,10 +1327,10 @@ nsContentUtils::ComparePosition(nsINode* aNode1,
} while (aNode2);
// Check if the nodes are disconnected.
PRUint32 pos1 = parents1.Count();
PRUint32 pos2 = parents2.Count();
nsINode* top1 = NS_STATIC_CAST(nsINode*, parents1.FastElementAt(--pos1));
nsINode* top2 = NS_STATIC_CAST(nsINode*, parents2.FastElementAt(--pos2));
PRUint32 pos1 = parents1.Length();
PRUint32 pos2 = parents2.Length();
nsINode* top1 = parents1.ElementAt(--pos1);
nsINode* top2 = parents2.ElementAt(--pos2);
if (top1 != top2) {
return top1 < top2 ?
(nsIDOM3Node::DOCUMENT_POSITION_PRECEDING |
@ -1344,8 +1345,8 @@ nsContentUtils::ComparePosition(nsINode* aNode1,
nsINode* parent = top1;
PRUint32 len;
for (len = PR_MIN(pos1, pos2); len > 0; --len) {
nsINode* child1 = NS_STATIC_CAST(nsINode*, parents1.FastElementAt(--pos1));
nsINode* child2 = NS_STATIC_CAST(nsINode*, parents2.FastElementAt(--pos2));
nsINode* child1 = parents1.ElementAt(--pos1);
nsINode* child2 = parents2.ElementAt(--pos2);
if (child1 != child2) {
// child1 or child2 can be an attribute here. This will work fine since
// IndexOf will return -1 for the attribute making the attribute be

Просмотреть файл

@ -46,7 +46,7 @@ nsTArray_base::Header nsTArray_base::sEmptyHdr = { 0, 0, 0 };
#ifdef NS_BUILD_REFCNT_LOGGING
nsTArray_base::nsTArray_base()
: mHdr(NS_CONST_CAST(Header *, &sEmptyHdr)) {
: mHdr(&sEmptyHdr) {
MOZ_COUNT_CTOR(nsTArray_base);
}

Просмотреть файл

@ -77,10 +77,16 @@ class NS_COM_GLUE nsTArray_base {
return mHdr->mCapacity;
}
#ifdef DEBUG
void* DebugGetHeader() {
return mHdr;
}
#endif
protected:
#ifndef NS_BUILD_REFCNT_LOGGING
nsTArray_base()
: mHdr(NS_CONST_CAST(Header *, &sEmptyHdr)) {
: mHdr(&sEmptyHdr) {
}
#else
nsTArray_base();
@ -108,8 +114,11 @@ class NS_COM_GLUE nsTArray_base {
size_type elementSize);
// This method increments the length member of the array's header.
// Note that mHdr may actually be sEmptyHdr in the case where a
// zero-length array is inserted into our array. But then n should
// always be 0.
void IncrementLength(PRUint32 n) {
NS_ASSERTION(mHdr != &sEmptyHdr, "bad data pointer");
NS_ASSERTION(mHdr != &sEmptyHdr || n == 0, "bad data pointer");
mHdr->mLength += n;
}
@ -123,14 +132,44 @@ class NS_COM_GLUE nsTArray_base {
protected:
// NOTE: This method isn't heavily optimized if either array is an
// nsAutoTArray.
PRBool SwapArrayElements(nsTArray_base& other, size_type elementSize);
// Helper function for SwapArrayElements. Ensures that if the array
// is an nsAutoTArray that it doesn't use the built-in buffer.
PRBool EnsureNotUsingAutoArrayBuffer(size_type elemSize);
// We prefix mData with a structure of this type. This is done to minimize
// the size of the nsTArray object when it is empty.
struct Header {
PRUint32 mLength;
PRUint32 mCapacity;
PRUint32 mCapacity : 31;
PRUint32 mIsAutoArray : 1;
};
static const Header sEmptyHdr;
// Returns true if this nsTArray is an nsAutoTArray with a built-in buffer.
PRBool IsAutoArray() {
return mHdr->mIsAutoArray;
}
// Returns a Header for the built-in buffer of this nsAutoTArray.
Header* GetAutoArrayBuffer() {
NS_ASSERTION(IsAutoArray(), "Should be an auto array to call this");
return NS_REINTERPRET_CAST(Header*, &mHdr + 1);
}
// Returns true if this is an nsAutoTArray and it currently uses the
// built-in buffer to store its elements.
PRBool UsesAutoArrayBuffer() {
return mHdr->mIsAutoArray && mHdr == GetAutoArrayBuffer();
}
// This is not const since we may actually write to it. However we will
// always write to it the same data that it already contains. See
// IncrementLength
static Header sEmptyHdr;
// The array's elements (prefixed with a Header). This pointer is never
// null. If the array is empty, then this will point to sEmptyHdr.
@ -533,10 +572,10 @@ class nsTArray : public nsTArray_base {
// This method causes the elements contained in this array and the given
// array to be swapped.
void SwapElements(self_type& other) {
Header *h = other.mHdr;
other.mHdr = mHdr;
mHdr = h;
// NOTE: This method isn't heavily optimized if either array is an
// nsAutoTArray.
PRBool SwapElements(self_type& other) {
return SwapArrayElements(other, sizeof(elem_type));
}
//
@ -661,4 +700,22 @@ class nsTArray : public nsTArray_base {
}
};
template<class E, PRUint32 N>
class nsAutoTArray : public nsTArray<E> {
public:
nsAutoTArray() {
mHdr = NS_REINTERPRET_CAST(Header*, &mAutoBuf);
mHdr->mLength = 0;
mHdr->mCapacity = N;
mHdr->mIsAutoArray = 1;
NS_ASSERTION(GetAutoArrayBuffer() ==
NS_REINTERPRET_CAST(Header*, &mAutoBuf),
"GetAutoArrayBuffer needs to be fixed");
}
protected:
char mAutoBuf[sizeof(Header) + N * sizeof(E)];
};
#endif // nsTArray_h__

Просмотреть файл

@ -94,4 +94,22 @@ class nsTPtrArray : public nsTArray<E*> {
}
};
template<class E, PRUint32 N>
class nsAutoTPtrArray : public nsTPtrArray<E> {
public:
nsAutoTPtrArray() {
mHdr = NS_REINTERPRET_CAST(Header*, &mAutoBuf);
mHdr->mLength = 0;
mHdr->mCapacity = N;
mHdr->mIsAutoArray = 1;
NS_ASSERTION(GetAutoArrayBuffer() ==
NS_REINTERPRET_CAST(Header*, &mAutoBuf),
"GetAutoArrayBuffer needs to be fixed");
}
protected:
char mAutoBuf[sizeof(Header) + N * sizeof(E*)];
};
#endif // nsTPtrArray_h__

Просмотреть файл

@ -410,6 +410,72 @@ static PRBool test_ptrarray() {
//----
static PRBool test_autoarray() {
PRUint32 data[] = {4,6,8,2,4,1,5,7,3};
nsAutoTArray<PRUint32, NS_ARRAY_LENGTH(data)> array;
void* hdr = array.DebugGetHeader();
if (hdr == (nsTArray<PRUint32>()).DebugGetHeader())
return PR_FALSE;
if (hdr == (nsAutoTArray<PRUint32, NS_ARRAY_LENGTH(data)>()).DebugGetHeader())
return PR_FALSE;
array.AppendElement(1);
if (hdr != array.DebugGetHeader())
return PR_FALSE;
array.RemoveElement(1);
array.AppendElements(data, NS_ARRAY_LENGTH(data));
if (hdr != array.DebugGetHeader())
return PR_FALSE;
array.AppendElement(2);
if (hdr == array.DebugGetHeader())
return PR_FALSE;
array.Clear();
array.Compact();
if (hdr != array.DebugGetHeader())
return PR_FALSE;
array.AppendElements(data, NS_ARRAY_LENGTH(data));
if (hdr != array.DebugGetHeader())
return PR_FALSE;
nsTArray<PRUint32> array2;
void* emptyHdr = array2.DebugGetHeader();
array.SwapElements(array2);
if (emptyHdr == array.DebugGetHeader())
return PR_FALSE;
if (hdr == array2.DebugGetHeader())
return PR_FALSE;
PRUint32 i;
for (i = 0; i < NS_ARRAY_LENGTH(data); ++i) {
if (array2[i] != data[i])
return PR_FALSE;
}
if (!array.IsEmpty())
return PR_FALSE;
array.Compact();
array.AppendElements(data, NS_ARRAY_LENGTH(data));
PRUint32 data3[] = {5, 7, 11};
nsAutoTArray<PRUint32, NS_ARRAY_LENGTH(data3)> array3;
array3.AppendElements(data3, NS_ARRAY_LENGTH(data3));
array.SwapElements(array3);
for (i = 0; i < NS_ARRAY_LENGTH(data); ++i) {
if (array3[i] != data[i])
return PR_FALSE;
}
for (i = 0; i < NS_ARRAY_LENGTH(data3); ++i) {
if (array[i] != data3[i])
return PR_FALSE;
}
return PR_TRUE;
}
//----
typedef PRBool (*TestFunc)();
#define DECL_TEST(name) { #name, name }
@ -426,6 +492,7 @@ static const struct Test {
DECL_TEST(test_comptr_array),
DECL_TEST(test_refptr_array),
DECL_TEST(test_ptrarray),
DECL_TEST(test_autoarray),
{ nsnull, nsnull }
};