From c5b034aaaea96267bbb4a0f93c034b99c22016a3 Mon Sep 17 00:00:00 2001 From: "jkeiser%netscape.com" Date: Thu, 26 Sep 2002 07:41:53 +0000 Subject: [PATCH] Make nsHTMLValue store embedded nulls (r=sicking@netscape.com, sr=bzbarsky@mit.edu, sr=jaggernaut@netscape.com git-svn-id: svn://10.0.0.236/trunk@130511 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/content/base/src/nsHTMLValue.cpp | 362 ++++++++++-------- mozilla/content/base/src/nsHTMLValue.h | 246 ++++++++++-- mozilla/content/shared/public/nsHTMLValue.h | 246 ++++++++++-- mozilla/content/shared/src/nsHTMLValue.cpp | 362 ++++++++++-------- mozilla/layout/base/nsCSSFrameConstructor.cpp | 54 +-- .../html/style/src/nsCSSFrameConstructor.cpp | 54 +-- mozilla/xpcom/ds/nsCRT.cpp | 11 + mozilla/xpcom/ds/nsCRT.h | 3 + 8 files changed, 884 insertions(+), 454 deletions(-) diff --git a/mozilla/content/base/src/nsHTMLValue.cpp b/mozilla/content/base/src/nsHTMLValue.cpp index a52ad27af79..1071667d728 100644 --- a/mozilla/content/base/src/nsHTMLValue.cpp +++ b/mozilla/content/base/src/nsHTMLValue.cpp @@ -42,12 +42,13 @@ #include "nsReadableUtils.h" #include "nsUnicharUtils.h" #include "nsCRT.h" +#include "nsMemory.h" nsHTMLValue::nsHTMLValue(nsHTMLUnit aUnit) : mUnit(aUnit) { - 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; @@ -56,19 +57,14 @@ nsHTMLValue::nsHTMLValue(nsHTMLUnit aUnit) nsHTMLValue::nsHTMLValue(PRInt32 aValue, nsHTMLUnit aUnit) : mUnit(aUnit) { - 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; } } @@ -81,16 +77,7 @@ nsHTMLValue::nsHTMLValue(float aValue) nsHTMLValue::nsHTMLValue(const nsAString& aValue, nsHTMLUnit aUnit) : mUnit(aUnit) { - 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) @@ -107,29 +94,8 @@ nsHTMLValue::nsHTMLValue(nscolor 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,76 +106,69 @@ 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 GetUnitClass() 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) { + retval = mValue.mString ? nsCheapStringBufferUtils::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) { + nsCheapStringBufferUtils::Free(mValue.mString); } } - else if (eHTMLUnit_ISupports == mUnit) { + else if (mUnit == eHTMLUnit_ISupports) { NS_IF_RELEASE(mValue.mISupports); } mUnit = eHTMLUnit_Null; @@ -220,14 +179,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 +202,29 @@ void nsHTMLValue::SetPercentValue(float aValue) mValue.mFloat = aValue; } +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 + if (aValue.IsEmpty()) { + mValue.mString = nsnull; + } else { + nsCheapStringBufferUtils::CopyToBuffer(mValue.mString, 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,70 +251,130 @@ 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: aBuffer.Append(PRUnichar('"')); - aBuffer.Append(mValue.mString); + aBuffer.Append(GetDependentString()); aBuffer.Append(PRUnichar('"')); - } - 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_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; - case eHTMLUnit_Percent: aBuffer.Append(NS_LITERAL_STRING("%")); break; - case eHTMLUnit_Pixel: aBuffer.Append(NS_LITERAL_STRING("px")); 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_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; + case eHTMLUnit_Percent: + aBuffer.Append(NS_LITERAL_STRING("%")); + break; + case eHTMLUnit_Pixel: + aBuffer.Append(NS_LITERAL_STRING("px")); + break; } aBuffer.Append(PRUnichar(' ')); } #endif // DEBUG + +void +nsHTMLValue::InitializeFrom(const nsHTMLValue& aCopy) +{ + mUnit = aCopy.mUnit; + switch (GetUnitClass()) { + case HTMLUNIT_NOSTORE: + mValue.mString = nsnull; + break; + + case HTMLUNIT_STRING: + if (aCopy.mValue.mString) { + nsCheapStringBufferUtils::Clone(mValue.mString, 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..749b2d7f346 100644 --- a/mozilla/content/base/src/nsHTMLValue.h +++ b/mozilla/content/base/src/nsHTMLValue.h @@ -43,20 +43,129 @@ #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 + */ + static void CopyToBuffer(PRUnichar*& aBuf, const nsAString& aStr) { + PRUint32 len = aStr.Length(); + aBuf = (PRUnichar*)nsMemory::Alloc(sizeof(PRUint32) + + len * sizeof(PRUnichar)); + *((PRUint32*)aBuf) = len; + CopyUnicodeTo(aStr, 0, StrPtr(aBuf), len); + } + /** + * 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 +190,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 +220,85 @@ public: #endif protected: - nsHTMLUnit mUnit; + /** + * The unit of the value + * @see nsHTMLUnit + */ + PRUint32 mUnit; + /** + * The actual value. Please to not be adding more-than-4-byte things to this + * union. + */ union { + /** Int. */ PRInt32 mInt; + /** Float. */ float mFloat; + /** String. First 4 bytes are the length, non-null-terminated. */ 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; } }; +inline nsDependentSingleFragmentSubstring nsHTMLValue::GetDependentString() const +{ + NS_ASSERTION(GetUnitClass() == HTMLUNIT_STRING, + "Some dork called GetDependentString() on a non-string!"); + static const PRUnichar blankStr[] = { '\0' }; + return mValue.mString + ? nsCheapStringBufferUtils::GetDependentString(mValue.mString) + : Substring(blankStr, blankStr); +} + 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 +322,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; } @@ -182,9 +350,9 @@ inline nscolor nsHTMLValue::GetColorValue(void) const if (mUnit == eHTMLUnit_Color) { return mValue.mColor; } - if ((mUnit == eHTMLUnit_ColorName) && (mValue.mString)) { + if (mUnit == eHTMLUnit_ColorName) { nscolor color; - if (NS_ColorNameToRGB(nsAutoString(mValue.mString), &color)) { + if (NS_ColorNameToRGB(GetDependentString(), &color)) { return color; } } diff --git a/mozilla/content/shared/public/nsHTMLValue.h b/mozilla/content/shared/public/nsHTMLValue.h index 08554bf426b..749b2d7f346 100644 --- a/mozilla/content/shared/public/nsHTMLValue.h +++ b/mozilla/content/shared/public/nsHTMLValue.h @@ -43,20 +43,129 @@ #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 + */ + static void CopyToBuffer(PRUnichar*& aBuf, const nsAString& aStr) { + PRUint32 len = aStr.Length(); + aBuf = (PRUnichar*)nsMemory::Alloc(sizeof(PRUint32) + + len * sizeof(PRUnichar)); + *((PRUint32*)aBuf) = len; + CopyUnicodeTo(aStr, 0, StrPtr(aBuf), len); + } + /** + * 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 +190,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 +220,85 @@ public: #endif protected: - nsHTMLUnit mUnit; + /** + * The unit of the value + * @see nsHTMLUnit + */ + PRUint32 mUnit; + /** + * The actual value. Please to not be adding more-than-4-byte things to this + * union. + */ union { + /** Int. */ PRInt32 mInt; + /** Float. */ float mFloat; + /** String. First 4 bytes are the length, non-null-terminated. */ 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; } }; +inline nsDependentSingleFragmentSubstring nsHTMLValue::GetDependentString() const +{ + NS_ASSERTION(GetUnitClass() == HTMLUNIT_STRING, + "Some dork called GetDependentString() on a non-string!"); + static const PRUnichar blankStr[] = { '\0' }; + return mValue.mString + ? nsCheapStringBufferUtils::GetDependentString(mValue.mString) + : Substring(blankStr, blankStr); +} + 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 +322,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; } @@ -182,9 +350,9 @@ inline nscolor nsHTMLValue::GetColorValue(void) const if (mUnit == eHTMLUnit_Color) { return mValue.mColor; } - if ((mUnit == eHTMLUnit_ColorName) && (mValue.mString)) { + if (mUnit == eHTMLUnit_ColorName) { nscolor color; - if (NS_ColorNameToRGB(nsAutoString(mValue.mString), &color)) { + if (NS_ColorNameToRGB(GetDependentString(), &color)) { return color; } } diff --git a/mozilla/content/shared/src/nsHTMLValue.cpp b/mozilla/content/shared/src/nsHTMLValue.cpp index a52ad27af79..1071667d728 100644 --- a/mozilla/content/shared/src/nsHTMLValue.cpp +++ b/mozilla/content/shared/src/nsHTMLValue.cpp @@ -42,12 +42,13 @@ #include "nsReadableUtils.h" #include "nsUnicharUtils.h" #include "nsCRT.h" +#include "nsMemory.h" nsHTMLValue::nsHTMLValue(nsHTMLUnit aUnit) : mUnit(aUnit) { - 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; @@ -56,19 +57,14 @@ nsHTMLValue::nsHTMLValue(nsHTMLUnit aUnit) nsHTMLValue::nsHTMLValue(PRInt32 aValue, nsHTMLUnit aUnit) : mUnit(aUnit) { - 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; } } @@ -81,16 +77,7 @@ nsHTMLValue::nsHTMLValue(float aValue) nsHTMLValue::nsHTMLValue(const nsAString& aValue, nsHTMLUnit aUnit) : mUnit(aUnit) { - 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) @@ -107,29 +94,8 @@ nsHTMLValue::nsHTMLValue(nscolor 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,76 +106,69 @@ 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 GetUnitClass() 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) { + retval = mValue.mString ? nsCheapStringBufferUtils::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) { + nsCheapStringBufferUtils::Free(mValue.mString); } } - else if (eHTMLUnit_ISupports == mUnit) { + else if (mUnit == eHTMLUnit_ISupports) { NS_IF_RELEASE(mValue.mISupports); } mUnit = eHTMLUnit_Null; @@ -220,14 +179,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 +202,29 @@ void nsHTMLValue::SetPercentValue(float aValue) mValue.mFloat = aValue; } +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 + if (aValue.IsEmpty()) { + mValue.mString = nsnull; + } else { + nsCheapStringBufferUtils::CopyToBuffer(mValue.mString, 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,70 +251,130 @@ 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: aBuffer.Append(PRUnichar('"')); - aBuffer.Append(mValue.mString); + aBuffer.Append(GetDependentString()); aBuffer.Append(PRUnichar('"')); - } - 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_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; - case eHTMLUnit_Percent: aBuffer.Append(NS_LITERAL_STRING("%")); break; - case eHTMLUnit_Pixel: aBuffer.Append(NS_LITERAL_STRING("px")); 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_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; + case eHTMLUnit_Percent: + aBuffer.Append(NS_LITERAL_STRING("%")); + break; + case eHTMLUnit_Pixel: + aBuffer.Append(NS_LITERAL_STRING("px")); + break; } aBuffer.Append(PRUnichar(' ')); } #endif // DEBUG + +void +nsHTMLValue::InitializeFrom(const nsHTMLValue& aCopy) +{ + mUnit = aCopy.mUnit; + switch (GetUnitClass()) { + case HTMLUNIT_NOSTORE: + mValue.mString = nsnull; + break; + + case HTMLUNIT_STRING: + if (aCopy.mValue.mString) { + nsCheapStringBufferUtils::Clone(mValue.mString, 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 d6d19a01ef5..daf722903ca 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 d6d19a01ef5..daf722903ca 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 diff --git a/mozilla/xpcom/ds/nsCRT.cpp b/mozilla/xpcom/ds/nsCRT.cpp index d5acef0d532..bb1c400bb97 100644 --- a/mozilla/xpcom/ds/nsCRT.cpp +++ b/mozilla/xpcom/ds/nsCRT.cpp @@ -399,6 +399,17 @@ PRUint32 nsCRT::BufferHashCode(const char* s, PRUint32 len) return h; } +PRUint32 nsCRT::BufferHashCode(const PRUnichar* s, PRUint32 len) +{ + PRUint32 h = 0; + const PRUnichar* done = s + len; + + while ( s < done ) + h = (h>>28) ^ (h<<4) ^ PRUint16(*s++); // cast to unsigned to prevent possible sign extension + + return h; +} + // This should use NSPR but NSPR isn't exporting its PR_strtoll function // Until then... PRInt64 nsCRT::atoll(const char *str) diff --git a/mozilla/xpcom/ds/nsCRT.h b/mozilla/xpcom/ds/nsCRT.h index bcd8d6ae497..ce9d69da54b 100644 --- a/mozilla/xpcom/ds/nsCRT.h +++ b/mozilla/xpcom/ds/nsCRT.h @@ -238,6 +238,9 @@ public: // Computes the hashcode for a buffer with a specified length. static PRUint32 BufferHashCode(const char* str, PRUint32 strLen); + // Computes the hashcode for a buffer with a specified length. + static PRUint32 BufferHashCode(const PRUnichar* str, PRUint32 strLen); + // String to longlong static PRInt64 atoll(const char *str);