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:
bzbarsky%mit.edu 2006-12-13 15:49:36 +00:00
Родитель 0fa26c65c2
Коммит e1973f01bc
4 изменённых файлов: 97 добавлений и 67 удалений

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

@ -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;