Do iterative cloning and destruction of linked list selector data structures. b=333634 r+sr=bzbarsky

This commit is contained in:
dbaron%dbaron.org 2006-04-25 21:48:11 +00:00
parent 6ce70b5a6f
commit a83d924850
2 changed files with 170 additions and 225 deletions

View File

@ -77,16 +77,53 @@
#include "nsContentUtils.h"
#include "nsContentErrors.h"
#define NS_IF_CLONE(member_) \
PR_BEGIN_MACRO \
if (member_) { \
result->member_ = member_->Clone(); \
if (!result->member_) { \
delete result; \
return nsnull; \
} \
} \
PR_END_MACRO
#define NS_IF_DEEP_CLONE(type_, member_) \
PR_BEGIN_MACRO \
type_ *dest = result; \
for (type_ *src = member_; src; src = src->member_) { \
type_ *clone = src->Clone(PR_FALSE); \
if (!clone) { \
delete result; \
return nsnull; \
} \
dest->member_ = clone; \
dest = clone; \
} \
PR_END_MACRO
#define NS_IF_DELETE(ptr) \
PR_BEGIN_MACRO \
if (ptr) { \
delete ptr; \
ptr = nsnull; \
} \
PR_END_MACRO
#define NS_IF_DEEP_DELETE(type_, member_) \
PR_BEGIN_MACRO \
type_ *cur = member_; \
member_ = nsnull; \
while (cur) { \
type_ *next = cur->member_; \
cur->member_ = nsnull; \
delete cur; \
cur = next; \
} \
PR_END_MACRO
/* ************************************************************************** */
// -- nsCSSSelector -------------------------------
#define NS_IF_COPY(dest,source,type) \
if (source) dest = new type(*(source))
#define NS_IF_DELETE(ptr) \
if (ptr) { delete ptr; ptr = nsnull; }
nsAtomList::nsAtomList(nsIAtom* aAtom)
: mAtom(aAtom),
mNext(nsnull)
@ -102,34 +139,22 @@ nsAtomList::nsAtomList(const nsString& aAtomValue)
mAtom = do_GetAtom(aAtomValue);
}
nsAtomList::nsAtomList(const nsAtomList& aCopy)
: mAtom(aCopy.mAtom),
mNext(nsnull)
nsAtomList*
nsAtomList::Clone(PRBool aDeep) const
{
MOZ_COUNT_CTOR(nsAtomList);
NS_IF_COPY(mNext, aCopy.mNext, nsAtomList);
nsAtomList *result = new nsAtomList(mAtom);
if (!result)
return nsnull;
if (aDeep)
NS_IF_DEEP_CLONE(nsAtomList, mNext);
return result;
}
nsAtomList::~nsAtomList(void)
{
MOZ_COUNT_DTOR(nsAtomList);
NS_IF_DELETE(mNext);
}
PRBool nsAtomList::Equals(const nsAtomList* aOther) const
{
if (this == aOther) {
return PR_TRUE;
}
if (nsnull != aOther) {
if (mAtom == aOther->mAtom) {
if (nsnull != mNext) {
return mNext->Equals(aOther->mNext);
}
return PRBool(nsnull == aOther->mNext);
}
}
return PR_FALSE;
NS_IF_DEEP_DELETE(nsAtomList, mNext);
}
nsAtomStringList::nsAtomStringList(nsIAtom* aAtom, const PRUnichar* aString)
@ -154,15 +179,15 @@ nsAtomStringList::nsAtomStringList(const nsString& aAtomValue,
mString = nsCRT::strdup(aString);
}
nsAtomStringList::nsAtomStringList(const nsAtomStringList& aCopy)
: mAtom(aCopy.mAtom),
mString(nsnull),
mNext(nsnull)
nsAtomStringList*
nsAtomStringList::Clone(PRBool aDeep) const
{
MOZ_COUNT_CTOR(nsAtomStringList);
if (aCopy.mString)
mString = nsCRT::strdup(aCopy.mString);
NS_IF_COPY(mNext, aCopy.mNext, nsAtomStringList);
nsAtomStringList *result = new nsAtomStringList(mAtom, mString);
if (aDeep)
NS_IF_DEEP_CLONE(nsAtomStringList, mNext);
return result;
}
nsAtomStringList::~nsAtomStringList(void)
@ -170,21 +195,7 @@ nsAtomStringList::~nsAtomStringList(void)
MOZ_COUNT_DTOR(nsAtomStringList);
if (mString)
nsCRT::free(mString);
NS_IF_DELETE(mNext);
}
PRBool nsAtomStringList::Equals(const nsAtomStringList* aOther) const
{
return (this == aOther) ||
(aOther &&
mAtom == aOther->mAtom &&
!mString == !aOther->mString &&
!mNext == !aOther->mNext &&
(!mNext || mNext->Equals(aOther->mNext)) &&
// Check strings last, since it's the slowest check.
(!mString || nsDependentString(mString).Equals(
nsDependentString(aOther->mString),
nsCaseInsensitiveStringComparator())));
NS_IF_DEEP_DELETE(nsAtomStringList, mNext);
}
nsAttrSelector::nsAttrSelector(PRInt32 aNameSpace, const nsString& aAttr)
@ -197,7 +208,7 @@ nsAttrSelector::nsAttrSelector(PRInt32 aNameSpace, const nsString& aAttr)
{
MOZ_COUNT_CTOR(nsAttrSelector);
mAttr = NS_NewAtom(aAttr);
mAttr = do_GetAtom(aAttr);
}
nsAttrSelector::nsAttrSelector(PRInt32 aNameSpace, const nsString& aAttr, PRUint8 aFunction,
@ -211,50 +222,42 @@ nsAttrSelector::nsAttrSelector(PRInt32 aNameSpace, const nsString& aAttr, PRUint
{
MOZ_COUNT_CTOR(nsAttrSelector);
mAttr = NS_NewAtom(aAttr);
mAttr = do_GetAtom(aAttr);
}
nsAttrSelector::nsAttrSelector(const nsAttrSelector& aCopy)
: mNameSpace(aCopy.mNameSpace),
mAttr(aCopy.mAttr),
mFunction(aCopy.mFunction),
mCaseSensitive(aCopy.mCaseSensitive),
mValue(aCopy.mValue),
nsAttrSelector::nsAttrSelector(PRInt32 aNameSpace, nsIAtom* aAttr,
PRUint8 aFunction, const nsString& aValue,
PRBool aCaseSensitive)
: mNameSpace(aNameSpace),
mAttr(aAttr),
mFunction(aFunction),
mCaseSensitive(aCaseSensitive),
mValue(aValue),
mNext(nsnull)
{
MOZ_COUNT_CTOR(nsAttrSelector);
}
NS_IF_ADDREF(mAttr);
NS_IF_COPY(mNext, aCopy.mNext, nsAttrSelector);
nsAttrSelector*
nsAttrSelector::Clone(PRBool aDeep) const
{
nsAttrSelector *result =
new nsAttrSelector(mNameSpace, mAttr, mFunction, mValue, mCaseSensitive);
if (aDeep)
NS_IF_DEEP_CLONE(nsAttrSelector, mNext);
return result;
}
nsAttrSelector::~nsAttrSelector(void)
{
MOZ_COUNT_DTOR(nsAttrSelector);
NS_IF_RELEASE(mAttr);
NS_IF_DELETE(mNext);
NS_IF_DEEP_DELETE(nsAttrSelector, mNext);
}
PRBool nsAttrSelector::Equals(const nsAttrSelector* aOther) const
{
if (this == aOther) {
return PR_TRUE;
}
if (nsnull != aOther) {
if ((mNameSpace == aOther->mNameSpace) &&
(mAttr == aOther->mAttr) &&
(mFunction == aOther->mFunction) &&
(mCaseSensitive == aOther->mCaseSensitive) &&
mValue.Equals(aOther->mValue)) {
if (nsnull != mNext) {
return mNext->Equals(aOther->mNext);
}
return PRBool(nsnull == aOther->mNext);
}
}
return PR_FALSE;
}
// -- nsCSSSelector -------------------------------
nsCSSSelector::nsCSSSelector(void)
: mNameSpace(kNameSpaceID_Unknown), mTag(nsnull),
@ -269,111 +272,41 @@ nsCSSSelector::nsCSSSelector(void)
MOZ_COUNT_CTOR(nsCSSSelector);
}
nsCSSSelector::nsCSSSelector(const nsCSSSelector& aCopy)
: mNameSpace(aCopy.mNameSpace), mTag(aCopy.mTag),
mIDList(nsnull),
mClassList(nsnull),
mPseudoClassList(nsnull),
mAttrList(nsnull),
mOperator(aCopy.mOperator),
mNegations(nsnull),
mNext(nsnull)
nsCSSSelector*
nsCSSSelector::Clone(PRBool aDeep) const
{
MOZ_COUNT_CTOR(nsCSSSelector);
NS_IF_COPY(mIDList, aCopy.mIDList, nsAtomList);
NS_IF_COPY(mClassList, aCopy.mClassList, nsAtomList);
NS_IF_COPY(mPseudoClassList, aCopy.mPseudoClassList, nsAtomStringList);
NS_IF_COPY(mAttrList, aCopy.mAttrList, nsAttrSelector);
NS_IF_COPY(mNegations, aCopy.mNegations, nsCSSSelector);
nsCSSSelector *result = new nsCSSSelector();
if (!result)
return nsnull;
result->mNameSpace = mNameSpace;
result->mTag = mTag;
NS_IF_CLONE(mIDList);
NS_IF_CLONE(mClassList);
NS_IF_CLONE(mPseudoClassList);
NS_IF_CLONE(mAttrList);
// No need to worry about multiple levels of recursion (or about copying
// mNegations->mNext) since an mNegations can't have an mNext.
NS_IF_DEEP_CLONE(nsCSSSelector, mNegations);
if (aDeep) {
NS_IF_DEEP_CLONE(nsCSSSelector, mNext);
}
return result;
}
nsCSSSelector::~nsCSSSelector(void)
{
MOZ_COUNT_DTOR(nsCSSSelector);
Reset();
// No need to worry about multiple levels of recursion since an
// mNegations can't have an mNext.
NS_IF_DEEP_DELETE(nsCSSSelector, mNext);
}
nsCSSSelector& nsCSSSelector::operator=(const nsCSSSelector& aCopy)
{
NS_IF_DELETE(mIDList);
NS_IF_DELETE(mClassList);
NS_IF_DELETE(mPseudoClassList);
NS_IF_DELETE(mAttrList);
NS_IF_DELETE(mNegations);
mNameSpace = aCopy.mNameSpace;
mTag = aCopy.mTag;
NS_IF_COPY(mIDList, aCopy.mIDList, nsAtomList);
NS_IF_COPY(mClassList, aCopy.mClassList, nsAtomList);
NS_IF_COPY(mPseudoClassList, aCopy.mPseudoClassList, nsAtomStringList);
NS_IF_COPY(mAttrList, aCopy.mAttrList, nsAttrSelector);
mOperator = aCopy.mOperator;
NS_IF_COPY(mNegations, aCopy.mNegations, nsCSSSelector);
return *this;
}
PRBool nsCSSSelector::Equals(const nsCSSSelector* aOther) const
{
if (this == aOther) {
return PR_TRUE;
}
if (nsnull != aOther) {
if ((aOther->mNameSpace == mNameSpace) &&
(aOther->mTag == mTag) &&
(aOther->mOperator == mOperator)) {
if (nsnull != mIDList) {
if (PR_FALSE == mIDList->Equals(aOther->mIDList)) {
return PR_FALSE;
}
}
else {
if (nsnull != aOther->mIDList) {
return PR_FALSE;
}
}
if (nsnull != mClassList) {
if (PR_FALSE == mClassList->Equals(aOther->mClassList)) {
return PR_FALSE;
}
}
else {
if (nsnull != aOther->mClassList) {
return PR_FALSE;
}
}
if (nsnull != mPseudoClassList) {
if (PR_FALSE == mPseudoClassList->Equals(aOther->mPseudoClassList)) {
return PR_FALSE;
}
}
else {
if (nsnull != aOther->mPseudoClassList) {
return PR_FALSE;
}
}
if (nsnull != mAttrList) {
if (PR_FALSE == mAttrList->Equals(aOther->mAttrList)) {
return PR_FALSE;
}
}
else {
if (nsnull != aOther->mAttrList) {
return PR_FALSE;
}
}
if (nsnull != mNegations) {
if (PR_FALSE == mNegations->Equals(aOther->mNegations)) {
return PR_FALSE;
}
}
return PR_TRUE;
}
}
return PR_FALSE;
}
void nsCSSSelector::Reset(void)
{
mNameSpace = kNameSpaceID_Unknown;
@ -382,7 +315,9 @@ void nsCSSSelector::Reset(void)
NS_IF_DELETE(mClassList);
NS_IF_DELETE(mPseudoClassList);
NS_IF_DELETE(mAttrList);
NS_IF_DELETE(mNegations);
// No need to worry about multiple levels of recursion since an
// mNegations can't have an mNext.
NS_IF_DEEP_DELETE(nsCSSSelector, mNegations);
mOperator = PRUnichar(0);
}
@ -749,20 +684,13 @@ nsCSSSelectorList::nsCSSSelectorList(void)
nsCSSSelectorList::~nsCSSSelectorList()
{
MOZ_COUNT_DTOR(nsCSSSelectorList);
nsCSSSelector* sel = mSelectors;
while (sel) {
nsCSSSelector* dead = sel;
sel = sel->mNext;
delete dead;
}
if (mNext) {
delete mNext;
}
NS_IF_DELETE(mSelectors);
NS_IF_DEEP_DELETE(nsCSSSelectorList, mNext);
}
void nsCSSSelectorList::AddSelector(const nsCSSSelector& aSelector)
{ // prepend to list
nsCSSSelector* newSel = new nsCSSSelector(aSelector);
nsCSSSelector* newSel = aSelector.Clone();
if (newSel) {
newSel->mNext = mSelectors;
mSelectors = newSel;
@ -784,32 +712,16 @@ nsCSSSelectorList::ToString(nsAString& aResult, nsICSSStyleSheet* aSheet)
}
nsCSSSelectorList*
nsCSSSelectorList::Clone()
nsCSSSelectorList::Clone(PRBool aDeep) const
{
nsCSSSelectorList *list = nsnull;
nsCSSSelectorList **list_cur = &list;
for (nsCSSSelectorList *l = this; l; l = l->mNext) {
nsCSSSelectorList *lcopy = new nsCSSSelectorList();
if (!lcopy) {
delete list;
return nsnull;
}
lcopy->mWeight = l->mWeight;
*list_cur = lcopy;
list_cur = &lcopy->mNext;
nsCSSSelectorList *result = new nsCSSSelectorList();
result->mWeight = mWeight;
NS_IF_CLONE(mSelectors);
nsCSSSelector **sel_cur = &lcopy->mSelectors;
for (nsCSSSelector *s = l->mSelectors; s; s = s->mNext) {
nsCSSSelector *scopy = new nsCSSSelector(*s);
if (!scopy) {
delete list;
return nsnull;
}
*sel_cur = scopy;
sel_cur = &scopy->mNext;
}
if (aDeep) {
NS_IF_DEEP_CLONE(nsCSSSelectorList, mNext);
}
return list;
return result;
}
// -- CSSImportantRule -------------------------------

View File

@ -60,25 +60,39 @@ struct nsAtomList {
public:
nsAtomList(nsIAtom* aAtom);
nsAtomList(const nsString& aAtomValue);
nsAtomList(const nsAtomList& aCopy);
~nsAtomList(void);
PRBool Equals(const nsAtomList* aOther) const;
/** Do a deep clone. Should be used only on the first in the linked list. */
nsAtomList* Clone() const { return Clone(PR_TRUE); }
nsCOMPtr<nsIAtom> mAtom;
nsAtomList* mNext;
private:
nsAtomList* Clone(PRBool aDeep) const;
// These are not supported and are not implemented!
nsAtomList(const nsAtomList& aCopy);
nsAtomList& operator=(const nsAtomList& aCopy);
};
struct nsAtomStringList {
public:
nsAtomStringList(nsIAtom* aAtom, const PRUnichar *aString = nsnull);
nsAtomStringList(const nsString& aAtomValue, const PRUnichar *aString = nsnull);
nsAtomStringList(const nsAtomStringList& aCopy);
~nsAtomStringList(void);
PRBool Equals(const nsAtomStringList* aOther) const;
/** Do a deep clone. Should be used only on the first in the linked list. */
nsAtomStringList* Clone() const { return Clone(PR_TRUE); }
nsCOMPtr<nsIAtom> mAtom;
PRUnichar* mString;
nsAtomStringList* mNext;
private:
nsAtomStringList* Clone(PRBool aDeep) const;
// These are not supported and are not implemented!
nsAtomStringList(const nsAtomStringList& aCopy);
nsAtomStringList& operator=(const nsAtomStringList& aCopy);
};
#define NS_ATTR_FUNC_SET 0 // [attr]
@ -94,26 +108,34 @@ public:
nsAttrSelector(PRInt32 aNameSpace, const nsString& aAttr);
nsAttrSelector(PRInt32 aNameSpace, const nsString& aAttr, PRUint8 aFunction,
const nsString& aValue, PRBool aCaseSensitive);
nsAttrSelector(const nsAttrSelector& aCopy);
nsAttrSelector(PRInt32 aNameSpace, nsIAtom* aAttr, PRUint8 aFunction,
const nsString& aValue, PRBool aCaseSensitive);
~nsAttrSelector(void);
PRBool Equals(const nsAttrSelector* aOther) const;
/** Do a deep clone. Should be used only on the first in the linked list. */
nsAttrSelector* Clone() const { return Clone(PR_TRUE); }
PRInt32 mNameSpace;
nsIAtom* mAttr;
nsCOMPtr<nsIAtom> mAttr;
PRUint8 mFunction;
PRPackedBool mCaseSensitive;
nsString mValue;
nsAttrSelector* mNext;
private:
nsAttrSelector* Clone(PRBool aDeep) const;
// These are not supported and are not implemented!
nsAttrSelector(const nsAttrSelector& aCopy);
nsAttrSelector& operator=(const nsAttrSelector& aCopy);
};
struct nsCSSSelector {
public:
nsCSSSelector(void);
nsCSSSelector(const nsCSSSelector& aCopy);
~nsCSSSelector(void);
nsCSSSelector& operator=(const nsCSSSelector& aCopy);
PRBool Equals(const nsCSSSelector* aOther) const;
/** Do a deep clone. Should be used only on the first in the linked list. */
nsCSSSelector* Clone() const { return Clone(PR_TRUE); }
void Reset(void);
void SetNameSpace(PRInt32 aNameSpace);
@ -133,6 +155,7 @@ public:
PRBool aAppend = PR_FALSE) const;
private:
nsCSSSelector* Clone(PRBool aDeep) const;
void AppendNegationToString(nsAString& aString);
void ToStringInternal(nsAString& aString, nsICSSStyleSheet* aSheet,
@ -151,6 +174,10 @@ public:
nsCSSSelector* mNegations;
nsCSSSelector* mNext;
private:
// These are not supported and are not implemented!
nsCSSSelector(const nsCSSSelector& aCopy);
nsCSSSelector& operator=(const nsCSSSelector& aCopy);
};
/**
@ -179,11 +206,17 @@ struct nsCSSSelectorList {
/**
* Do a deep clone. Should be used only on the first in the list.
*/
nsCSSSelectorList* Clone();
nsCSSSelectorList* Clone() const { return Clone(PR_TRUE); }
nsCSSSelector* mSelectors;
PRInt32 mWeight;
nsCSSSelectorList* mNext;
private:
nsCSSSelectorList* Clone(PRBool aDeep) const;
// These are not supported and are not implemented!
nsCSSSelectorList(const nsCSSSelectorList& aCopy);
nsCSSSelectorList& operator=(const nsCSSSelectorList& aCopy);
};
// IID for the nsICSSStyleRule interface {00803ccc-66e8-4ec8-a037-45e901bb5304}