diff --git a/mozilla/content/base/src/nsHTMLValue.cpp b/mozilla/content/base/src/nsHTMLValue.cpp index a52ad27af79..ca58c1a48e2 100644 --- a/mozilla/content/base/src/nsHTMLValue.cpp +++ b/mozilla/content/base/src/nsHTMLValue.cpp @@ -42,94 +42,60 @@ #include "nsReadableUtils.h" #include "nsUnicharUtils.h" #include "nsCRT.h" +#include "nsMemory.h" nsHTMLValue::nsHTMLValue(nsHTMLUnit aUnit) - : mUnit(aUnit) + : mUnit(aUnit), mStorageFlags(HTMLSTORAGE_NORMAL) { - NS_ASSERTION((aUnit <= eHTMLUnit_Empty), "not a valueless unit"); - if (aUnit > eHTMLUnit_Empty) { + NS_ASSERTION(GetUnitClass() == HTMLUNIT_NOSTORE, "not a valueless unit"); + if (GetUnitClass() != HTMLUNIT_NOSTORE) { mUnit = eHTMLUnit_Null; } mValue.mString = nsnull; } nsHTMLValue::nsHTMLValue(PRInt32 aValue, nsHTMLUnit aUnit) - : mUnit(aUnit) + : mUnit(aUnit), mStorageFlags(HTMLSTORAGE_NORMAL) { - NS_ASSERTION((eHTMLUnit_Integer == aUnit) || - (eHTMLUnit_Enumerated == aUnit) || - (eHTMLUnit_Proportional == aUnit) || - (eHTMLUnit_Pixel == aUnit), "not an integer value"); - if ((eHTMLUnit_Integer == aUnit) || - (eHTMLUnit_Enumerated == aUnit) || - (eHTMLUnit_Proportional == aUnit) || - (eHTMLUnit_Pixel == aUnit)) { + NS_ASSERTION(GetUnitClass() == HTMLUNIT_INTEGER || + GetUnitClass() == HTMLUNIT_PIXEL, "unit not an integer unit"); + if (GetUnitClass() == HTMLUNIT_INTEGER || + GetUnitClass() == HTMLUNIT_PIXEL) { mValue.mInt = aValue; - } - else { + } else { mUnit = eHTMLUnit_Null; - mValue.mInt = 0; + mValue.mString = nsnull; } } nsHTMLValue::nsHTMLValue(float aValue) - : mUnit(eHTMLUnit_Percent) + : mUnit(eHTMLUnit_Percent), mStorageFlags(HTMLSTORAGE_NORMAL) { mValue.mFloat = aValue; } nsHTMLValue::nsHTMLValue(const nsAString& aValue, nsHTMLUnit aUnit) - : mUnit(aUnit) + : mUnit(aUnit), mStorageFlags(HTMLSTORAGE_NORMAL) { - NS_ASSERTION((eHTMLUnit_String == aUnit) || - (eHTMLUnit_ColorName == aUnit), "not a string value"); - if ((eHTMLUnit_String == aUnit) || - (eHTMLUnit_ColorName == aUnit)) { - mValue.mString = ToNewUnicode(aValue); - } - else { - mUnit = eHTMLUnit_Null; - mValue.mInt = 0; - } + SetStringValueInternal(aValue, aUnit); } nsHTMLValue::nsHTMLValue(nsISupports* aValue) - : mUnit(eHTMLUnit_ISupports) + : mUnit(eHTMLUnit_ISupports), mStorageFlags(HTMLSTORAGE_NORMAL) { mValue.mISupports = aValue; NS_IF_ADDREF(mValue.mISupports); } nsHTMLValue::nsHTMLValue(nscolor aValue) - : mUnit(eHTMLUnit_Color) + : mUnit(eHTMLUnit_Color), mStorageFlags(HTMLSTORAGE_NORMAL) { mValue.mColor = aValue; } nsHTMLValue::nsHTMLValue(const nsHTMLValue& aCopy) - : mUnit(aCopy.mUnit) { - if ((eHTMLUnit_String == mUnit) || (eHTMLUnit_ColorName == mUnit)) { - if (nsnull != aCopy.mValue.mString) { - mValue.mString = nsCRT::strdup(aCopy.mValue.mString); - } - else { - mValue.mString = nsnull; - } - } - else if (eHTMLUnit_ISupports == mUnit) { - mValue.mISupports = aCopy.mValue.mISupports; - NS_IF_ADDREF(mValue.mISupports); - } - else if (eHTMLUnit_Color == mUnit){ - mValue.mColor = aCopy.mValue.mColor; - } - else if (eHTMLUnit_Percent == mUnit) { - mValue.mFloat = aCopy.mValue.mFloat; - } - else { - mValue.mInt = aCopy.mValue.mInt; - } + InitializeFrom(aCopy); } nsHTMLValue::~nsHTMLValue(void) @@ -140,79 +106,81 @@ nsHTMLValue::~nsHTMLValue(void) nsHTMLValue& nsHTMLValue::operator=(const nsHTMLValue& aCopy) { Reset(); - mUnit = aCopy.mUnit; - if ((eHTMLUnit_String == mUnit) || (eHTMLUnit_ColorName == mUnit)) { - if (nsnull != aCopy.mValue.mString) { - mValue.mString = nsCRT::strdup(aCopy.mValue.mString); - } - } - else if (eHTMLUnit_ISupports == mUnit) { - mValue.mISupports = aCopy.mValue.mISupports; - NS_IF_ADDREF(mValue.mISupports); - } - else if (eHTMLUnit_Color == mUnit){ - mValue.mColor = aCopy.mValue.mColor; - } - else if (eHTMLUnit_Percent == mUnit) { - mValue.mFloat = aCopy.mValue.mFloat; - } - else { - mValue.mInt = aCopy.mValue.mInt; - } + InitializeFrom(aCopy); return *this; } PRBool nsHTMLValue::operator==(const nsHTMLValue& aOther) const { - if (mUnit == aOther.mUnit) { - if ((eHTMLUnit_String == mUnit) || (eHTMLUnit_ColorName == mUnit)) { - if (nsnull == mValue.mString) { - if (nsnull == aOther.mValue.mString) { - return PR_TRUE; - } - } - else if (nsnull != aOther.mValue.mString) { - return nsDependentString(mValue.mString).Equals(nsDependentString(aOther.mValue.mString), - nsCaseInsensitiveStringComparator()); - } - } - else if (eHTMLUnit_ISupports == mUnit) { - return PRBool(mValue.mISupports == aOther.mValue.mISupports); - } - else if (eHTMLUnit_Color == mUnit){ - return PRBool(mValue.mColor == aOther.mValue.mColor); - } - else if (eHTMLUnit_Percent == mUnit) { - return PRBool(mValue.mFloat == aOther.mValue.mFloat); - } - else { - return PRBool(mValue.mInt == aOther.mValue.mInt); - } + if (mUnit != aOther.mUnit) { + return PR_FALSE; + } + // Call GetUnit() so that we turn StringWithLength into String + PRUint32 unitClass = GetUnitClass(); + switch (unitClass) { + case HTMLUNIT_NOSTORE: + return PR_TRUE; + + case HTMLUNIT_STRING: + if (mValue.mString && aOther.mValue.mString) { + return GetDependentString().Equals(aOther.GetDependentString(), + nsCaseInsensitiveStringComparator()); + } + // One of them is null. An == check will see if they are both null. + return mValue.mString == aOther.mValue.mString; + + case HTMLUNIT_INTEGER: + case HTMLUNIT_PIXEL: + return mValue.mInt == aOther.mValue.mInt; + + case HTMLUNIT_COLOR: + return mValue.mColor == aOther.mValue.mColor; + + case HTMLUNIT_ISUPPORTS: + return mValue.mISupports == aOther.mValue.mISupports; + + case HTMLUNIT_PERCENT: + return mValue.mFloat == aOther.mValue.mFloat; + + default: + NS_WARNING("Unknown unit"); + return PR_TRUE; } - return PR_FALSE; } PRUint32 nsHTMLValue::HashValue(void) const { - return PRUint32(mUnit) ^ - ((((eHTMLUnit_String == mUnit) || (eHTMLUnit_ColorName == mUnit)) && - (nsnull != mValue.mString)) ? - nsCRT::HashCode(mValue.mString) : - mValue.mInt); + PRUint32 retval; + if (GetUnitClass() == HTMLUNIT_STRING) { + if (mStorageFlags & HTMLSTORAGE_STRWITHLEN) { + retval = mValue.mString ? nsCheapStringBufferUtils::HashCode(mValue.mString) + : 0; + } else { + retval = mValue.mString ? nsCRT::HashCode(mValue.mString) : 0; + } + } else { + retval = mValue.mInt; + } + return retval ^ PRUint32(mUnit); } void nsHTMLValue::Reset(void) { - if ((eHTMLUnit_String == mUnit) || (eHTMLUnit_ColorName == mUnit)) { - if (nsnull != mValue.mString) { - nsCRT::free(mValue.mString); + if (GetUnitClass() == HTMLUNIT_STRING) { + if (mValue.mString) { + if (mStorageFlags & HTMLSTORAGE_STRWITHLEN) { + nsCheapStringBufferUtils::Free(mValue.mString); + } else { + nsMemory::Free(mValue.mString); + } } } - else if (eHTMLUnit_ISupports == mUnit) { + else if (mUnit == eHTMLUnit_ISupports) { NS_IF_RELEASE(mValue.mISupports); } mUnit = eHTMLUnit_Null; + mStorageFlags = 0; mValue.mString = nsnull; } @@ -220,14 +188,12 @@ void nsHTMLValue::Reset(void) void nsHTMLValue::SetIntValue(PRInt32 aValue, nsHTMLUnit aUnit) { Reset(); - NS_ASSERTION((eHTMLUnit_Integer == aUnit) || - (eHTMLUnit_Enumerated == aUnit) || - (eHTMLUnit_Proportional == aUnit), "not an int value"); - if ((eHTMLUnit_Integer == aUnit) || - (eHTMLUnit_Enumerated == aUnit) || - (eHTMLUnit_Proportional == aUnit)) { - mUnit = aUnit; + mUnit = aUnit; + NS_ASSERTION(GetUnitClass() == HTMLUNIT_INTEGER, "not an int value"); + if (GetUnitClass() == HTMLUNIT_INTEGER) { mValue.mInt = aValue; + } else { + mUnit = eHTMLUnit_Null; } } @@ -245,14 +211,50 @@ void nsHTMLValue::SetPercentValue(float aValue) mValue.mFloat = aValue; } +static inline PRBool +ShouldStoreLength(const nsAString& aStr, PRUint32 aLen) +{ + // Always remember the length of the string if the length is greater than 30 + if (aLen > 30) { + return PR_TRUE; + } + // Obviously never remember the length of the string if it is empty :) + if (aLen == 0) { + return PR_FALSE; + } + // Remember the length of the string if it has embedded nulls + nsAString::const_iterator begin, end; + return FindCharInReadable('\0', aStr.BeginReading(begin), + aStr.EndReading(end)); +} + +void nsHTMLValue::SetStringValueInternal(const nsAString& aValue, + nsHTMLUnit aUnit) +{ + NS_ASSERTION(GetUnitClass() == HTMLUNIT_STRING, "unit not a string unit!"); + if (GetUnitClass() == HTMLUNIT_STRING) { + // Remember the length of the string if necessary + PRUint32 len = aValue.Length(); + if (ShouldStoreLength(aValue, len)) { + mStorageFlags = HTMLSTORAGE_STRWITHLEN; + nsCheapStringBufferUtils::CopyToBuffer(mValue.mString, aValue, len); + return; + } + + // Else just store as a normal string + mValue.mString = ToNewUnicode(aValue); + } else { + mUnit = eHTMLUnit_Null; + mValue.mString = nsnull; + } +} + void nsHTMLValue::SetStringValue(const nsAString& aValue, nsHTMLUnit aUnit) { Reset(); - if ((eHTMLUnit_String == aUnit) || (eHTMLUnit_ColorName == aUnit)) { - mUnit = aUnit; - mValue.mString = ToNewUnicode(aValue); - } + mUnit = aUnit; + SetStringValueInternal(aValue, aUnit); } void nsHTMLValue::SetISupportsValue(nsISupports* aValue) @@ -279,64 +281,72 @@ void nsHTMLValue::SetEmptyValue(void) #ifdef DEBUG void nsHTMLValue::AppendToString(nsAString& aBuffer) const { - if (eHTMLUnit_Null == mUnit) { - return; - } - - if (eHTMLUnit_Empty == mUnit) { - } - else if ((eHTMLUnit_String == mUnit) || (eHTMLUnit_ColorName == mUnit)) { - if (nsnull != mValue.mString) { + switch (GetUnitClass()) { + case HTMLUNIT_NOSTORE: + break; + case HTMLUNIT_STRING: + if (mValue.mString) { aBuffer.Append(PRUnichar('"')); - aBuffer.Append(mValue.mString); + aBuffer.Append(GetDependentString()); aBuffer.Append(PRUnichar('"')); - } - else { + } else { aBuffer.Append(NS_LITERAL_STRING("null str")); } - } - else if (eHTMLUnit_ISupports == mUnit) { - aBuffer.Append(NS_LITERAL_STRING("0x")); - nsAutoString intStr; - intStr.AppendInt(NS_PTR_TO_INT32(mValue.mISupports), 16); - aBuffer.Append(intStr); - } - else if (eHTMLUnit_Color == mUnit){ - nsAutoString intStr; - intStr.Append(NS_LITERAL_STRING("(0x")); - intStr.AppendInt(NS_GET_R(mValue.mColor), 16); - intStr.Append(NS_LITERAL_STRING(" 0x")); - intStr.AppendInt(NS_GET_G(mValue.mColor), 16); - intStr.Append(NS_LITERAL_STRING(" 0x")); - intStr.AppendInt(NS_GET_B(mValue.mColor), 16); - intStr.Append(NS_LITERAL_STRING(" 0x")); - intStr.AppendInt(NS_GET_A(mValue.mColor), 16); - intStr.Append(PRUnichar(')')); + break; + case HTMLUNIT_INTEGER: + case HTMLUNIT_PIXEL: + { + nsAutoString intStr; + intStr.AppendInt(mValue.mInt, 10); + intStr.Append(NS_LITERAL_STRING("[0x")); + intStr.AppendInt(mValue.mInt, 16); + intStr.Append(PRUnichar(']')); - aBuffer.Append(intStr); - } - else if (eHTMLUnit_Percent == mUnit) { - nsAutoString floatStr; - floatStr.AppendFloat(mValue.mFloat * 100.0f); - aBuffer.Append(floatStr); - } - else { - nsAutoString intStr; - intStr.AppendInt(mValue.mInt, 10); - intStr.Append(NS_LITERAL_STRING("[0x")); - intStr.AppendInt(mValue.mInt, 16); - intStr.Append(PRUnichar(']')); + aBuffer.Append(intStr); + } + break; + case HTMLUNIT_COLOR: + { + nsAutoString intStr; + intStr.Append(NS_LITERAL_STRING("(0x")); + intStr.AppendInt(NS_GET_R(mValue.mColor), 16); + intStr.Append(NS_LITERAL_STRING(" 0x")); + intStr.AppendInt(NS_GET_G(mValue.mColor), 16); + intStr.Append(NS_LITERAL_STRING(" 0x")); + intStr.AppendInt(NS_GET_B(mValue.mColor), 16); + intStr.Append(NS_LITERAL_STRING(" 0x")); + intStr.AppendInt(NS_GET_A(mValue.mColor), 16); + intStr.Append(PRUnichar(')')); - aBuffer.Append(intStr); + aBuffer.Append(intStr); + } + break; + case HTMLUNIT_ISUPPORTS: + { + aBuffer.Append(NS_LITERAL_STRING("0x")); + nsAutoString intStr; + intStr.AppendInt(NS_PTR_TO_INT32(mValue.mISupports), 16); + aBuffer.Append(intStr); + } + break; + case HTMLUNIT_PERCENT: + { + nsAutoString floatStr; + floatStr.AppendFloat(mValue.mFloat * 100.0f); + aBuffer.Append(floatStr); + } + break; + default: + NS_ERROR("Unknown HTMLValue type!"); } + // + // Append the type name for types that are ambiguous + // switch (mUnit) { - case eHTMLUnit_Null: break; - case eHTMLUnit_Empty: break; - case eHTMLUnit_String: break; - case eHTMLUnit_ColorName: break; + case eHTMLUnit_Null: aBuffer.Append(NS_LITERAL_STRING("null")); break; + case eHTMLUnit_Empty: aBuffer.Append(NS_LITERAL_STRING("empty")); break; case eHTMLUnit_ISupports: aBuffer.Append(NS_LITERAL_STRING("ptr")); break; - case eHTMLUnit_Integer: break; case eHTMLUnit_Enumerated: aBuffer.Append(NS_LITERAL_STRING("enum")); break; case eHTMLUnit_Proportional: aBuffer.Append(NS_LITERAL_STRING("*")); break; case eHTMLUnit_Color: aBuffer.Append(NS_LITERAL_STRING("rbga")); break; @@ -346,3 +356,49 @@ void nsHTMLValue::AppendToString(nsAString& aBuffer) const aBuffer.Append(PRUnichar(' ')); } #endif // DEBUG + +void +nsHTMLValue::InitializeFrom(const nsHTMLValue& aCopy) +{ + mUnit = aCopy.mUnit; + mStorageFlags = aCopy.mStorageFlags; + switch (GetUnitClass()) { + case HTMLUNIT_NOSTORE: + mValue.mString = nsnull; + break; + + case HTMLUNIT_STRING: + if (aCopy.mValue.mString) { + if (aCopy.mStorageFlags & HTMLSTORAGE_STRWITHLEN) { + // Clone the string = (PRUint32) + PRUnichar*len + nsCheapStringBufferUtils::Clone(mValue.mString, aCopy.mValue.mString); + } else { + mValue.mString = ToNewUnicode(nsDependentString(aCopy.mValue.mString)); + } + } else { + mValue.mString = nsnull; + } + break; + + case HTMLUNIT_INTEGER: + case HTMLUNIT_PIXEL: + mValue.mInt = aCopy.mValue.mInt; + break; + + case HTMLUNIT_COLOR: + mValue.mColor = aCopy.mValue.mColor; + break; + + case HTMLUNIT_ISUPPORTS: + mValue.mISupports = aCopy.mValue.mISupports; + NS_IF_ADDREF(mValue.mISupports); + break; + + case HTMLUNIT_PERCENT: + mValue.mFloat = aCopy.mValue.mFloat; + break; + + default: + NS_ERROR("Unknown HTMLValue type!"); + } +} diff --git a/mozilla/content/base/src/nsHTMLValue.h b/mozilla/content/base/src/nsHTMLValue.h index 08554bf426b..15bb71572e9 100644 --- a/mozilla/content/base/src/nsHTMLValue.h +++ b/mozilla/content/base/src/nsHTMLValue.h @@ -43,20 +43,130 @@ #include "nsString.h" #include "nsISupports.h" -enum nsHTMLUnit { - eHTMLUnit_Null = 0, // (n/a) null unit, value is not specified - eHTMLUnit_Empty = 1, // (n/a) empty unit, value is not specified - eHTMLUnit_String = 10, // (nsString) a string value - eHTMLUnit_ISupports = 20, // (nsISupports*) a ref counted interface - eHTMLUnit_Integer = 50, // (int) simple value - eHTMLUnit_Enumerated = 51, // (int) value has enumerated meaning - eHTMLUnit_Proportional = 52, // (int) value is a relative proportion of some whole - eHTMLUnit_Color = 80, // (color) an RGBA value - eHTMLUnit_ColorName = 81, // (nsString/color) a color name value - eHTMLUnit_Percent = 90, // (float) 1.0 == 100%) value is percentage of something +#include "nsReadableUtils.h" +#include "nsCRT.h" - // Screen relative measure - eHTMLUnit_Pixel = 600 // (int) screen pixels +class nsCheapStringBufferUtils { +public: + /** + * Get the string pointer + * @param aBuf the buffer + * @return a pointer to the string + */ + static const PRUnichar* StrPtr(const PRUnichar* aBuf) { + NS_ASSERTION(aBuf, "Cannot work on null buffer!"); + return (const PRUnichar*)( ((const char*)aBuf) + sizeof(PRUint32) ); + } + static PRUnichar* StrPtr(PRUnichar* aBuf) { + NS_ASSERTION(aBuf, "Cannot work on null buffer!"); + return (PRUnichar*)( ((char*)aBuf) + sizeof(PRUint32) ); + } + /** + * Get the string length + * @param aBuf the buffer + * @return the string length + */ + static PRUint32 Length(const PRUnichar* aBuf) { + NS_ASSERTION(aBuf, "Cannot work on null buffer!"); + return *((PRUint32*)aBuf); + } + /** + * Get a DependentString from a buffer + * + * @param aBuf the buffer to get string from + * @return a DependentString representing this string + */ + static nsDependentSingleFragmentSubstring GetDependentString(const PRUnichar* aBuf) { + NS_ASSERTION(aBuf, "Cannot work on null buffer!"); + const PRUnichar* buf = StrPtr(aBuf); + return Substring(buf, buf + Length(aBuf)); + } + /** + * Construct from an AString + * @param aBuf the buffer to copy to + * @param aStr the string to construct from + * @param aLen the length of the string (passed for efficiency) + */ + static void CopyToBuffer(PRUnichar*& aBuf, const nsAString& aStr, PRUint32 aLen) { + NS_ASSERTION(aStr.Length() == aLen, "Wrong length passed in!"); + aBuf = (PRUnichar*)nsMemory::Alloc(sizeof(PRUint32) + + aLen * sizeof(PRUnichar)); + *((PRUint32*)aBuf) = aLen; + CopyUnicodeTo(aStr, 0, StrPtr(aBuf), aLen); + } + /** + * Construct from another nsCheapStringBuffer + * @param aBuf the buffer to put into + * @param aSrc the buffer to construct from + */ + static void Clone(PRUnichar*& aBuf, const PRUnichar* aSrc) { + NS_ASSERTION(aSrc, "Cannot work on null buffer!"); + aBuf = (PRUnichar*)nsMemory::Clone(aSrc, sizeof(PRUint32) + + Length(aSrc) * sizeof(PRUnichar)); + } + /** + * Free the memory for the buf + * @param aBuf the buffer to free + */ + static void Free(PRUnichar* aBuf) { + NS_ASSERTION(aBuf, "Cannot work on null buffer!"); + nsMemory::Free(aBuf); + } + /** + * Get a hashcode for the buffer + * @param aBuf the buffer + * @return the hashcode + */ + static PRUint32 HashCode(const PRUnichar* aBuf) { + NS_ASSERTION(aBuf, "Cannot work on null buffer!"); + return nsCRT::BufferHashCode((char*)StrPtr(aBuf), + Length(aBuf)*sizeof(PRUnichar)); + } +}; + +// +// nsHTMLUnit is two bytes: the class of type, and a specifier to distinguish +// between different things stored as the same type. Doing +// mUnit & HTMLUNIT_CLASS_MASK should give you the class of type. +// +#define HTMLUNIT_NOSTORE 0x0000 +#define HTMLUNIT_STRING 0x0100 +#define HTMLUNIT_INTEGER 0x0200 +#define HTMLUNIT_PIXEL 0x0400 +#define HTMLUNIT_COLOR 0x0800 +#define HTMLUNIT_ISUPPORTS 0x1000 +#define HTMLUNIT_PERCENT 0x2000 +#define HTMLUNIT_CLASS_MASK 0xff00 + +enum nsHTMLUnit { + // null, value is not specified: 0x0000 + eHTMLUnit_Null = HTMLUNIT_NOSTORE, + // empty, value is not specified: 0x0001 + eHTMLUnit_Empty = HTMLUNIT_NOSTORE | 1, + + // a string value + eHTMLUnit_String = HTMLUNIT_STRING, + // a color name value + eHTMLUnit_ColorName = HTMLUNIT_STRING | 1, + + // a simple int value + eHTMLUnit_Integer = HTMLUNIT_INTEGER, + // value has enumerated meaning + eHTMLUnit_Enumerated = HTMLUNIT_INTEGER | 1, + // value is a relative proportion of some whole + eHTMLUnit_Proportional = HTMLUNIT_INTEGER | 2, + + // screen pixels (screen relative measure) + eHTMLUnit_Pixel = HTMLUNIT_PIXEL, + + // an RGBA value + eHTMLUnit_Color = HTMLUNIT_COLOR, + + // (nsISupports*) a ref counted interface + eHTMLUnit_ISupports = HTMLUNIT_ISUPPORTS, + + // (1.0 == 100%) value is percentage of something + eHTMLUnit_Percent = HTMLUNIT_PERCENT }; /** @@ -81,14 +191,22 @@ public: PRBool operator!=(const nsHTMLValue& aOther) const; PRUint32 HashValue(void) const; - nsHTMLUnit GetUnit(void) const { return mUnit; } - PRInt32 GetIntValue(void) const; - PRInt32 GetPixelValue(void) const; - float GetPercentValue(void) const; - nsAString& GetStringValue(nsAString& aBuffer) const; - nsISupports* GetISupportsValue(void) const; - nscolor GetColorValue(void) const; + /** + * Get the unit of this HTMLValue + * @return the unit of this HTMLValue + */ + nsHTMLUnit GetUnit(void) const { return (nsHTMLUnit)mUnit; } + PRInt32 GetIntValue(void) const; + PRInt32 GetPixelValue(void) const; + float GetPercentValue(void) const; + nsAString& GetStringValue(nsAString& aBuffer) const; + nsISupports* GetISupportsValue(void) const; + nscolor GetColorValue(void) const; + + /** + * Reset the string to null type, freeing things in the process if necessary. + */ void Reset(void); void SetIntValue(PRInt32 aValue, nsHTMLUnit aUnit); void SetPixelValue(PRInt32 aValue); @@ -103,34 +221,98 @@ public: #endif protected: - nsHTMLUnit mUnit; + /** + * The unit of the value + * @see nsHTMLUnit + */ + PRUint16 mUnit; + /** Flags indicating specifics of the storage format (HTMLSTORAGE_*) */ + PRUint16 mStorageFlags; + /** + * The actual value. Please to not be adding more-than-4-byte things to this + * union. + */ union { + /** Int. */ PRInt32 mInt; + /** Float. */ float mFloat; + /** + * String. Depending on mStorageFlags & HTMLSTORAGE_STRWITHLEN, this may be + * stored with the first 4 bytes being the length (this is done for + * embedded nulls and long strings). + */ PRUnichar* mString; + /** ISupports. Strong reference. */ nsISupports* mISupports; + /** Color. */ nscolor mColor; - } mValue; + } mValue; +private: + /** + * Copy into this HTMLValue from aCopy. Please be aware that if this is an + * existing HTMLValue and you do not call Reset(), this will leak. + * @param aCopy the value to copy + */ + void InitializeFrom(const nsHTMLValue& aCopy); + /** + * Helper to set string value (checks for embedded nulls or length); verifies + * that aUnit is a string type as well. + * @param aValue the value to set + * @param aUnit the unit to set + */ + void SetStringValueInternal(const nsAString& aValue, nsHTMLUnit aUnit); + /** + * Get a DependentString from mValue.mString (if the string is stored with + * length, passes that information to the DependentString). Do not call this + * if mValue.mString is null. + * + * @return a DependentString representing this string + */ + nsDependentSingleFragmentSubstring GetDependentString() const; + /** + * Get the unit class (HTMLUNIT_*) + * @return the unit class + */ + PRUint32 GetUnitClass() const { return mUnit & HTMLUNIT_CLASS_MASK; } }; +/** Indicates that a string is stored as an nsCheapStringBuffer */ +#define HTMLSTORAGE_NORMAL 0 +#define HTMLSTORAGE_STRWITHLEN 1 + +inline nsDependentSingleFragmentSubstring nsHTMLValue::GetDependentString() const +{ + NS_ASSERTION(GetUnitClass() == HTMLUNIT_STRING, + "Some dork called GetDependentString() on a non-string!"); + NS_ASSERTION(mValue.mString, "buffer is null! This is bad."); + // If it is stored in string-with-length format, use the length properly + return (mStorageFlags & HTMLSTORAGE_STRWITHLEN) ? + nsCheapStringBufferUtils::GetDependentString(mValue.mString) : + Substring(mValue.mString, + mValue.mString + + nsCharTraits::length(mValue.mString)); +} + inline PRInt32 nsHTMLValue::GetIntValue(void) const { - NS_ASSERTION((mUnit == eHTMLUnit_String) || - (mUnit == eHTMLUnit_Integer) || - (mUnit == eHTMLUnit_Enumerated) || - (mUnit == eHTMLUnit_Proportional), "not an int value"); - if ((mUnit == eHTMLUnit_Integer) || - (mUnit == eHTMLUnit_Enumerated) || - (mUnit == eHTMLUnit_Proportional)) { + NS_ASSERTION(GetUnitClass() == HTMLUNIT_STRING || + GetUnitClass() == HTMLUNIT_INTEGER, + "not an int value"); + PRUint32 unitClass = GetUnitClass(); + if (unitClass == HTMLUNIT_INTEGER) { return mValue.mInt; } - else if (mUnit == eHTMLUnit_String) { + + if (unitClass == HTMLUNIT_STRING) { if (mValue.mString) { PRInt32 err=0; - nsAutoString str(mValue.mString); // XXX copy. new string APIs will make this better, right? + // XXX this copies. new string APIs will make this better, right? + nsAutoString str(GetDependentString()); return str.ToInteger(&err); } } + return 0; } @@ -154,12 +336,12 @@ inline float nsHTMLValue::GetPercentValue(void) const inline nsAString& nsHTMLValue::GetStringValue(nsAString& aBuffer) const { - NS_ASSERTION((mUnit == eHTMLUnit_String) || (mUnit == eHTMLUnit_ColorName) || - (mUnit == eHTMLUnit_Null), "not a string value"); - aBuffer.SetLength(0); - if (((mUnit == eHTMLUnit_String) || (mUnit == eHTMLUnit_ColorName)) && - (nsnull != mValue.mString)) { - aBuffer.Append(mValue.mString); + NS_ASSERTION(GetUnitClass() == HTMLUNIT_STRING || mUnit == eHTMLUnit_Null, + "not a string value"); + if (GetUnitClass() == HTMLUNIT_STRING && mValue.mString) { + aBuffer = GetDependentString(); + } else { + aBuffer.Truncate(); } return aBuffer; } diff --git a/mozilla/content/shared/public/nsHTMLValue.h b/mozilla/content/shared/public/nsHTMLValue.h index 08554bf426b..15bb71572e9 100644 --- a/mozilla/content/shared/public/nsHTMLValue.h +++ b/mozilla/content/shared/public/nsHTMLValue.h @@ -43,20 +43,130 @@ #include "nsString.h" #include "nsISupports.h" -enum nsHTMLUnit { - eHTMLUnit_Null = 0, // (n/a) null unit, value is not specified - eHTMLUnit_Empty = 1, // (n/a) empty unit, value is not specified - eHTMLUnit_String = 10, // (nsString) a string value - eHTMLUnit_ISupports = 20, // (nsISupports*) a ref counted interface - eHTMLUnit_Integer = 50, // (int) simple value - eHTMLUnit_Enumerated = 51, // (int) value has enumerated meaning - eHTMLUnit_Proportional = 52, // (int) value is a relative proportion of some whole - eHTMLUnit_Color = 80, // (color) an RGBA value - eHTMLUnit_ColorName = 81, // (nsString/color) a color name value - eHTMLUnit_Percent = 90, // (float) 1.0 == 100%) value is percentage of something +#include "nsReadableUtils.h" +#include "nsCRT.h" - // Screen relative measure - eHTMLUnit_Pixel = 600 // (int) screen pixels +class nsCheapStringBufferUtils { +public: + /** + * Get the string pointer + * @param aBuf the buffer + * @return a pointer to the string + */ + static const PRUnichar* StrPtr(const PRUnichar* aBuf) { + NS_ASSERTION(aBuf, "Cannot work on null buffer!"); + return (const PRUnichar*)( ((const char*)aBuf) + sizeof(PRUint32) ); + } + static PRUnichar* StrPtr(PRUnichar* aBuf) { + NS_ASSERTION(aBuf, "Cannot work on null buffer!"); + return (PRUnichar*)( ((char*)aBuf) + sizeof(PRUint32) ); + } + /** + * Get the string length + * @param aBuf the buffer + * @return the string length + */ + static PRUint32 Length(const PRUnichar* aBuf) { + NS_ASSERTION(aBuf, "Cannot work on null buffer!"); + return *((PRUint32*)aBuf); + } + /** + * Get a DependentString from a buffer + * + * @param aBuf the buffer to get string from + * @return a DependentString representing this string + */ + static nsDependentSingleFragmentSubstring GetDependentString(const PRUnichar* aBuf) { + NS_ASSERTION(aBuf, "Cannot work on null buffer!"); + const PRUnichar* buf = StrPtr(aBuf); + return Substring(buf, buf + Length(aBuf)); + } + /** + * Construct from an AString + * @param aBuf the buffer to copy to + * @param aStr the string to construct from + * @param aLen the length of the string (passed for efficiency) + */ + static void CopyToBuffer(PRUnichar*& aBuf, const nsAString& aStr, PRUint32 aLen) { + NS_ASSERTION(aStr.Length() == aLen, "Wrong length passed in!"); + aBuf = (PRUnichar*)nsMemory::Alloc(sizeof(PRUint32) + + aLen * sizeof(PRUnichar)); + *((PRUint32*)aBuf) = aLen; + CopyUnicodeTo(aStr, 0, StrPtr(aBuf), aLen); + } + /** + * Construct from another nsCheapStringBuffer + * @param aBuf the buffer to put into + * @param aSrc the buffer to construct from + */ + static void Clone(PRUnichar*& aBuf, const PRUnichar* aSrc) { + NS_ASSERTION(aSrc, "Cannot work on null buffer!"); + aBuf = (PRUnichar*)nsMemory::Clone(aSrc, sizeof(PRUint32) + + Length(aSrc) * sizeof(PRUnichar)); + } + /** + * Free the memory for the buf + * @param aBuf the buffer to free + */ + static void Free(PRUnichar* aBuf) { + NS_ASSERTION(aBuf, "Cannot work on null buffer!"); + nsMemory::Free(aBuf); + } + /** + * Get a hashcode for the buffer + * @param aBuf the buffer + * @return the hashcode + */ + static PRUint32 HashCode(const PRUnichar* aBuf) { + NS_ASSERTION(aBuf, "Cannot work on null buffer!"); + return nsCRT::BufferHashCode((char*)StrPtr(aBuf), + Length(aBuf)*sizeof(PRUnichar)); + } +}; + +// +// nsHTMLUnit is two bytes: the class of type, and a specifier to distinguish +// between different things stored as the same type. Doing +// mUnit & HTMLUNIT_CLASS_MASK should give you the class of type. +// +#define HTMLUNIT_NOSTORE 0x0000 +#define HTMLUNIT_STRING 0x0100 +#define HTMLUNIT_INTEGER 0x0200 +#define HTMLUNIT_PIXEL 0x0400 +#define HTMLUNIT_COLOR 0x0800 +#define HTMLUNIT_ISUPPORTS 0x1000 +#define HTMLUNIT_PERCENT 0x2000 +#define HTMLUNIT_CLASS_MASK 0xff00 + +enum nsHTMLUnit { + // null, value is not specified: 0x0000 + eHTMLUnit_Null = HTMLUNIT_NOSTORE, + // empty, value is not specified: 0x0001 + eHTMLUnit_Empty = HTMLUNIT_NOSTORE | 1, + + // a string value + eHTMLUnit_String = HTMLUNIT_STRING, + // a color name value + eHTMLUnit_ColorName = HTMLUNIT_STRING | 1, + + // a simple int value + eHTMLUnit_Integer = HTMLUNIT_INTEGER, + // value has enumerated meaning + eHTMLUnit_Enumerated = HTMLUNIT_INTEGER | 1, + // value is a relative proportion of some whole + eHTMLUnit_Proportional = HTMLUNIT_INTEGER | 2, + + // screen pixels (screen relative measure) + eHTMLUnit_Pixel = HTMLUNIT_PIXEL, + + // an RGBA value + eHTMLUnit_Color = HTMLUNIT_COLOR, + + // (nsISupports*) a ref counted interface + eHTMLUnit_ISupports = HTMLUNIT_ISUPPORTS, + + // (1.0 == 100%) value is percentage of something + eHTMLUnit_Percent = HTMLUNIT_PERCENT }; /** @@ -81,14 +191,22 @@ public: PRBool operator!=(const nsHTMLValue& aOther) const; PRUint32 HashValue(void) const; - nsHTMLUnit GetUnit(void) const { return mUnit; } - PRInt32 GetIntValue(void) const; - PRInt32 GetPixelValue(void) const; - float GetPercentValue(void) const; - nsAString& GetStringValue(nsAString& aBuffer) const; - nsISupports* GetISupportsValue(void) const; - nscolor GetColorValue(void) const; + /** + * Get the unit of this HTMLValue + * @return the unit of this HTMLValue + */ + nsHTMLUnit GetUnit(void) const { return (nsHTMLUnit)mUnit; } + PRInt32 GetIntValue(void) const; + PRInt32 GetPixelValue(void) const; + float GetPercentValue(void) const; + nsAString& GetStringValue(nsAString& aBuffer) const; + nsISupports* GetISupportsValue(void) const; + nscolor GetColorValue(void) const; + + /** + * Reset the string to null type, freeing things in the process if necessary. + */ void Reset(void); void SetIntValue(PRInt32 aValue, nsHTMLUnit aUnit); void SetPixelValue(PRInt32 aValue); @@ -103,34 +221,98 @@ public: #endif protected: - nsHTMLUnit mUnit; + /** + * The unit of the value + * @see nsHTMLUnit + */ + PRUint16 mUnit; + /** Flags indicating specifics of the storage format (HTMLSTORAGE_*) */ + PRUint16 mStorageFlags; + /** + * The actual value. Please to not be adding more-than-4-byte things to this + * union. + */ union { + /** Int. */ PRInt32 mInt; + /** Float. */ float mFloat; + /** + * String. Depending on mStorageFlags & HTMLSTORAGE_STRWITHLEN, this may be + * stored with the first 4 bytes being the length (this is done for + * embedded nulls and long strings). + */ PRUnichar* mString; + /** ISupports. Strong reference. */ nsISupports* mISupports; + /** Color. */ nscolor mColor; - } mValue; + } mValue; +private: + /** + * Copy into this HTMLValue from aCopy. Please be aware that if this is an + * existing HTMLValue and you do not call Reset(), this will leak. + * @param aCopy the value to copy + */ + void InitializeFrom(const nsHTMLValue& aCopy); + /** + * Helper to set string value (checks for embedded nulls or length); verifies + * that aUnit is a string type as well. + * @param aValue the value to set + * @param aUnit the unit to set + */ + void SetStringValueInternal(const nsAString& aValue, nsHTMLUnit aUnit); + /** + * Get a DependentString from mValue.mString (if the string is stored with + * length, passes that information to the DependentString). Do not call this + * if mValue.mString is null. + * + * @return a DependentString representing this string + */ + nsDependentSingleFragmentSubstring GetDependentString() const; + /** + * Get the unit class (HTMLUNIT_*) + * @return the unit class + */ + PRUint32 GetUnitClass() const { return mUnit & HTMLUNIT_CLASS_MASK; } }; +/** Indicates that a string is stored as an nsCheapStringBuffer */ +#define HTMLSTORAGE_NORMAL 0 +#define HTMLSTORAGE_STRWITHLEN 1 + +inline nsDependentSingleFragmentSubstring nsHTMLValue::GetDependentString() const +{ + NS_ASSERTION(GetUnitClass() == HTMLUNIT_STRING, + "Some dork called GetDependentString() on a non-string!"); + NS_ASSERTION(mValue.mString, "buffer is null! This is bad."); + // If it is stored in string-with-length format, use the length properly + return (mStorageFlags & HTMLSTORAGE_STRWITHLEN) ? + nsCheapStringBufferUtils::GetDependentString(mValue.mString) : + Substring(mValue.mString, + mValue.mString + + nsCharTraits::length(mValue.mString)); +} + inline PRInt32 nsHTMLValue::GetIntValue(void) const { - NS_ASSERTION((mUnit == eHTMLUnit_String) || - (mUnit == eHTMLUnit_Integer) || - (mUnit == eHTMLUnit_Enumerated) || - (mUnit == eHTMLUnit_Proportional), "not an int value"); - if ((mUnit == eHTMLUnit_Integer) || - (mUnit == eHTMLUnit_Enumerated) || - (mUnit == eHTMLUnit_Proportional)) { + NS_ASSERTION(GetUnitClass() == HTMLUNIT_STRING || + GetUnitClass() == HTMLUNIT_INTEGER, + "not an int value"); + PRUint32 unitClass = GetUnitClass(); + if (unitClass == HTMLUNIT_INTEGER) { return mValue.mInt; } - else if (mUnit == eHTMLUnit_String) { + + if (unitClass == HTMLUNIT_STRING) { if (mValue.mString) { PRInt32 err=0; - nsAutoString str(mValue.mString); // XXX copy. new string APIs will make this better, right? + // XXX this copies. new string APIs will make this better, right? + nsAutoString str(GetDependentString()); return str.ToInteger(&err); } } + return 0; } @@ -154,12 +336,12 @@ inline float nsHTMLValue::GetPercentValue(void) const inline nsAString& nsHTMLValue::GetStringValue(nsAString& aBuffer) const { - NS_ASSERTION((mUnit == eHTMLUnit_String) || (mUnit == eHTMLUnit_ColorName) || - (mUnit == eHTMLUnit_Null), "not a string value"); - aBuffer.SetLength(0); - if (((mUnit == eHTMLUnit_String) || (mUnit == eHTMLUnit_ColorName)) && - (nsnull != mValue.mString)) { - aBuffer.Append(mValue.mString); + NS_ASSERTION(GetUnitClass() == HTMLUNIT_STRING || mUnit == eHTMLUnit_Null, + "not a string value"); + if (GetUnitClass() == HTMLUNIT_STRING && mValue.mString) { + aBuffer = GetDependentString(); + } else { + aBuffer.Truncate(); } return aBuffer; } diff --git a/mozilla/content/shared/src/nsHTMLValue.cpp b/mozilla/content/shared/src/nsHTMLValue.cpp index a52ad27af79..ca58c1a48e2 100644 --- a/mozilla/content/shared/src/nsHTMLValue.cpp +++ b/mozilla/content/shared/src/nsHTMLValue.cpp @@ -42,94 +42,60 @@ #include "nsReadableUtils.h" #include "nsUnicharUtils.h" #include "nsCRT.h" +#include "nsMemory.h" nsHTMLValue::nsHTMLValue(nsHTMLUnit aUnit) - : mUnit(aUnit) + : mUnit(aUnit), mStorageFlags(HTMLSTORAGE_NORMAL) { - NS_ASSERTION((aUnit <= eHTMLUnit_Empty), "not a valueless unit"); - if (aUnit > eHTMLUnit_Empty) { + NS_ASSERTION(GetUnitClass() == HTMLUNIT_NOSTORE, "not a valueless unit"); + if (GetUnitClass() != HTMLUNIT_NOSTORE) { mUnit = eHTMLUnit_Null; } mValue.mString = nsnull; } nsHTMLValue::nsHTMLValue(PRInt32 aValue, nsHTMLUnit aUnit) - : mUnit(aUnit) + : mUnit(aUnit), mStorageFlags(HTMLSTORAGE_NORMAL) { - NS_ASSERTION((eHTMLUnit_Integer == aUnit) || - (eHTMLUnit_Enumerated == aUnit) || - (eHTMLUnit_Proportional == aUnit) || - (eHTMLUnit_Pixel == aUnit), "not an integer value"); - if ((eHTMLUnit_Integer == aUnit) || - (eHTMLUnit_Enumerated == aUnit) || - (eHTMLUnit_Proportional == aUnit) || - (eHTMLUnit_Pixel == aUnit)) { + NS_ASSERTION(GetUnitClass() == HTMLUNIT_INTEGER || + GetUnitClass() == HTMLUNIT_PIXEL, "unit not an integer unit"); + if (GetUnitClass() == HTMLUNIT_INTEGER || + GetUnitClass() == HTMLUNIT_PIXEL) { mValue.mInt = aValue; - } - else { + } else { mUnit = eHTMLUnit_Null; - mValue.mInt = 0; + mValue.mString = nsnull; } } nsHTMLValue::nsHTMLValue(float aValue) - : mUnit(eHTMLUnit_Percent) + : mUnit(eHTMLUnit_Percent), mStorageFlags(HTMLSTORAGE_NORMAL) { mValue.mFloat = aValue; } nsHTMLValue::nsHTMLValue(const nsAString& aValue, nsHTMLUnit aUnit) - : mUnit(aUnit) + : mUnit(aUnit), mStorageFlags(HTMLSTORAGE_NORMAL) { - NS_ASSERTION((eHTMLUnit_String == aUnit) || - (eHTMLUnit_ColorName == aUnit), "not a string value"); - if ((eHTMLUnit_String == aUnit) || - (eHTMLUnit_ColorName == aUnit)) { - mValue.mString = ToNewUnicode(aValue); - } - else { - mUnit = eHTMLUnit_Null; - mValue.mInt = 0; - } + SetStringValueInternal(aValue, aUnit); } nsHTMLValue::nsHTMLValue(nsISupports* aValue) - : mUnit(eHTMLUnit_ISupports) + : mUnit(eHTMLUnit_ISupports), mStorageFlags(HTMLSTORAGE_NORMAL) { mValue.mISupports = aValue; NS_IF_ADDREF(mValue.mISupports); } nsHTMLValue::nsHTMLValue(nscolor aValue) - : mUnit(eHTMLUnit_Color) + : mUnit(eHTMLUnit_Color), mStorageFlags(HTMLSTORAGE_NORMAL) { mValue.mColor = aValue; } nsHTMLValue::nsHTMLValue(const nsHTMLValue& aCopy) - : mUnit(aCopy.mUnit) { - if ((eHTMLUnit_String == mUnit) || (eHTMLUnit_ColorName == mUnit)) { - if (nsnull != aCopy.mValue.mString) { - mValue.mString = nsCRT::strdup(aCopy.mValue.mString); - } - else { - mValue.mString = nsnull; - } - } - else if (eHTMLUnit_ISupports == mUnit) { - mValue.mISupports = aCopy.mValue.mISupports; - NS_IF_ADDREF(mValue.mISupports); - } - else if (eHTMLUnit_Color == mUnit){ - mValue.mColor = aCopy.mValue.mColor; - } - else if (eHTMLUnit_Percent == mUnit) { - mValue.mFloat = aCopy.mValue.mFloat; - } - else { - mValue.mInt = aCopy.mValue.mInt; - } + InitializeFrom(aCopy); } nsHTMLValue::~nsHTMLValue(void) @@ -140,79 +106,81 @@ nsHTMLValue::~nsHTMLValue(void) nsHTMLValue& nsHTMLValue::operator=(const nsHTMLValue& aCopy) { Reset(); - mUnit = aCopy.mUnit; - if ((eHTMLUnit_String == mUnit) || (eHTMLUnit_ColorName == mUnit)) { - if (nsnull != aCopy.mValue.mString) { - mValue.mString = nsCRT::strdup(aCopy.mValue.mString); - } - } - else if (eHTMLUnit_ISupports == mUnit) { - mValue.mISupports = aCopy.mValue.mISupports; - NS_IF_ADDREF(mValue.mISupports); - } - else if (eHTMLUnit_Color == mUnit){ - mValue.mColor = aCopy.mValue.mColor; - } - else if (eHTMLUnit_Percent == mUnit) { - mValue.mFloat = aCopy.mValue.mFloat; - } - else { - mValue.mInt = aCopy.mValue.mInt; - } + InitializeFrom(aCopy); return *this; } PRBool nsHTMLValue::operator==(const nsHTMLValue& aOther) const { - if (mUnit == aOther.mUnit) { - if ((eHTMLUnit_String == mUnit) || (eHTMLUnit_ColorName == mUnit)) { - if (nsnull == mValue.mString) { - if (nsnull == aOther.mValue.mString) { - return PR_TRUE; - } - } - else if (nsnull != aOther.mValue.mString) { - return nsDependentString(mValue.mString).Equals(nsDependentString(aOther.mValue.mString), - nsCaseInsensitiveStringComparator()); - } - } - else if (eHTMLUnit_ISupports == mUnit) { - return PRBool(mValue.mISupports == aOther.mValue.mISupports); - } - else if (eHTMLUnit_Color == mUnit){ - return PRBool(mValue.mColor == aOther.mValue.mColor); - } - else if (eHTMLUnit_Percent == mUnit) { - return PRBool(mValue.mFloat == aOther.mValue.mFloat); - } - else { - return PRBool(mValue.mInt == aOther.mValue.mInt); - } + if (mUnit != aOther.mUnit) { + return PR_FALSE; + } + // Call GetUnit() so that we turn StringWithLength into String + PRUint32 unitClass = GetUnitClass(); + switch (unitClass) { + case HTMLUNIT_NOSTORE: + return PR_TRUE; + + case HTMLUNIT_STRING: + if (mValue.mString && aOther.mValue.mString) { + return GetDependentString().Equals(aOther.GetDependentString(), + nsCaseInsensitiveStringComparator()); + } + // One of them is null. An == check will see if they are both null. + return mValue.mString == aOther.mValue.mString; + + case HTMLUNIT_INTEGER: + case HTMLUNIT_PIXEL: + return mValue.mInt == aOther.mValue.mInt; + + case HTMLUNIT_COLOR: + return mValue.mColor == aOther.mValue.mColor; + + case HTMLUNIT_ISUPPORTS: + return mValue.mISupports == aOther.mValue.mISupports; + + case HTMLUNIT_PERCENT: + return mValue.mFloat == aOther.mValue.mFloat; + + default: + NS_WARNING("Unknown unit"); + return PR_TRUE; } - return PR_FALSE; } PRUint32 nsHTMLValue::HashValue(void) const { - return PRUint32(mUnit) ^ - ((((eHTMLUnit_String == mUnit) || (eHTMLUnit_ColorName == mUnit)) && - (nsnull != mValue.mString)) ? - nsCRT::HashCode(mValue.mString) : - mValue.mInt); + PRUint32 retval; + if (GetUnitClass() == HTMLUNIT_STRING) { + if (mStorageFlags & HTMLSTORAGE_STRWITHLEN) { + retval = mValue.mString ? nsCheapStringBufferUtils::HashCode(mValue.mString) + : 0; + } else { + retval = mValue.mString ? nsCRT::HashCode(mValue.mString) : 0; + } + } else { + retval = mValue.mInt; + } + return retval ^ PRUint32(mUnit); } void nsHTMLValue::Reset(void) { - if ((eHTMLUnit_String == mUnit) || (eHTMLUnit_ColorName == mUnit)) { - if (nsnull != mValue.mString) { - nsCRT::free(mValue.mString); + if (GetUnitClass() == HTMLUNIT_STRING) { + if (mValue.mString) { + if (mStorageFlags & HTMLSTORAGE_STRWITHLEN) { + nsCheapStringBufferUtils::Free(mValue.mString); + } else { + nsMemory::Free(mValue.mString); + } } } - else if (eHTMLUnit_ISupports == mUnit) { + else if (mUnit == eHTMLUnit_ISupports) { NS_IF_RELEASE(mValue.mISupports); } mUnit = eHTMLUnit_Null; + mStorageFlags = 0; mValue.mString = nsnull; } @@ -220,14 +188,12 @@ void nsHTMLValue::Reset(void) void nsHTMLValue::SetIntValue(PRInt32 aValue, nsHTMLUnit aUnit) { Reset(); - NS_ASSERTION((eHTMLUnit_Integer == aUnit) || - (eHTMLUnit_Enumerated == aUnit) || - (eHTMLUnit_Proportional == aUnit), "not an int value"); - if ((eHTMLUnit_Integer == aUnit) || - (eHTMLUnit_Enumerated == aUnit) || - (eHTMLUnit_Proportional == aUnit)) { - mUnit = aUnit; + mUnit = aUnit; + NS_ASSERTION(GetUnitClass() == HTMLUNIT_INTEGER, "not an int value"); + if (GetUnitClass() == HTMLUNIT_INTEGER) { mValue.mInt = aValue; + } else { + mUnit = eHTMLUnit_Null; } } @@ -245,14 +211,50 @@ void nsHTMLValue::SetPercentValue(float aValue) mValue.mFloat = aValue; } +static inline PRBool +ShouldStoreLength(const nsAString& aStr, PRUint32 aLen) +{ + // Always remember the length of the string if the length is greater than 30 + if (aLen > 30) { + return PR_TRUE; + } + // Obviously never remember the length of the string if it is empty :) + if (aLen == 0) { + return PR_FALSE; + } + // Remember the length of the string if it has embedded nulls + nsAString::const_iterator begin, end; + return FindCharInReadable('\0', aStr.BeginReading(begin), + aStr.EndReading(end)); +} + +void nsHTMLValue::SetStringValueInternal(const nsAString& aValue, + nsHTMLUnit aUnit) +{ + NS_ASSERTION(GetUnitClass() == HTMLUNIT_STRING, "unit not a string unit!"); + if (GetUnitClass() == HTMLUNIT_STRING) { + // Remember the length of the string if necessary + PRUint32 len = aValue.Length(); + if (ShouldStoreLength(aValue, len)) { + mStorageFlags = HTMLSTORAGE_STRWITHLEN; + nsCheapStringBufferUtils::CopyToBuffer(mValue.mString, aValue, len); + return; + } + + // Else just store as a normal string + mValue.mString = ToNewUnicode(aValue); + } else { + mUnit = eHTMLUnit_Null; + mValue.mString = nsnull; + } +} + void nsHTMLValue::SetStringValue(const nsAString& aValue, nsHTMLUnit aUnit) { Reset(); - if ((eHTMLUnit_String == aUnit) || (eHTMLUnit_ColorName == aUnit)) { - mUnit = aUnit; - mValue.mString = ToNewUnicode(aValue); - } + mUnit = aUnit; + SetStringValueInternal(aValue, aUnit); } void nsHTMLValue::SetISupportsValue(nsISupports* aValue) @@ -279,64 +281,72 @@ void nsHTMLValue::SetEmptyValue(void) #ifdef DEBUG void nsHTMLValue::AppendToString(nsAString& aBuffer) const { - if (eHTMLUnit_Null == mUnit) { - return; - } - - if (eHTMLUnit_Empty == mUnit) { - } - else if ((eHTMLUnit_String == mUnit) || (eHTMLUnit_ColorName == mUnit)) { - if (nsnull != mValue.mString) { + switch (GetUnitClass()) { + case HTMLUNIT_NOSTORE: + break; + case HTMLUNIT_STRING: + if (mValue.mString) { aBuffer.Append(PRUnichar('"')); - aBuffer.Append(mValue.mString); + aBuffer.Append(GetDependentString()); aBuffer.Append(PRUnichar('"')); - } - else { + } else { aBuffer.Append(NS_LITERAL_STRING("null str")); } - } - else if (eHTMLUnit_ISupports == mUnit) { - aBuffer.Append(NS_LITERAL_STRING("0x")); - nsAutoString intStr; - intStr.AppendInt(NS_PTR_TO_INT32(mValue.mISupports), 16); - aBuffer.Append(intStr); - } - else if (eHTMLUnit_Color == mUnit){ - nsAutoString intStr; - intStr.Append(NS_LITERAL_STRING("(0x")); - intStr.AppendInt(NS_GET_R(mValue.mColor), 16); - intStr.Append(NS_LITERAL_STRING(" 0x")); - intStr.AppendInt(NS_GET_G(mValue.mColor), 16); - intStr.Append(NS_LITERAL_STRING(" 0x")); - intStr.AppendInt(NS_GET_B(mValue.mColor), 16); - intStr.Append(NS_LITERAL_STRING(" 0x")); - intStr.AppendInt(NS_GET_A(mValue.mColor), 16); - intStr.Append(PRUnichar(')')); + break; + case HTMLUNIT_INTEGER: + case HTMLUNIT_PIXEL: + { + nsAutoString intStr; + intStr.AppendInt(mValue.mInt, 10); + intStr.Append(NS_LITERAL_STRING("[0x")); + intStr.AppendInt(mValue.mInt, 16); + intStr.Append(PRUnichar(']')); - aBuffer.Append(intStr); - } - else if (eHTMLUnit_Percent == mUnit) { - nsAutoString floatStr; - floatStr.AppendFloat(mValue.mFloat * 100.0f); - aBuffer.Append(floatStr); - } - else { - nsAutoString intStr; - intStr.AppendInt(mValue.mInt, 10); - intStr.Append(NS_LITERAL_STRING("[0x")); - intStr.AppendInt(mValue.mInt, 16); - intStr.Append(PRUnichar(']')); + aBuffer.Append(intStr); + } + break; + case HTMLUNIT_COLOR: + { + nsAutoString intStr; + intStr.Append(NS_LITERAL_STRING("(0x")); + intStr.AppendInt(NS_GET_R(mValue.mColor), 16); + intStr.Append(NS_LITERAL_STRING(" 0x")); + intStr.AppendInt(NS_GET_G(mValue.mColor), 16); + intStr.Append(NS_LITERAL_STRING(" 0x")); + intStr.AppendInt(NS_GET_B(mValue.mColor), 16); + intStr.Append(NS_LITERAL_STRING(" 0x")); + intStr.AppendInt(NS_GET_A(mValue.mColor), 16); + intStr.Append(PRUnichar(')')); - aBuffer.Append(intStr); + aBuffer.Append(intStr); + } + break; + case HTMLUNIT_ISUPPORTS: + { + aBuffer.Append(NS_LITERAL_STRING("0x")); + nsAutoString intStr; + intStr.AppendInt(NS_PTR_TO_INT32(mValue.mISupports), 16); + aBuffer.Append(intStr); + } + break; + case HTMLUNIT_PERCENT: + { + nsAutoString floatStr; + floatStr.AppendFloat(mValue.mFloat * 100.0f); + aBuffer.Append(floatStr); + } + break; + default: + NS_ERROR("Unknown HTMLValue type!"); } + // + // Append the type name for types that are ambiguous + // switch (mUnit) { - case eHTMLUnit_Null: break; - case eHTMLUnit_Empty: break; - case eHTMLUnit_String: break; - case eHTMLUnit_ColorName: break; + case eHTMLUnit_Null: aBuffer.Append(NS_LITERAL_STRING("null")); break; + case eHTMLUnit_Empty: aBuffer.Append(NS_LITERAL_STRING("empty")); break; case eHTMLUnit_ISupports: aBuffer.Append(NS_LITERAL_STRING("ptr")); break; - case eHTMLUnit_Integer: break; case eHTMLUnit_Enumerated: aBuffer.Append(NS_LITERAL_STRING("enum")); break; case eHTMLUnit_Proportional: aBuffer.Append(NS_LITERAL_STRING("*")); break; case eHTMLUnit_Color: aBuffer.Append(NS_LITERAL_STRING("rbga")); break; @@ -346,3 +356,49 @@ void nsHTMLValue::AppendToString(nsAString& aBuffer) const aBuffer.Append(PRUnichar(' ')); } #endif // DEBUG + +void +nsHTMLValue::InitializeFrom(const nsHTMLValue& aCopy) +{ + mUnit = aCopy.mUnit; + mStorageFlags = aCopy.mStorageFlags; + switch (GetUnitClass()) { + case HTMLUNIT_NOSTORE: + mValue.mString = nsnull; + break; + + case HTMLUNIT_STRING: + if (aCopy.mValue.mString) { + if (aCopy.mStorageFlags & HTMLSTORAGE_STRWITHLEN) { + // Clone the string = (PRUint32) + PRUnichar*len + nsCheapStringBufferUtils::Clone(mValue.mString, aCopy.mValue.mString); + } else { + mValue.mString = ToNewUnicode(nsDependentString(aCopy.mValue.mString)); + } + } else { + mValue.mString = nsnull; + } + break; + + case HTMLUNIT_INTEGER: + case HTMLUNIT_PIXEL: + mValue.mInt = aCopy.mValue.mInt; + break; + + case HTMLUNIT_COLOR: + mValue.mColor = aCopy.mValue.mColor; + break; + + case HTMLUNIT_ISUPPORTS: + mValue.mISupports = aCopy.mValue.mISupports; + NS_IF_ADDREF(mValue.mISupports); + break; + + case HTMLUNIT_PERCENT: + mValue.mFloat = aCopy.mValue.mFloat; + break; + + default: + NS_ERROR("Unknown HTMLValue type!"); + } +} diff --git a/mozilla/layout/base/nsCSSFrameConstructor.cpp b/mozilla/layout/base/nsCSSFrameConstructor.cpp index 5f3ad8f0d47..c2d83239926 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/base/nsCSSFrameConstructor.cpp @@ -1649,39 +1649,47 @@ nsCSSFrameConstructor::CreateInputFrame(nsIPresShell *aPresShell, nsIFrame *&aFrame, nsIStyleContext *aStyleContext) { - // Figure out which type of input frame to create - nsAutoString val; - if (NS_OK == aContent->GetAttr(kNameSpaceID_None, nsHTMLAtoms::type, val)) { - if (val.EqualsIgnoreCase("submit") || - val.EqualsIgnoreCase("reset") || - val.EqualsIgnoreCase("button")) { + nsCOMPtr control = do_QueryInterface(aContent); + NS_ASSERTION(control, "input is not an nsIFormControl!"); + + PRInt32 type; + control->GetType(&type); + switch (type) { + case NS_FORM_INPUT_SUBMIT: + case NS_FORM_INPUT_RESET: + case NS_FORM_INPUT_BUTTON: if (UseXBLForms()) return NS_OK; return ConstructButtonControlFrame(aPresShell, aPresContext, aFrame); - } - else if (val.EqualsIgnoreCase("checkbox")) { + + case NS_FORM_INPUT_CHECKBOX: if (UseXBLForms()) return NS_OK; return ConstructCheckboxControlFrame(aPresShell, aPresContext, aFrame, aContent, aStyleContext); - } - else if (val.EqualsIgnoreCase("file")) { - return NS_NewFileControlFrame(aPresShell, &aFrame); - } - else if (val.EqualsIgnoreCase("hidden")) { - return NS_OK; - } - else if (val.EqualsIgnoreCase("image")) { - return NS_NewImageControlFrame(aPresShell, &aFrame); - } - else if (val.EqualsIgnoreCase("radio")) { + + case NS_FORM_INPUT_RADIO: if (UseXBLForms()) return NS_OK; return ConstructRadioControlFrame(aPresShell, aPresContext, aFrame, aContent, aStyleContext); - } - } - // "password", "text", and all others - return ConstructTextControlFrame(aPresShell, aPresContext, aFrame, aContent); + case NS_FORM_INPUT_FILE: + return NS_NewFileControlFrame(aPresShell, &aFrame); + + case NS_FORM_INPUT_HIDDEN: + return NS_OK; + + case NS_FORM_INPUT_IMAGE: + return NS_NewImageControlFrame(aPresShell, &aFrame); + + case NS_FORM_INPUT_TEXT: + case NS_FORM_INPUT_PASSWORD: + return ConstructTextControlFrame(aPresShell, aPresContext, + aFrame, aContent); + + default: + NS_ASSERTION(0, "Unknown input type!"); + return NS_ERROR_INVALID_ARG; + } } static PRBool diff --git a/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp b/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp index 5f3ad8f0d47..c2d83239926 100644 --- a/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp @@ -1649,39 +1649,47 @@ nsCSSFrameConstructor::CreateInputFrame(nsIPresShell *aPresShell, nsIFrame *&aFrame, nsIStyleContext *aStyleContext) { - // Figure out which type of input frame to create - nsAutoString val; - if (NS_OK == aContent->GetAttr(kNameSpaceID_None, nsHTMLAtoms::type, val)) { - if (val.EqualsIgnoreCase("submit") || - val.EqualsIgnoreCase("reset") || - val.EqualsIgnoreCase("button")) { + nsCOMPtr control = do_QueryInterface(aContent); + NS_ASSERTION(control, "input is not an nsIFormControl!"); + + PRInt32 type; + control->GetType(&type); + switch (type) { + case NS_FORM_INPUT_SUBMIT: + case NS_FORM_INPUT_RESET: + case NS_FORM_INPUT_BUTTON: if (UseXBLForms()) return NS_OK; return ConstructButtonControlFrame(aPresShell, aPresContext, aFrame); - } - else if (val.EqualsIgnoreCase("checkbox")) { + + case NS_FORM_INPUT_CHECKBOX: if (UseXBLForms()) return NS_OK; return ConstructCheckboxControlFrame(aPresShell, aPresContext, aFrame, aContent, aStyleContext); - } - else if (val.EqualsIgnoreCase("file")) { - return NS_NewFileControlFrame(aPresShell, &aFrame); - } - else if (val.EqualsIgnoreCase("hidden")) { - return NS_OK; - } - else if (val.EqualsIgnoreCase("image")) { - return NS_NewImageControlFrame(aPresShell, &aFrame); - } - else if (val.EqualsIgnoreCase("radio")) { + + case NS_FORM_INPUT_RADIO: if (UseXBLForms()) return NS_OK; return ConstructRadioControlFrame(aPresShell, aPresContext, aFrame, aContent, aStyleContext); - } - } - // "password", "text", and all others - return ConstructTextControlFrame(aPresShell, aPresContext, aFrame, aContent); + case NS_FORM_INPUT_FILE: + return NS_NewFileControlFrame(aPresShell, &aFrame); + + case NS_FORM_INPUT_HIDDEN: + return NS_OK; + + case NS_FORM_INPUT_IMAGE: + return NS_NewImageControlFrame(aPresShell, &aFrame); + + case NS_FORM_INPUT_TEXT: + case NS_FORM_INPUT_PASSWORD: + return ConstructTextControlFrame(aPresShell, aPresContext, + aFrame, aContent); + + default: + NS_ASSERTION(0, "Unknown input type!"); + return NS_ERROR_INVALID_ARG; + } } static PRBool