diff --git a/layout/style/nsCSSStyleRule.cpp b/layout/style/nsCSSStyleRule.cpp index 91a6b388f17d..295a92a83f5d 100644 --- a/layout/style/nsCSSStyleRule.cpp +++ b/layout/style/nsCSSStyleRule.cpp @@ -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 ------------------------------- diff --git a/layout/style/nsICSSStyleRule.h b/layout/style/nsICSSStyleRule.h index 3202be648324..51d26a6c81c2 100644 --- a/layout/style/nsICSSStyleRule.h +++ b/layout/style/nsICSSStyleRule.h @@ -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 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 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 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}