зеркало из https://github.com/mozilla/gecko-dev.git
Add nsAutoTArray and nsAutoTPtrArray. b=356299 r/sr=darin
This commit is contained in:
Родитель
d29b5d7174
Коммит
480afae792
|
@ -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 }
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче