зеркало из https://github.com/mozilla/gecko-dev.git
Use string buffers to store strings in nsCSSValue so we don't have to alloc in
copy constructors and such. Bug 350141, r+sr=dbaron
This commit is contained in:
Родитель
0fa26c65c2
Коммит
e1973f01bc
|
@ -2679,7 +2679,7 @@ nsGenericHTMLElement::MapBackgroundInto(const nsMappedAttributes* aAttributes,
|
|||
// background
|
||||
const nsAttrValue* value = aAttributes->GetAttr(nsHTMLAtoms::background);
|
||||
if (value && value->Type() == nsAttrValue::eString) {
|
||||
nsAutoString spec(value->GetStringValue());
|
||||
const nsString& spec = value->GetStringValue();
|
||||
if (!spec.IsEmpty()) {
|
||||
// Resolve url to an absolute url
|
||||
// XXX this breaks if the HTML element has an xml:base
|
||||
|
@ -2692,15 +2692,18 @@ nsGenericHTMLElement::MapBackgroundInto(const nsMappedAttributes* aAttributes,
|
|||
nsresult rv = nsContentUtils::NewURIWithDocumentCharset(
|
||||
getter_AddRefs(uri), spec, doc, doc->GetBaseURI());
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCSSValue::Image *img =
|
||||
new nsCSSValue::Image(uri, spec.get(), doc->GetDocumentURI(),
|
||||
doc, PR_TRUE);
|
||||
if (img) {
|
||||
if (img->mString) {
|
||||
// Note that this should generally succeed here, due to the way
|
||||
// |spec| is created. Maybe we should just add an nsStringBuffer
|
||||
// accessor on nsAttrValue?
|
||||
nsStringBuffer* buffer = nsCSSValue::BufferFromString(spec);
|
||||
if (NS_LIKELY(buffer != 0)) {
|
||||
nsCSSValue::Image *img =
|
||||
new nsCSSValue::Image(uri, buffer, doc->GetDocumentURI(),
|
||||
doc, PR_TRUE);
|
||||
buffer->Release();
|
||||
if (NS_LIKELY(img != 0)) {
|
||||
aData->mColorData->mBackImage.SetImageValue(img);
|
||||
}
|
||||
else
|
||||
delete img;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4007,11 +4007,16 @@ PRBool CSSParserImpl::ParseURL(nsresult& aErrorCode, nsCSSValue& aValue)
|
|||
if (ExpectSymbol(aErrorCode, ')', PR_TRUE)) {
|
||||
// Set a null value on failure. Most failure cases should be
|
||||
// NS_ERROR_MALFORMED_URI.
|
||||
nsCSSValue::URL *url =
|
||||
new nsCSSValue::URL(uri, tk->mIdent.get(), mSheetURL);
|
||||
if (!url || !url->mString) {
|
||||
nsStringBuffer* buffer = nsCSSValue::BufferFromString(tk->mIdent);
|
||||
if (NS_UNLIKELY(!buffer)) {
|
||||
aErrorCode = NS_ERROR_OUT_OF_MEMORY;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
nsCSSValue::URL *url = new nsCSSValue::URL(uri, buffer, mSheetURL);
|
||||
buffer->Release();
|
||||
if (NS_UNLIKELY(!url)) {
|
||||
aErrorCode = NS_ERROR_OUT_OF_MEMORY;
|
||||
delete url;
|
||||
return PR_FALSE;
|
||||
}
|
||||
aValue.SetURLValue(url);
|
||||
|
|
|
@ -48,9 +48,6 @@
|
|||
// Paint forcing
|
||||
#include "prenv.h"
|
||||
|
||||
//#include "nsStyleConsts.h"
|
||||
|
||||
|
||||
nsCSSValue::nsCSSValue(PRInt32 aValue, nsCSSUnit aUnit)
|
||||
: mUnit(aUnit)
|
||||
{
|
||||
|
@ -79,12 +76,17 @@ nsCSSValue::nsCSSValue(float aValue, nsCSSUnit aUnit)
|
|||
}
|
||||
}
|
||||
|
||||
nsCSSValue::nsCSSValue(const nsAString& aValue, nsCSSUnit aUnit)
|
||||
nsCSSValue::nsCSSValue(const nsString& aValue, nsCSSUnit aUnit)
|
||||
: mUnit(aUnit)
|
||||
{
|
||||
NS_ASSERTION((eCSSUnit_String <= aUnit) && (aUnit <= eCSSUnit_Attr), "not a string value");
|
||||
if ((eCSSUnit_String <= aUnit) && (aUnit <= eCSSUnit_Attr)) {
|
||||
mValue.mString = ToNewUnicode(aValue);
|
||||
mValue.mString = BufferFromString(aValue);
|
||||
if (NS_UNLIKELY(!mValue.mString)) {
|
||||
// XXXbz not much we can do here; just make sure that our promise of a
|
||||
// non-null mValue.mString holds for string units.
|
||||
mUnit = eCSSUnit_Null;
|
||||
}
|
||||
}
|
||||
else {
|
||||
mUnit = eCSSUnit_Null;
|
||||
|
@ -125,12 +127,8 @@ nsCSSValue::nsCSSValue(const nsCSSValue& aCopy)
|
|||
: mUnit(aCopy.mUnit)
|
||||
{
|
||||
if ((eCSSUnit_String <= mUnit) && (mUnit <= eCSSUnit_Attr)) {
|
||||
if (nsnull != aCopy.mValue.mString) {
|
||||
mValue.mString = NS_strdup(aCopy.mValue.mString);
|
||||
}
|
||||
else {
|
||||
mValue.mString = nsnull;
|
||||
}
|
||||
mValue.mString = aCopy.mValue.mString;
|
||||
mValue.mString->AddRef();
|
||||
}
|
||||
else if ((eCSSUnit_Integer <= mUnit) && (mUnit <= eCSSUnit_Enumerated)) {
|
||||
mValue.mInt = aCopy.mValue.mInt;
|
||||
|
@ -173,14 +171,8 @@ PRBool nsCSSValue::operator==(const nsCSSValue& aOther) const
|
|||
{
|
||||
if (mUnit == aOther.mUnit) {
|
||||
if ((eCSSUnit_String <= mUnit) && (mUnit <= eCSSUnit_Attr)) {
|
||||
if (nsnull == mValue.mString) {
|
||||
if (nsnull == aOther.mValue.mString) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
else if (nsnull != aOther.mValue.mString) {
|
||||
return (NS_strcmp(mValue.mString, aOther.mValue.mString) == 0);
|
||||
}
|
||||
return (NS_strcmp(GetBufferValue(mValue.mString),
|
||||
GetBufferValue(aOther.mValue.mString)) == 0);
|
||||
}
|
||||
else if ((eCSSUnit_Integer <= mUnit) && (mUnit <= eCSSUnit_Enumerated)) {
|
||||
return mValue.mInt == aOther.mValue.mInt;
|
||||
|
@ -277,14 +269,19 @@ void nsCSSValue::SetFloatValue(float aValue, nsCSSUnit aUnit)
|
|||
}
|
||||
}
|
||||
|
||||
void nsCSSValue::SetStringValue(const nsAString& aValue,
|
||||
void nsCSSValue::SetStringValue(const nsString& aValue,
|
||||
nsCSSUnit aUnit)
|
||||
{
|
||||
NS_ASSERTION((eCSSUnit_String <= aUnit) && (aUnit <= eCSSUnit_Attr), "not a string unit");
|
||||
Reset();
|
||||
if ((eCSSUnit_String <= aUnit) && (aUnit <= eCSSUnit_Attr)) {
|
||||
mUnit = aUnit;
|
||||
mValue.mString = ToNewUnicode(aValue);
|
||||
mValue.mString = BufferFromString(aValue);
|
||||
if (NS_UNLIKELY(!mValue.mString)) {
|
||||
// XXXbz not much we can do here; just make sure that our promise of a
|
||||
// non-null mValue.mString holds for string units.
|
||||
mUnit = eCSSUnit_Null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -360,26 +357,40 @@ void nsCSSValue::StartImageLoad(nsIDocument* aDocument, PRBool aIsBGImage) const
|
|||
mValue.mURL->mReferrer,
|
||||
aDocument, aIsBGImage);
|
||||
if (image) {
|
||||
if (image->mString) {
|
||||
nsCSSValue* writable = NS_CONST_CAST(nsCSSValue*, this);
|
||||
writable->SetImageValue(image);
|
||||
} else {
|
||||
delete image;
|
||||
}
|
||||
nsCSSValue* writable = NS_CONST_CAST(nsCSSValue*, this);
|
||||
writable->SetImageValue(image);
|
||||
}
|
||||
}
|
||||
|
||||
nsCSSValue::Image::Image(nsIURI* aURI, const PRUnichar* aString,
|
||||
// static
|
||||
nsStringBuffer*
|
||||
nsCSSValue::BufferFromString(const nsString& aValue)
|
||||
{
|
||||
nsStringBuffer* buffer = nsStringBuffer::FromString(aValue);
|
||||
if (buffer) {
|
||||
buffer->AddRef();
|
||||
return buffer;
|
||||
}
|
||||
|
||||
PRUnichar length = aValue.Length();
|
||||
buffer = nsStringBuffer::Alloc((length + 1) * sizeof(PRUnichar));
|
||||
if (NS_LIKELY(buffer != 0)) {
|
||||
PRUnichar* data = NS_STATIC_CAST(PRUnichar*, buffer->Data());
|
||||
nsCharTraits<PRUnichar>::copy(data, aValue.get(), length);
|
||||
// Null-terminate.
|
||||
data[length] = 0;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
nsCSSValue::Image::Image(nsIURI* aURI, nsStringBuffer* aString,
|
||||
nsIURI* aReferrer, nsIDocument* aDocument,
|
||||
PRBool aIsBGImage)
|
||||
: URL(aURI, aString, aReferrer)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsCSSValue::Image);
|
||||
|
||||
// Check for failed mString allocation first
|
||||
if (!mString)
|
||||
return;
|
||||
|
||||
// If the pref is enabled, force all background image loads to
|
||||
// complete before firing onload for the document. Otherwise, background
|
||||
// image loads are special and don't block onload.
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "nsCOMPtr.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCRTGlue.h"
|
||||
#include "nsStringBuffer.h"
|
||||
|
||||
class imgIRequest;
|
||||
class nsIDocument;
|
||||
|
@ -145,7 +146,7 @@ public:
|
|||
|
||||
nsCSSValue(PRInt32 aValue, nsCSSUnit aUnit) NS_HIDDEN;
|
||||
nsCSSValue(float aValue, nsCSSUnit aUnit) NS_HIDDEN;
|
||||
nsCSSValue(const nsAString& aValue, nsCSSUnit aUnit) NS_HIDDEN;
|
||||
nsCSSValue(const nsString& aValue, nsCSSUnit aUnit) NS_HIDDEN;
|
||||
explicit nsCSSValue(nscolor aValue) NS_HIDDEN;
|
||||
nsCSSValue(Array* aArray, nsCSSUnit aUnit) NS_HIDDEN;
|
||||
explicit nsCSSValue(URL* aValue) NS_HIDDEN;
|
||||
|
@ -199,9 +200,8 @@ public:
|
|||
NS_ASSERTION(eCSSUnit_String <= mUnit && mUnit <= eCSSUnit_Attr,
|
||||
"not a string value");
|
||||
aBuffer.Truncate();
|
||||
if (nsnull != mValue.mString) {
|
||||
aBuffer.Append(mValue.mString);
|
||||
}
|
||||
PRUint32 len = NS_strlen(GetBufferValue(mValue.mString));
|
||||
mValue.mString->ToString(len, aBuffer);
|
||||
return aBuffer;
|
||||
}
|
||||
|
||||
|
@ -209,7 +209,7 @@ public:
|
|||
{
|
||||
NS_ASSERTION(eCSSUnit_String <= mUnit && mUnit <= eCSSUnit_Attr,
|
||||
"not a string value");
|
||||
return mValue.mString;
|
||||
return GetBufferValue(mValue.mString);
|
||||
}
|
||||
|
||||
nscolor GetColorValue() const
|
||||
|
@ -237,8 +237,9 @@ public:
|
|||
{
|
||||
NS_ASSERTION(mUnit == eCSSUnit_URL || mUnit == eCSSUnit_Image,
|
||||
"not a URL value");
|
||||
return mUnit == eCSSUnit_URL ?
|
||||
mValue.mURL->mString : mValue.mImage->mString;
|
||||
return GetBufferValue(mUnit == eCSSUnit_URL ?
|
||||
mValue.mURL->mString :
|
||||
mValue.mImage->mString);
|
||||
}
|
||||
|
||||
// Not making this inline because that would force us to include
|
||||
|
@ -250,9 +251,8 @@ public:
|
|||
|
||||
NS_HIDDEN_(void) Reset() // sets to null
|
||||
{
|
||||
if ((eCSSUnit_String <= mUnit) && (mUnit <= eCSSUnit_Attr) &&
|
||||
(nsnull != mValue.mString)) {
|
||||
NS_Free(mValue.mString);
|
||||
if (eCSSUnit_String <= mUnit && mUnit <= eCSSUnit_Attr) {
|
||||
mValue.mString->Release();
|
||||
} else if (eCSSUnit_Array <= mUnit && mUnit <= eCSSUnit_Counters) {
|
||||
mValue.mArray->Release();
|
||||
} else if (eCSSUnit_URL == mUnit) {
|
||||
|
@ -267,7 +267,7 @@ public:
|
|||
NS_HIDDEN_(void) SetIntValue(PRInt32 aValue, nsCSSUnit aUnit);
|
||||
NS_HIDDEN_(void) SetPercentValue(float aValue);
|
||||
NS_HIDDEN_(void) SetFloatValue(float aValue, nsCSSUnit aUnit);
|
||||
NS_HIDDEN_(void) SetStringValue(const nsAString& aValue, nsCSSUnit aUnit);
|
||||
NS_HIDDEN_(void) SetStringValue(const nsString& aValue, nsCSSUnit aUnit);
|
||||
NS_HIDDEN_(void) SetColorValue(nscolor aValue);
|
||||
NS_HIDDEN_(void) SetArrayValue(nsCSSValue::Array* aArray, nsCSSUnit aUnit);
|
||||
NS_HIDDEN_(void) SetURLValue(nsCSSValue::URL* aURI);
|
||||
|
@ -281,6 +281,10 @@ public:
|
|||
PRBool aIsBGImage = PR_FALSE)
|
||||
const; // Not really const, but pretending
|
||||
|
||||
// Returns an already addrefed buffer. Can return null on allocation
|
||||
// failure.
|
||||
static nsStringBuffer* BufferFromString(const nsString& aValue);
|
||||
|
||||
struct Array {
|
||||
|
||||
// return |Array| with reference count of zero
|
||||
|
@ -372,30 +376,28 @@ public:
|
|||
};
|
||||
|
||||
struct URL {
|
||||
// Caller must delete this object immediately if the allocation of
|
||||
// |mString| fails.
|
||||
URL(nsIURI* aURI, const PRUnichar* aString, nsIURI* aReferrer)
|
||||
// aString must not be null.
|
||||
URL(nsIURI* aURI, nsStringBuffer* aString, nsIURI* aReferrer)
|
||||
: mURI(aURI),
|
||||
mString(NS_strdup(aString)),
|
||||
mString(aString),
|
||||
mReferrer(aReferrer),
|
||||
mRefCnt(0)
|
||||
{
|
||||
mString->AddRef();
|
||||
MOZ_COUNT_CTOR(nsCSSValue::URL);
|
||||
}
|
||||
|
||||
~URL()
|
||||
{
|
||||
// null |mString| isn't valid normally, but is checked by callers
|
||||
// of the constructor
|
||||
if (mString)
|
||||
NS_Free(mString);
|
||||
mString->Release();
|
||||
MOZ_COUNT_DTOR(nsCSSValue::URL);
|
||||
}
|
||||
|
||||
PRBool operator==(const URL& aOther)
|
||||
{
|
||||
PRBool eq;
|
||||
return NS_strcmp(mString, aOther.mString) == 0 &&
|
||||
return NS_strcmp(GetBufferValue(mString),
|
||||
GetBufferValue(aOther.mString)) == 0 &&
|
||||
(mURI == aOther.mURI || // handles null == null
|
||||
(mURI && aOther.mURI &&
|
||||
NS_SUCCEEDED(mURI->Equals(aOther.mURI, &eq)) &&
|
||||
|
@ -403,7 +405,8 @@ public:
|
|||
}
|
||||
|
||||
nsCOMPtr<nsIURI> mURI; // null == invalid URL
|
||||
PRUnichar* mString;
|
||||
nsStringBuffer* mString; // Could use nsRefPtr, but it'd add useless
|
||||
// null-checks; this is never null.
|
||||
nsCOMPtr<nsIURI> mReferrer;
|
||||
|
||||
void AddRef() { ++mRefCnt; }
|
||||
|
@ -416,7 +419,8 @@ public:
|
|||
// Not making the constructor and destructor inline because that would
|
||||
// force us to include imgIRequest.h, which leads to REQUIRES hell, since
|
||||
// this header is included all over.
|
||||
Image(nsIURI* aURI, const PRUnichar* aString, nsIURI* aReferrer,
|
||||
// aString must not be null.
|
||||
Image(nsIURI* aURI, nsStringBuffer* aString, nsIURI* aReferrer,
|
||||
nsIDocument* aDocument, PRBool aIsBGImage = PR_FALSE) NS_HIDDEN;
|
||||
~Image() NS_HIDDEN;
|
||||
|
||||
|
@ -429,12 +433,19 @@ public:
|
|||
void Release() { if (--mRefCnt == 0) delete this; }
|
||||
};
|
||||
|
||||
private:
|
||||
static const PRUnichar* GetBufferValue(nsStringBuffer* aBuffer) {
|
||||
return NS_STATIC_CAST(PRUnichar*, aBuffer->Data());
|
||||
}
|
||||
|
||||
protected:
|
||||
nsCSSUnit mUnit;
|
||||
union {
|
||||
PRInt32 mInt;
|
||||
float mFloat;
|
||||
PRUnichar* mString;
|
||||
// Note: the capacity of the buffer may exceed the length of the string.
|
||||
// If we're of a string type, mString is not null.
|
||||
nsStringBuffer* mString;
|
||||
nscolor mColor;
|
||||
Array* mArray;
|
||||
URL* mURL;
|
||||
|
|
Загрузка…
Ссылка в новой задаче