diff --git a/accessible/src/base/nsAccessible.cpp b/accessible/src/base/nsAccessible.cpp index 87d6c72f5334..d4b26cfab1be 100644 --- a/accessible/src/base/nsAccessible.cpp +++ b/accessible/src/base/nsAccessible.cpp @@ -1491,9 +1491,8 @@ nsAccessible::GetAttributes(nsIPersistentProperties **aAttributes) const nsAttrName *attr = content->GetAttrNameAt(count); if (attr && attr->NamespaceEquals(kNameSpaceID_None)) { nsIAtom *attrAtom = attr->Atom(); - const char *attrStr; - attrAtom->GetUTF8String(&attrStr); - if (PL_strncmp(attrStr, "aria-", 5)) + nsDependentAtomString attrStr(attrAtom); + if (!StringBeginsWith(attrStr, NS_LITERAL_STRING("aria-"))) continue; // Not ARIA PRUint8 attrFlags = nsAccUtils::GetAttributeCharacteristics(attrAtom); if (attrFlags & ATTR_BYPASSOBJ) @@ -1503,7 +1502,7 @@ nsAccessible::GetAttributes(nsIPersistentProperties **aAttributes) continue; // only expose token based attributes if they are defined nsAutoString value; if (content->GetAttr(kNameSpaceID_None, attrAtom, value)) { - attributes->SetStringProperty(nsDependentCString(attrStr + 5), value, oldValueUnused); + attributes->SetStringProperty(NS_ConvertUTF16toUTF8(Substring(attrStr, 5)), value, oldValueUnused); } } } diff --git a/accessible/src/base/nsDocAccessible.cpp b/accessible/src/base/nsDocAccessible.cpp index 936877f93b17..a31601f7bd0f 100644 --- a/accessible/src/base/nsDocAccessible.cpp +++ b/accessible/src/base/nsDocAccessible.cpp @@ -1112,9 +1112,8 @@ nsDocAccessible::AttributeChangedImpl(nsIContent* aContent, PRInt32 aNameSpaceID // Check for namespaced ARIA attribute if (aNameSpaceID == kNameSpaceID_None) { // Check for hyphenated aria-foo property? - const char* attributeName; - aAttribute->GetUTF8String(&attributeName); - if (!PL_strncmp("aria-", attributeName, 5)) { + if (StringBeginsWith(nsDependentAtomString(aAttribute), + NS_LITERAL_STRING("aria-"))) { ARIAAttributeChanged(aContent, aAttribute); } } diff --git a/accessible/src/msaa/nsAccessNodeWrap.cpp b/accessible/src/msaa/nsAccessNodeWrap.cpp index 945081da9dee..fbc1399301ef 100644 --- a/accessible/src/msaa/nsAccessNodeWrap.cpp +++ b/accessible/src/msaa/nsAccessNodeWrap.cpp @@ -249,12 +249,10 @@ __try{ for (PRUint32 index = 0; index < numAttribs; index++) { aNameSpaceIDs[index] = 0; aAttribValues[index] = aAttribNames[index] = nsnull; nsAutoString attributeValue; - const char *pszAttributeName; const nsAttrName* name = content->GetAttrNameAt(index); aNameSpaceIDs[index] = static_cast(name->NamespaceID()); - name->LocalName()->GetUTF8String(&pszAttributeName); - aAttribNames[index] = ::SysAllocString(NS_ConvertUTF8toUTF16(pszAttributeName).get()); + aAttribNames[index] = ::SysAllocString(name->LocalName()->GetUTF16String()); content->GetAttr(name->NamespaceID(), name->LocalName(), attributeValue); aAttribValues[index] = ::SysAllocString(attributeValue.get()); } diff --git a/content/base/public/nsContentUtils.h b/content/base/public/nsContentUtils.h index 0078a392dd4e..ab5e7fb99db5 100644 --- a/content/base/public/nsContentUtils.h +++ b/content/base/public/nsContentUtils.h @@ -1455,6 +1455,13 @@ public: static JSContext *GetCurrentJSContext(); + /** + * Case insensitive comparison between two strings. However it only ignores + * case for ASCII characters a-z. + */ + static PRBool EqualsIgnoreASCIICase(const nsAString& aStr1, + const nsAString& aStr2); + /** * Convert ASCII A-Z to a-z. */ diff --git a/content/base/public/nsINodeInfo.h b/content/base/public/nsINodeInfo.h index d5da6183e608..b1e1ac51be87 100644 --- a/content/base/public/nsINodeInfo.h +++ b/content/base/public/nsINodeInfo.h @@ -270,9 +270,7 @@ public: if (!GetPrefixAtom()) return Equals(aNameAtom); - const char* utf8; - aNameAtom->GetUTF8String(&utf8); - return QualifiedNameEqualsInternal(nsDependentCString(utf8)); + return QualifiedNameEqualsInternal(nsAtomCString(aNameAtom)); } PRBool QualifiedNameEquals(const nsACString& aQualifiedName) const diff --git a/content/base/src/nsAttrValue.cpp b/content/base/src/nsAttrValue.cpp index 6e43f0093b74..ef298e5e9c98 100644 --- a/content/base/src/nsAttrValue.cpp +++ b/content/base/src/nsAttrValue.cpp @@ -510,7 +510,7 @@ nsAttrValue::HashValue() const nsStringBuffer* str = static_cast(GetPtr()); if (str) { PRUint32 len = str->StorageSize()/sizeof(PRUnichar) - 1; - return nsCRT::BufferHashCode(static_cast(str->Data()), len); + return nsCRT::HashCode(static_cast(str->Data()), len); } return 0; @@ -776,11 +776,11 @@ nsAttrValue::Contains(nsIAtom* aValue, nsCaseTreatment aCaseSensitive) const return aValue == atom; } - const char *val1, *val2; - aValue->GetUTF8String(&val1); - atom->GetUTF8String(&val2); - - return nsCRT::strcasecmp(val1, val2) == 0; + // For performance reasons, don't do a full on unicode case insensitive + // string comparison. This is only used for quirks mode anyway. + return + nsContentUtils::EqualsIgnoreASCIICase(nsDependentAtomString(aValue), + nsDependentAtomString(atom)); } default: { @@ -790,12 +790,14 @@ nsAttrValue::Contains(nsIAtom* aValue, nsCaseTreatment aCaseSensitive) const return array->IndexOf(aValue) >= 0; } - const char *val1, *val2; - aValue->GetUTF8String(&val1); + nsDependentAtomString val1(aValue); for (PRInt32 i = 0, count = array->Count(); i < count; ++i) { - array->ObjectAt(i)->GetUTF8String(&val2); - if (nsCRT::strcasecmp(val1, val2) == 0) { + // For performance reasons, don't do a full on unicode case + // insensitive string comparison. This is only used for quirks mode + // anyway. + if (nsContentUtils::EqualsIgnoreASCIICase(val1, + nsDependentAtomString(array->ObjectAt(i)))) { return PR_TRUE; } } diff --git a/content/base/src/nsContentSink.cpp b/content/base/src/nsContentSink.cpp index 00b93120d5d8..9abe3c2b36f9 100644 --- a/content/base/src/nsContentSink.cpp +++ b/content/base/src/nsContentSink.cpp @@ -532,11 +532,9 @@ nsContentSink::ProcessHeaderData(nsIAtom* aHeader, const nsAString& aValue, if (NS_SUCCEEDED(mParser->GetChannel(getter_AddRefs(channel)))) { nsCOMPtr httpChannel(do_QueryInterface(channel)); if (httpChannel) { - const char* header; - (void)aHeader->GetUTF8String(&header); - (void)httpChannel->SetResponseHeader(nsDependentCString(header), - NS_ConvertUTF16toUTF8(aValue), - PR_TRUE); + httpChannel->SetResponseHeader(nsAtomCString(aHeader), + NS_ConvertUTF16toUTF8(aValue), + PR_TRUE); } } } diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp index a612a37de8b2..a8cd9279fce3 100644 --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -1897,10 +1897,7 @@ static inline void KeyAppendAtom(nsIAtom* aAtom, nsACString& aKey) { NS_PRECONDITION(aAtom, "KeyAppendAtom: aAtom can not be null!\n"); - const char* atomString = nsnull; - aAtom->GetUTF8String(&atomString); - - KeyAppendString(nsDependentCString(atomString), aKey); + KeyAppendString(nsAtomCString(aAtom), aKey); } static inline PRBool IsAutocompleteOff(nsIDOMElement* aElement) @@ -3210,8 +3207,7 @@ nsAutoGCRoot::RemoveJSGCRoot(void* aPtr) PRBool nsContentUtils::IsEventAttributeName(nsIAtom* aName, PRInt32 aType) { - const char* name; - aName->GetUTF8String(&name); + const PRUnichar* name = aName->GetUTF16String(); if (name[0] != 'o' || name[1] != 'n') return PR_FALSE; @@ -4930,6 +4926,43 @@ nsContentUtils::ASCIIToUpper(nsAString& aStr) } } +PRBool +nsContentUtils::EqualsIgnoreASCIICase(const nsAString& aStr1, + const nsAString& aStr2) +{ + PRUint32 len = aStr1.Length(); + if (len != aStr2.Length()) { + return PR_FALSE; + } + + const PRUnichar* str1 = aStr1.BeginReading(); + const PRUnichar* str2 = aStr2.BeginReading(); + const PRUnichar* end = str1 + len; + + while (str1 < end) { + PRUnichar c1 = *str1++; + PRUnichar c2 = *str2++; + + // First check if any bits other than the 0x0020 differs + if ((c1 ^ c2) & 0xffdf) { + return PR_FALSE; + } + + // We know they only differ in the 0x0020 bit. + // Likely the two chars are the same, so check that first + if (c1 != c2) { + // They do differ, but since it's only in the 0x0020 bit, check if it's + // the same ascii char, but just differing in case + PRUnichar c1Upper = c1 & 0xffdf; + if (!('A' <= c1Upper && c1Upper <= 'Z')) { + return PR_FALSE; + } + } + } + + return PR_TRUE; +} + /* static */ void nsAutoGCRoot::Shutdown() diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index f8153916c9e4..05fba9c90885 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -6718,9 +6718,7 @@ nsDocument::CreateElem(nsIAtom *aName, nsIAtom *aPrefix, PRInt32 aNamespaceID, aPrefix->ToString(qName); qName.Append(':'); } - const char *name; - aName->GetUTF8String(&name); - AppendUTF8toUTF16(name, qName); + qName.Append(nsAtomString(aName)); // Note: "a:b:c" is a valid name in non-namespaces XML, and // nsDocument::CreateElement can call us with such a name and no prefix, diff --git a/content/base/src/nsHTMLContentSerializer.cpp b/content/base/src/nsHTMLContentSerializer.cpp index ec630fa5f14a..19d2bbd729b7 100644 --- a/content/base/src/nsHTMLContentSerializer.cpp +++ b/content/base/src/nsHTMLContentSerializer.cpp @@ -69,8 +69,6 @@ #include "nsIScriptElement.h" #include "nsAttrName.h" -static const char kMozStr[] = "moz"; - static const PRInt32 kLongLineLen = 128; nsresult NS_NewHTMLContentSerializer(nsIContentSerializer** aSerializer) @@ -123,10 +121,9 @@ nsHTMLContentSerializer::SerializeHTMLAttributes(nsIContent* aContent, nsIAtom* attrName = name->LocalName(); // Filter out any attribute starting with [-|_]moz - const char* sharedName; - attrName->GetUTF8String(&sharedName); - if ((('_' == *sharedName) || ('-' == *sharedName)) && - !nsCRT::strncmp(sharedName+1, kMozStr, PRUint32(sizeof(kMozStr)-1))) { + nsDependentAtomString attrNameStr(attrName); + if (StringBeginsWith(attrNameStr, NS_LITERAL_STRING("_moz")) || + StringBeginsWith(attrNameStr, NS_LITERAL_STRING("-moz"))) { continue; } aContent->GetAttr(namespaceID, attrName, valueStr); diff --git a/content/base/src/nsNodeInfo.cpp b/content/base/src/nsNodeInfo.cpp index b10091cd2957..5488fff01a03 100644 --- a/content/base/src/nsNodeInfo.cpp +++ b/content/base/src/nsNodeInfo.cpp @@ -257,16 +257,13 @@ nsNodeInfo::QualifiedNameEqualsInternal(const nsACString& aQualifiedName) const nsACString::const_iterator colon(start); - const char* prefix; - mInner.mPrefix->GetUTF8String(&prefix); + nsAtomCString prefix(mInner.mPrefix); - PRUint32 len = strlen(prefix); - - if (len >= aQualifiedName.Length()) { + if (prefix.Length() >= aQualifiedName.Length()) { return PR_FALSE; } - colon.advance(len); + colon.advance(prefix.Length()); // If the character at the prefix length index is not a colon, // aQualifiedName is not equal to this string. @@ -275,7 +272,7 @@ nsNodeInfo::QualifiedNameEqualsInternal(const nsACString& aQualifiedName) const } // Compare the prefix to the string from the start to the colon - if (!mInner.mPrefix->EqualsUTF8(Substring(start, colon))) + if (!prefix.Equals(Substring(start, colon))) return PR_FALSE; ++colon; // Skip the ':' diff --git a/content/base/src/nsXHTMLContentSerializer.cpp b/content/base/src/nsXHTMLContentSerializer.cpp index 584f2ad7194d..1382fe2fe946 100644 --- a/content/base/src/nsXHTMLContentSerializer.cpp +++ b/content/base/src/nsXHTMLContentSerializer.cpp @@ -346,10 +346,9 @@ nsXHTMLContentSerializer::SerializeAttributes(nsIContent* aContent, nsIAtom* attrPrefix = name->GetPrefix(); // Filter out any attribute starting with [-|_]moz - const char* sharedName; - attrName->GetUTF8String(&sharedName); - if ((('_' == *sharedName) || ('-' == *sharedName)) && - !nsCRT::strncmp(sharedName+1, kMozStr, PRUint32(sizeof(kMozStr)-1))) { + nsDependentAtomString attrNameStr(attrName); + if (StringBeginsWith(attrNameStr, NS_LITERAL_STRING("_moz")) || + StringBeginsWith(attrNameStr, NS_LITERAL_STRING("-moz"))) { continue; } diff --git a/content/html/document/src/nsHTMLContentSink.cpp b/content/html/document/src/nsHTMLContentSink.cpp index eb56894e1ab3..40cbf5abc93f 100644 --- a/content/html/document/src/nsHTMLContentSink.cpp +++ b/content/html/document/src/nsHTMLContentSink.cpp @@ -942,13 +942,10 @@ SinkContext::CloseContainer(const nsHTMLTag aTag, PRBool aMalformed) #ifdef NS_DEBUG { // Tracing code - const char *tagStr; - mStack[mStackPos].mContent->Tag()->GetUTF8String(&tagStr); - SINK_TRACE(gSinkLogModuleInfo, SINK_TRACE_REFLOW, ("SinkContext::CloseContainer: reflow on notifyImmediate " "tag=%s newIndex=%d stackPos=%d", - tagStr, + nsAtomCString(mStack[mStackPos].mContent->Tag()).get(), mStack[mStackPos].mNumFlushed, mStackPos)); } #endif @@ -1353,12 +1350,10 @@ SinkContext::FlushTags() #ifdef NS_DEBUG { // Tracing code - const char* tagStr; - mStack[stackPos].mContent->Tag()->GetUTF8String(&tagStr); - SINK_TRACE(gSinkLogModuleInfo, SINK_TRACE_REFLOW, ("SinkContext::FlushTags: tag=%s from newindex=%d at " - "stackPos=%d", tagStr, + "stackPos=%d", + nsAtomCString(mStack[stackPos].mContent->Tag()).get(), mStack[stackPos].mNumFlushed, stackPos)); } #endif diff --git a/content/smil/nsSMILCompositor.cpp b/content/smil/nsSMILCompositor.cpp index 894f4357531d..081b75f38bce 100644 --- a/content/smil/nsSMILCompositor.cpp +++ b/content/smil/nsSMILCompositor.cpp @@ -51,10 +51,8 @@ nsSMILCompositor::KeyEquals(KeyTypePointer aKey) const nsSMILCompositor::HashKey(KeyTypePointer aKey) { // Combine the 3 values into one numeric value, which will be hashed - const char *attrName = nsnull; - aKey->mAttributeName->GetUTF8String(&attrName); - return NS_PTR_TO_UINT32(aKey->mElement.get()) + - HashString(attrName) + + return NS_PTR_TO_UINT32(aKey->mElement.get()) >> 4 + + NS_PTR_TO_INT32(aKey->mAttributeName.get()) + (aKey->mIsCSS ? 1 : 0); } diff --git a/content/xslt/src/base/txStringUtils.h b/content/xslt/src/base/txStringUtils.h index 852282c46540..9714f73ca0a0 100644 --- a/content/xslt/src/base/txStringUtils.h +++ b/content/xslt/src/base/txStringUtils.h @@ -49,10 +49,7 @@ inline PRBool TX_StringEqualsAtom(const nsASingleFragmentString& aString, nsIAtom* aAtom) { - const char* ASCIIAtom; - aAtom->GetUTF8String(&ASCIIAtom); - - return aString.EqualsASCII(ASCIIAtom); + return aAtom->Equals(aString); } #ifndef TX_EXE diff --git a/content/xslt/src/xpath/txXPCOMExtensionFunction.cpp b/content/xslt/src/xpath/txXPCOMExtensionFunction.cpp index f7822b5b1040..83e182e80732 100644 --- a/content/xslt/src/xpath/txXPCOMExtensionFunction.cpp +++ b/content/xslt/src/xpath/txXPCOMExtensionFunction.cpp @@ -212,10 +212,9 @@ LookupFunction(const char *aContractID, nsIAtom* aName, nsIID &aIID, // foo-bar becomes fooBar). Note that if there are any names that already // have uppercase letters they might cause false matches (both fooBar and // foo-bar matching fooBar). - const char *name; - aName->GetUTF8String(&name); + const PRUnichar *name = aName->GetUTF16String(); nsCAutoString methodName; - char letter; + PRUnichar letter; PRBool upperNext = PR_FALSE; while ((letter = *name)) { if (letter == '-') { diff --git a/content/xul/document/src/nsXULDocument.cpp b/content/xul/document/src/nsXULDocument.cpp index 0786d5d514a9..5009e69a37ce 100644 --- a/content/xul/document/src/nsXULDocument.cpp +++ b/content/xul/document/src/nsXULDocument.cpp @@ -1408,20 +1408,17 @@ nsXULDocument::Persist(nsIContent* aElement, PRInt32 aNameSpaceID, // Ick. Construct a property from the attribute. Punt on // namespaces for now. - const char* attrstr; - rv = aAttribute->GetUTF8String(&attrstr); - if (NS_FAILED(rv)) return rv; - // Don't bother with unreasonable attributes. We clamp long values, // but truncating attribute names turns it into a different attribute // so there's no point in persisting anything at all - if (!attrstr || strlen(attrstr) > kMaxAttrNameLength) { + nsAtomCString attrstr(aAttribute); + if (attrstr.Length() > kMaxAttrNameLength) { NS_WARNING("Can't persist, Attribute name too long"); return NS_ERROR_ILLEGAL_VALUE; } nsCOMPtr attr; - rv = gRDFService->GetResource(nsDependentCString(attrstr), + rv = gRDFService->GetResource(attrstr, getter_AddRefs(attr)); if (NS_FAILED(rv)) return rv; diff --git a/content/xul/templates/src/nsXULContentBuilder.cpp b/content/xul/templates/src/nsXULContentBuilder.cpp index 03fe572c768c..497e9c05ee26 100644 --- a/content/xul/templates/src/nsXULContentBuilder.cpp +++ b/content/xul/templates/src/nsXULContentBuilder.cpp @@ -483,17 +483,14 @@ nsXULContentBuilder::BuildContentFromTemplate(nsIContent *aTemplateNode, ("nsXULContentBuilder::BuildContentFromTemplate (is unique: %d)", aIsUnique)); - const char *tmpln, *resn, *realn; - aTemplateNode->Tag()->GetUTF8String(&tmpln); - aResourceNode->Tag()->GetUTF8String(&resn); - aRealNode->Tag()->GetUTF8String(&realn); - nsAutoString id; aChild->GetId(id); PR_LOG(gXULTemplateLog, PR_LOG_ALWAYS, ("Tags: [Template: %s Resource: %s Real: %s] for id %s", - tmpln, resn, realn, NS_ConvertUTF16toUTF8(id).get())); + nsAtomCString(aTemplateNode->Tag()).get(), + nsAtomCString(aResourceNode->Tag()).get(), + nsAtomCString(aRealNode->Tag()).get(), NS_ConvertUTF16toUTF8(id).get())); } #endif @@ -562,11 +559,9 @@ nsXULContentBuilder::BuildContentFromTemplate(nsIContent *aTemplateNode, #ifdef PR_LOGGING if (PR_LOG_TEST(gXULTemplateLog, PR_LOG_DEBUG)) { - const char *tagname; - tag->GetUTF8String(&tagname); PR_LOG(gXULTemplateLog, PR_LOG_DEBUG, ("xultemplate[%p] building %s %s %s", - this, tagname, + this, nsAtomCString(tag).get(), (isGenerationElement ? "[resource]" : ""), (isUnique ? "[unique]" : ""))); } diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index db55d5ebc6bd..e1aadacd4d4b 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -1927,26 +1927,24 @@ nsJSContext::ExecuteScript(void *aScriptObject, } -static inline const char * -AtomToEventHandlerName(nsIAtom *aName) -{ - const char *name; - - aName->GetUTF8String(&name); - #ifdef DEBUG - const char *cp; - char c; +PRBool +AtomIsEventHandlerName(nsIAtom *aName) +{ + const PRUnichar *name = aName->GetUTF16String(); + + const PRUnichar *cp; + PRUnichar c; for (cp = name; *cp != '\0'; ++cp) { c = *cp; - NS_ASSERTION (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z'), - "non-ASCII non-alphabetic event handler name"); + if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z')) + return PR_FALSE; } -#endif - return name; + return PR_TRUE; } +#endif // Helper function to find the JSObject associated with a (presumably DOM) // interface. @@ -1992,6 +1990,7 @@ nsJSContext::CompileEventHandler(nsIAtom *aName, { NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED); + NS_PRECONDITION(AtomIsEventHandlerName(aName), "Bad event name"); NS_PRECONDITION(!::JS_IsExceptionPending(mContext), "Why are we being called with a pending exception?"); @@ -2008,8 +2007,6 @@ nsJSContext::CompileEventHandler(nsIAtom *aName, return NS_ERROR_ILLEGAL_VALUE; } - const char *charName = AtomToEventHandlerName(aName); - #ifdef DEBUG JSContext* top = nsContentUtils::GetCurrentJSContext(); NS_ASSERTION(mContext == top, "Context not properly pushed!"); @@ -2024,7 +2021,7 @@ nsJSContext::CompileEventHandler(nsIAtom *aName, JSFunction* fun = ::JS_CompileUCFunctionForPrincipals(mContext, nsnull, nsnull, - charName, aArgCount, aArgNames, + nsAtomCString(aName).get(), aArgCount, aArgNames, (jschar*)PromiseFlatString(aBody).get(), aBody.Length(), aURL, aLineNo); @@ -2206,7 +2203,7 @@ nsJSContext::BindCompiledEventHandler(nsISupports* aTarget, void *aScope, NS_ENSURE_ARG(aHandler); NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED); - const char *charName = AtomToEventHandlerName(aName); + NS_PRECONDITION(AtomIsEventHandlerName(aName), "Bad event name"); nsresult rv; // Get the jsobject associated with this target @@ -2240,7 +2237,7 @@ nsJSContext::BindCompiledEventHandler(nsISupports* aTarget, void *aScope, if (NS_SUCCEEDED(rv) && // Make sure the flags here match those in nsEventReceiverSH::NewResolve - !::JS_DefineProperty(mContext, target, charName, + !::JS_DefineProperty(mContext, target, nsAtomCString(aName).get(), OBJECT_TO_JSVAL(funobj), nsnull, nsnull, JSPROP_ENUMERATE | JSPROP_PERMANENT)) { ReportPendingException(); @@ -2262,6 +2259,8 @@ nsJSContext::GetBoundEventHandler(nsISupports* aTarget, void *aScope, nsIAtom* aName, nsScriptObjectHolder &aHandler) { + NS_PRECONDITION(AtomIsEventHandlerName(aName), "Bad event name"); + nsresult rv; JSObject *obj = nsnull; nsAutoGCRoot root(&obj, &rv); @@ -2270,11 +2269,9 @@ nsJSContext::GetBoundEventHandler(nsISupports* aTarget, void *aScope, rv = JSObjectFromInterface(aTarget, aScope, &obj); NS_ENSURE_SUCCESS(rv, rv); - const char *charName = AtomToEventHandlerName(aName); - jsval funval; if (!JS_LookupProperty(mContext, obj, - charName, &funval)) + nsAtomCString(aName).get(), &funval)) return NS_ERROR_FAILURE; if (JS_TypeOfValue(mContext, funval) != JSTYPE_FUNCTION) { diff --git a/gfx/thebes/src/gfxWindowsFonts.cpp b/gfx/thebes/src/gfxWindowsFonts.cpp index d40960ef34ca..8e501b4a6c97 100644 --- a/gfx/thebes/src/gfxWindowsFonts.cpp +++ b/gfx/thebes/src/gfxWindowsFonts.cpp @@ -1860,9 +1860,7 @@ gfxWindowsFontGroup::WhichPrefFontSupportsChar(PRUint32 aCh) nsIAtom *langGroup = LangGroupFromUnicodeRange(unicodeRange); if (langGroup) { #ifdef PR_LOGGING - const char *langGroupStr; - langGroup->GetUTF8String(&langGroupStr); - PR_LOG(gFontLog, PR_LOG_DEBUG, (" - Trying to find fonts for: %s", langGroupStr)); + PR_LOG(gFontLog, PR_LOG_DEBUG, (" - Trying to find fonts for: %s", nsAtomCString(langGroup).get())); #endif nsAutoTArray, 5> fonts; this->GetPrefFonts(langGroup, fonts); diff --git a/gfx/thebes/test/gfxFontSelectionTests.h b/gfx/thebes/test/gfxFontSelectionTests.h index d45b503fb4d0..4aad859ac9ca 100644 --- a/gfx/thebes/test/gfxFontSelectionTests.h +++ b/gfx/thebes/test/gfxFontSelectionTests.h @@ -109,7 +109,7 @@ SetupTests() NS_FONT_STRETCH_NORMAL, 400, 16.0, - NS_NewPermanentAtom(NS_LITERAL_CSTRING("en")), + NS_NewPermanentAtom(NS_LITERAL_STRING("en")), 0.0, PR_FALSE, PR_FALSE, PR_FALSE); @@ -117,7 +117,7 @@ SetupTests() NS_FONT_STRETCH_NORMAL, 700, 16.0, - NS_NewPermanentAtom(NS_LITERAL_CSTRING("en")), + NS_NewPermanentAtom(NS_LITERAL_STRING("en")), 0.0, PR_FALSE, PR_FALSE, PR_FALSE); diff --git a/gfx/thebes/test/gfxTextRunPerfTest.cpp b/gfx/thebes/test/gfxTextRunPerfTest.cpp index 1c0ba78f4e6a..700ffbfcbaa2 100644 --- a/gfx/thebes/test/gfxTextRunPerfTest.cpp +++ b/gfx/thebes/test/gfxTextRunPerfTest.cpp @@ -93,7 +93,7 @@ RunTest (TestEntry *test, gfxContext *ctx) { NS_FONT_STRETCH_NORMAL, 400, 16.0, - NS_NewPermanentAtom(NS_LITERAL_CSTRING("en")), + NS_NewPermanentAtom(NS_LITERAL_STRING("en")), 0.0, PR_FALSE, PR_FALSE, PR_FALSE); diff --git a/gfx/thebes/test/gfxWordCacheTest.cpp b/gfx/thebes/test/gfxWordCacheTest.cpp index b632883584cd..7f42e1614a4d 100644 --- a/gfx/thebes/test/gfxWordCacheTest.cpp +++ b/gfx/thebes/test/gfxWordCacheTest.cpp @@ -159,7 +159,7 @@ main (int argc, char **argv) { NS_FONT_STRETCH_NORMAL, 139, 10.0, - NS_NewPermanentAtom(NS_LITERAL_CSTRING("en")), + NS_NewPermanentAtom(NS_LITERAL_STRING("en")), 0.0, PR_FALSE, PR_FALSE, PR_FALSE); diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp index 757a024b1ed4..7fa3863aa43d 100644 --- a/layout/base/nsPresContext.cpp +++ b/layout/base/nsPresContext.cpp @@ -431,13 +431,19 @@ nsPresContext::GetFontPreferences() mDefaultFixedFont.size = CSSPixelsToAppUnits(13); // the font prefs are based on langGroup, not actual language - const char *langGroup = "x-western"; // Assume x-western is safe... + nsCAutoString langGroup; if (mLanguage && mLangService) { nsresult rv; nsIAtom *group = mLangService->GetLanguageGroup(mLanguage, &rv); if (NS_SUCCEEDED(rv) && group) { - group->GetUTF8String(&langGroup); + group->ToUTF8String(langGroup); } + else { + langGroup.AssignLiteral("x-western"); // Assume x-western is safe... + } + } + else { + langGroup.AssignLiteral("x-western"); // Assume x-western is safe... } nsCAutoString pref; diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 41adf3504b4f..5cad8b88cdd3 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -6734,11 +6734,13 @@ static void GetTagName(nsFrame* aFrame, nsIContent* aContent, PRIntn aResultSize, char* aResult) { - const char *nameStr = ""; if (aContent) { - aContent->Tag()->GetUTF8String(&nameStr); + PR_snprintf(aResult, aResultSize, "%s@%p", + nsAtomCString(aContent->Tag()).get(), aFrame); + } + else { + PR_snprintf(aResult, aResultSize, "@%p", aFrame); } - PR_snprintf(aResult, aResultSize, "%s@%p", nameStr, aFrame); } void diff --git a/layout/generic/nsSelection.cpp b/layout/generic/nsSelection.cpp index d918fa1a392f..46ea01ab9699 100644 --- a/layout/generic/nsSelection.cpp +++ b/layout/generic/nsSelection.cpp @@ -4881,9 +4881,8 @@ nsTypedSelection::Collapse(nsINode* aParentNode, PRInt32 aOffset) if (!content) return NS_ERROR_FAILURE; - const char *tagString; - content->Tag()->GetUTF8String(&tagString); - printf ("Sel. Collapse to %p %s %d\n", content.get(), tagString, aOffset); + printf ("Sel. Collapse to %p %s %d\n", content.get(), + nsAtomCString(content->Tag()).get(), aOffset); } else { printf ("Sel. Collapse set to null parent.\n"); @@ -5274,9 +5273,8 @@ nsTypedSelection::Extend(nsINode* aParentNode, PRInt32 aOffset) nsCOMPtrcontent; content = do_QueryInterface(aParentNode); - const char *tagString; - content->Tag()->GetUTF8String(&tagString); - printf ("Sel. Extend to %p %s %d\n", content.get(), tagString, aOffset); + printf ("Sel. Extend to %p %s %d\n", content.get(), + nsAtomCString(content->Tag()).get(), aOffset); } else { printf ("Sel. Extend set to null parent.\n"); diff --git a/layout/generic/nsTextFrameThebes.cpp b/layout/generic/nsTextFrameThebes.cpp index 1ca82616e744..98e796f7a045 100644 --- a/layout/generic/nsTextFrameThebes.cpp +++ b/layout/generic/nsTextFrameThebes.cpp @@ -2164,10 +2164,10 @@ static PRBool IsChineseOrJapanese(nsIFrame* aFrame) if (!language) { return PR_FALSE; } - const char *lang; - language->GetUTF8String(&lang); - return (!strncmp(lang, "ja", 2) || !strncmp(lang, "zh", 2)) && - (lang[2] == '\0' || lang[2] == '-'); + const PRUnichar *lang = language->GetUTF16String(); + return (!nsCRT::strncmp(lang, NS_LITERAL_STRING("ja").get(), 2) || + !nsCRT::strncmp(lang, NS_LITERAL_STRING("zh").get(), 2)) && + (language->GetLength() == 2 || lang[2] == '-'); } #ifdef DEBUG diff --git a/layout/style/nsCSSAnonBoxes.cpp b/layout/style/nsCSSAnonBoxes.cpp index d65a28278d22..444178dd640a 100644 --- a/layout/style/nsCSSAnonBoxes.cpp +++ b/layout/style/nsCSSAnonBoxes.cpp @@ -78,9 +78,7 @@ PRBool nsCSSAnonBoxes::IsAnonBox(nsIAtom *aAtom) /* static */ PRBool nsCSSAnonBoxes::IsTreePseudoElement(nsIAtom* aPseudo) { - const char* str; - aPseudo->GetUTF8String(&str); - static const char moz_tree[] = ":-moz-tree-"; - return nsCRT::strncmp(str, moz_tree, PRInt32(sizeof(moz_tree)-1)) == 0; + return StringBeginsWith(nsDependentAtomString(aPseudo), + NS_LITERAL_STRING(":-moz-tree-")); } #endif diff --git a/layout/style/nsCSSRuleProcessor.cpp b/layout/style/nsCSSRuleProcessor.cpp index 8db9930f555b..90f73b9b7369 100644 --- a/layout/style/nsCSSRuleProcessor.cpp +++ b/layout/style/nsCSSRuleProcessor.cpp @@ -196,11 +196,13 @@ RuleHash_CIMatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr, if (match_atom == entry_atom) return PR_TRUE; - const char *match_str, *entry_str; - match_atom->GetUTF8String(&match_str); - entry_atom->GetUTF8String(&entry_str); + // Use EqualsIgnoreASCIICase instead of full on unicode case conversion + // in order to save on performance. This is only used in quirks mode + // anyway. - return (nsCRT::strcasecmp(entry_str, match_str) == 0); + return + nsContentUtils::EqualsIgnoreASCIICase(nsDependentAtomString(entry_atom), + nsDependentAtomString(match_atom)); } static PRBool @@ -1834,13 +1836,13 @@ static PRBool SelectorMatches(RuleProcessorData &data, IDList = IDList->mNext; } while (IDList); } else { - const char* id1Str; - data.mContentID->GetUTF8String(&id1Str); - nsDependentCString id1(id1Str); + // Use EqualsIgnoreASCIICase instead of full on unicode case conversion + // in order to save on performance. This is only used in quirks mode + // anyway. + nsDependentAtomString id1Str(data.mContentID); do { - const char* id2Str; - IDList->mAtom->GetUTF8String(&id2Str); - if (!id1.Equals(id2Str, nsCaseInsensitiveCStringComparator())) { + if (!nsContentUtils::EqualsIgnoreASCIICase(id1Str, + nsDependentAtomString(IDList->mAtom))) { return PR_FALSE; } IDList = IDList->mNext; diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp index d0f1a9495d7d..f260da029e1c 100644 --- a/layout/style/nsComputedDOMStyle.cpp +++ b/layout/style/nsComputedDOMStyle.cpp @@ -4294,10 +4294,9 @@ nsComputedDOMStyle::GetTransitionProperty(nsIDOMCSSValue** aValue) property->SetIdent(eCSSKeyword_none); else if (cssprop == eCSSProperty_UNKNOWN) { - const char *str; - transition->GetUnknownProperty()->GetUTF8String(&str); nsAutoString escaped; - nsStyleUtil::AppendEscapedCSSIdent(NS_ConvertUTF8toUTF16(str), escaped); + nsStyleUtil::AppendEscapedCSSIdent( + nsDependentAtomString(transition->GetUnknownProperty()), escaped); property->SetString(escaped); // really want SetIdent } else diff --git a/parser/html/nsHtml5Atom.cpp b/parser/html/nsHtml5Atom.cpp index 41998bfe30cc..77c4c609a56e 100644 --- a/parser/html/nsHtml5Atom.cpp +++ b/parser/html/nsHtml5Atom.cpp @@ -82,9 +82,16 @@ nsHtml5Atom::ToUTF8String(nsACString& aReturn) } NS_IMETHODIMP -nsHtml5Atom::GetUTF8String(const char **aReturn) +nsHtml5Atom::GetUTF16String(const PRUnichar **aReturn) { - NS_NOTREACHED("Should not attempt to get a UTF-8 string from nsHtml5Atom"); + NS_NOTREACHED("Should not attempt to get a UTF-16 string from nsHtml5Atom"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP_(PRUint32) +nsHtml5Atom::GetLength() +{ + NS_NOTREACHED("Should not attempt to get a length from nsHtml5Atom"); return NS_ERROR_NOT_IMPLEMENTED; } diff --git a/parser/htmlparser/src/nsHTMLTags.cpp b/parser/htmlparser/src/nsHTMLTags.cpp index 0f81da1bd54a..4e2659f57935 100644 --- a/parser/htmlparser/src/nsHTMLTags.cpp +++ b/parser/htmlparser/src/nsHTMLTags.cpp @@ -368,12 +368,12 @@ nsHTMLTags::AddRefTable(void) -#ifdef DEBUG +#if defined(DEBUG) && defined(NS_STATIC_ATOM_USE_WIDE_STRINGS) { // let's verify that all names in the the table are lowercase... for (i = 0; i < NS_HTML_TAG_MAX; ++i) { - nsCAutoString temp1((char*)sTagAtoms_info[i].mStringBuffer->Data()); - nsCAutoString temp2((char*)sTagAtoms_info[i].mStringBuffer->Data()); + nsAutoString temp1((PRUnichar*)sTagAtoms_info[i].mStringBuffer->Data()); + nsAutoString temp2((PRUnichar*)sTagAtoms_info[i].mStringBuffer->Data()); ToLowerCase(temp1); NS_ASSERTION(temp1.Equals(temp2), "upper case char in table"); } @@ -382,7 +382,7 @@ nsHTMLTags::AddRefTable(void) // correct. for (i = 0; i < NS_HTML_TAG_MAX; ++i) { nsAutoString temp1(sTagUnicodeTable[i]); - nsAutoString temp2; temp2.AssignWithConversion((char*)sTagAtoms_info[i].mStringBuffer->Data()); + nsAutoString temp2((PRUnichar*)sTagAtoms_info[i].mStringBuffer->Data()); NS_ASSERTION(temp1.Equals(temp2), "Bad unicode tag name!"); } diff --git a/rdf/base/src/nsRDFContentSink.cpp b/rdf/base/src/nsRDFContentSink.cpp index f7039dec320f..d661b2e65e00 100644 --- a/rdf/base/src/nsRDFContentSink.cpp +++ b/rdf/base/src/nsRDFContentSink.cpp @@ -1026,11 +1026,8 @@ RDFContentSinkImpl::AddProperties(const PRUnichar** aAttributes, } } - const char* attrName; - localName->GetUTF8String(&attrName); - NS_ConvertUTF16toUTF8 propertyStr(nameSpaceURI); - propertyStr.Append(attrName); + propertyStr.Append(nsAtomCString(localName)); // Add the assertion to RDF nsCOMPtr property; @@ -1158,11 +1155,8 @@ RDFContentSinkImpl::OpenObject(const PRUnichar* aName, } if (isaTypedNode) { - const char* attrName; - localName->GetUTF8String(&attrName); - NS_ConvertUTF16toUTF8 typeStr(nameSpaceURI); - typeStr.Append(attrName); + typeStr.Append(nsAtomCString(localName)); nsCOMPtr type; nsresult rv = gRDFService->GetResource(typeStr, getter_AddRefs(type)); @@ -1190,11 +1184,8 @@ RDFContentSinkImpl::OpenProperty(const PRUnichar* aName, const PRUnichar** aAttr const nsDependentSubstring& nameSpaceURI = SplitExpatName(aName, getter_AddRefs(localName)); - const char* attrName; - localName->GetUTF8String(&attrName); - NS_ConvertUTF16toUTF8 propertyStr(nameSpaceURI); - propertyStr.Append(attrName); + propertyStr.Append(nsAtomCString(localName)); nsCOMPtr property; rv = gRDFService->GetResource(propertyStr, getter_AddRefs(property)); diff --git a/xpcom/ds/nsAtomService.cpp b/xpcom/ds/nsAtomService.cpp index dc59a079c83d..a996505c0db4 100644 --- a/xpcom/ds/nsAtomService.cpp +++ b/xpcom/ds/nsAtomService.cpp @@ -59,7 +59,7 @@ nsAtomService::GetAtom(const nsAString& aString, nsIAtom ** aResult) nsresult nsAtomService::GetPermanentAtom(const nsAString& aString, nsIAtom ** aResult) { - *aResult = NS_NewPermanentAtom(NS_ConvertUTF16toUTF8(aString)); + *aResult = NS_NewPermanentAtom(aString); if (!*aResult) return NS_ERROR_OUT_OF_MEMORY; @@ -81,7 +81,7 @@ nsAtomService::GetAtomUTF8(const char *aValue, nsIAtom* *aResult) NS_IMETHODIMP nsAtomService::GetPermanentAtomUTF8(const char *aValue, nsIAtom* *aResult) { - *aResult = NS_NewPermanentAtom(nsDependentCString(aValue)); + *aResult = NS_NewPermanentAtom(NS_ConvertUTF8toUTF16(aValue)); if (!*aResult) return NS_ERROR_OUT_OF_MEMORY; diff --git a/xpcom/ds/nsAtomTable.cpp b/xpcom/ds/nsAtomTable.cpp index 180b0b2becf9..db2945dde875 100644 --- a/xpcom/ds/nsAtomTable.cpp +++ b/xpcom/ds/nsAtomTable.cpp @@ -153,7 +153,7 @@ struct AtomTableEntry : public PLDHashEntryHdr { // type-agnostic accessors // get the string buffer - inline const char* getAtomString() const { + inline const PRUnichar* getAtomString() const { NS_ASSERTION(keyHash > 1, "getAtomString() called on non-atom AtomTableEntry!"); @@ -200,14 +200,14 @@ AtomTableGetHash(PLDHashTable *table, const void *key) { const AtomTableEntry *e = static_cast(key); - if (e->IsUTF16String()) { - return nsCRT::HashCodeAsUTF8(e->getUTF16String(), e->getLength());; + if (e->IsUTF8String()) { + return nsCRT::HashCodeAsUTF16(e->getUTF8String(), e->getLength());; } - NS_ASSERTION(e->IsUTF8String(), + NS_ASSERTION(e->IsUTF16String(), "AtomTableGetHash() called on non-string-key AtomTableEntry!"); - return nsCRT::HashCode(e->getUTF8String(), e->getLength()); + return nsCRT::HashCode(e->getUTF16String(), e->getLength()); } static PRBool @@ -217,13 +217,13 @@ AtomTableMatchKey(PLDHashTable *table, const PLDHashEntryHdr *entry, const AtomTableEntry *he = static_cast(entry); const AtomTableEntry *strKey = static_cast(key); - const char *atomString = he->getAtomString(); + const PRUnichar *atomString = he->getAtomString(); - if (strKey->IsUTF16String()) { + if (strKey->IsUTF8String()) { return - CompareUTF8toUTF16(nsDependentCSubstring(atomString, atomString + he->getLength()), - nsDependentSubstring(strKey->getUTF16String(), - strKey->getUTF16String() + strKey->getLength())) == 0; + CompareUTF8toUTF16(nsDependentCSubstring(strKey->getUTF8String(), + strKey->getUTF8String() + strKey->getLength()), + nsDependentSubstring(atomString, atomString + he->getLength())) == 0; } PRUint32 length = he->getLength(); @@ -231,15 +231,15 @@ AtomTableMatchKey(PLDHashTable *table, const PLDHashEntryHdr *entry, return PR_FALSE; } - const char *str; + const PRUnichar *str; - if (strKey->IsUTF8String()) { - str = strKey->getUTF8String(); + if (strKey->IsUTF16String()) { + str = strKey->getUTF16String(); } else { str = strKey->getAtomString(); } - return memcmp(atomString, str, length * sizeof(char)) == 0; + return memcmp(atomString, str, length * sizeof(PRUnichar)) == 0; } static void @@ -298,9 +298,9 @@ DumpAtomLeaks(PLDHashTable *table, PLDHashEntryHdr *he, AtomImpl* atom = entry->GetAtomImpl(); if (!atom->IsPermanent()) { ++*static_cast(arg); - const char *str; - atom->GetUTF8String(&str); - fputs(str, stdout); + nsCAutoString str; + atom->ToUTF8String(str); + fputs(str.get(), stdout); fputs("\n", stdout); } return PL_DHASH_NEXT; @@ -343,25 +343,25 @@ NS_PurgeAtomTable() } } -AtomImpl::AtomImpl(const nsACString& aString) +AtomImpl::AtomImpl(const nsAString& aString) : mLength(aString.Length()) { nsStringBuffer* buf = nsStringBuffer::FromString(aString); if (buf) { buf->AddRef(); - mString = static_cast(buf->Data()); + mString = static_cast(buf->Data()); } else { - buf = nsStringBuffer::Alloc((mLength + 1) * sizeof(char)); - mString = static_cast(buf->Data()); - memcpy(mString, aString.BeginReading(), mLength * sizeof(char)); + buf = nsStringBuffer::Alloc((mLength + 1) * sizeof(PRUnichar)); + mString = static_cast(buf->Data()); + CopyUnicodeTo(aString, 0, mString, mLength); mString[mLength] = PRUnichar(0); } } AtomImpl::AtomImpl(nsStringBuffer* aStringBuffer, PRUint32 aLength) : mLength(aLength), - mString(static_cast(aStringBuffer->Data())) + mString(static_cast(aStringBuffer->Data())) { // Technically we could currently avoid doing this addref by instead making // the static atom buffers have an initial refcount of 2. @@ -430,37 +430,43 @@ void* PermanentAtomImpl::operator new ( size_t size, AtomImpl* aAtom ) CPP_THROW NS_IMETHODIMP AtomImpl::ToString(nsAString& aBuf) { - CopyUTF8toUTF16(nsDependentCString(mString, mLength), aBuf); + nsStringBuffer::FromData(mString)->ToString(mLength, aBuf); return NS_OK; } NS_IMETHODIMP AtomImpl::ToUTF8String(nsACString& aBuf) { - nsStringBuffer::FromData(mString)->ToString(mLength, aBuf); + CopyUTF16toUTF8(nsDependentString(mString, mLength), aBuf); return NS_OK; } NS_IMETHODIMP -AtomImpl::GetUTF8String(const char **aResult) +AtomImpl::GetUTF16String(const PRUnichar **aResult) { NS_PRECONDITION(aResult, "null out param"); *aResult = mString; return NS_OK; } +NS_IMETHODIMP_(PRUint32) +AtomImpl::GetLength() +{ + return mLength; +} + NS_IMETHODIMP AtomImpl::EqualsUTF8(const nsACString& aString, PRBool* aResult) { - *aResult = aString.Equals(nsDependentCString(mString, mLength)); + *aResult = CompareUTF8toUTF16(aString, + nsDependentString(mString, mLength)) == 0; return NS_OK; } NS_IMETHODIMP AtomImpl::Equals(const nsAString& aString, PRBool* aResult) { - *aResult = CompareUTF8toUTF16(nsDependentCString(mString, mLength), - aString) == 0; + *aResult = aString.Equals(nsDependentString(mString, mLength)); return NS_OK; } @@ -540,14 +546,15 @@ NS_RegisterStaticAtoms(const nsStaticAtom* aAtoms, PRUint32 aAtomCount) } for (PRUint32 i=0; iData()), +#ifdef NS_STATIC_ATOM_USE_WIDE_STRINGS + NS_ASSERTION(nsCRT::IsAscii((PRUnichar*)aAtoms[i].mStringBuffer->Data()), "Static atoms must be ASCII!"); PRUint32 stringLen = - aAtoms[i].mStringBuffer->StorageSize() / sizeof(char) - 1; + aAtoms[i].mStringBuffer->StorageSize() / sizeof(PRUnichar) - 1; AtomTableEntry *he = - GetAtomHashEntry((char*)aAtoms[i].mStringBuffer->Data(), + GetAtomHashEntry((PRUnichar*)aAtoms[i].mStringBuffer->Data(), stringLen); if (he->HasValue()) { @@ -569,11 +576,25 @@ NS_RegisterStaticAtoms(const nsStaticAtom* aAtoms, PRUint32 aAtomCount) *aAtoms[i].mAtom = atom; if (!gStaticAtomTableSealed) { - nsAutoString key; - atom->ToString(key); - gStaticAtomTable->Put(key, atom); + gStaticAtomTable->Put(nsAtomString(atom), atom); } } +#else // NS_STATIC_ATOM_USE_WIDE_STRINGS + NS_ASSERTION(nsCRT::IsAscii((char*)aAtoms[i].mStringBuffer->Data()), + "Static atoms must be ASCII!"); + + PRUint32 stringLen = aAtoms[i].mStringBuffer->StorageSize() - 1; + + NS_ConvertASCIItoUTF16 str((char*)aAtoms[i].mStringBuffer->Data(), + stringLen); + nsIAtom* atom = NS_NewPermanentAtom(str); + *aAtoms[i].mAtom = atom; + + if (!gStaticAtomTableSealed) { + gStaticAtomTable->Put(str, atom); + } +#endif + } return NS_OK; } @@ -594,13 +615,15 @@ NS_NewAtom(const nsACString& aUTF8String) return nsnull; } - NS_ASSERTION(!he->IsUTF8String() && !he->IsUTF16String(), - "Atom hash entry is string? Should be atom!"); - if (he->HasValue()) return he->GetAtom(); - AtomImpl* atom = new AtomImpl(aUTF8String); + // This results in an extra addref/release of the nsStringBuffer. + // Unfortunately there doesn't seem to be any APIs to avoid that. + nsString str; + CopyUTF8toUTF16(aUTF8String, str); + AtomImpl* atom = new AtomImpl(str); + he->SetAtomImpl(atom); NS_ADDREF(atom); @@ -622,12 +645,7 @@ NS_NewAtom(const nsAString& aUTF16String) if (he->HasValue()) return he->GetAtom(); - // This results in an extra addref/release of the nsStringBuffer. - // Unfortunately there doesn't seem to be any APIs to avoid that. - nsCString str; - CopyUTF16toUTF8(aUTF16String, str); - AtomImpl* atom = new AtomImpl(str); - + AtomImpl* atom = new AtomImpl(aUTF16String); he->SetAtomImpl(atom); NS_ADDREF(atom); @@ -635,10 +653,10 @@ NS_NewAtom(const nsAString& aUTF16String) } NS_COM nsIAtom* -NS_NewPermanentAtom(const nsACString& aUTF8String) +NS_NewPermanentAtom(const nsAString& aUTF16String) { - AtomTableEntry *he = GetAtomHashEntry(aUTF8String.Data(), - aUTF8String.Length()); + AtomTableEntry *he = GetAtomHashEntry(aUTF16String.Data(), + aUTF16String.Length()); if (he->HasValue()) { AtomImpl* atom = he->GetAtomImpl(); @@ -648,7 +666,7 @@ NS_NewPermanentAtom(const nsACString& aUTF8String) return atom; } - AtomImpl* atom = new PermanentAtomImpl(aUTF8String); + AtomImpl* atom = new PermanentAtomImpl(aUTF16String); he->SetAtomImpl(atom); // No need to addref since permanent atoms aren't refcounted anyway diff --git a/xpcom/ds/nsAtomTable.h b/xpcom/ds/nsAtomTable.h index f0446f1d09b5..6e8d05b1c4c3 100644 --- a/xpcom/ds/nsAtomTable.h +++ b/xpcom/ds/nsAtomTable.h @@ -48,7 +48,7 @@ class AtomImpl : public nsIAtom { public: - AtomImpl(const nsACString& aString); + AtomImpl(const nsAString& aString); // This is currently only used during startup when creating a permanent atom // from NS_RegisterStaticAtoms @@ -60,7 +60,7 @@ protected: AtomImpl() { // We can't really assert that mString is a valid nsStringBuffer string, // so do the best we can do and check for some consistencies. - NS_ASSERTION((mLength + 1) * sizeof(char) <= + NS_ASSERTION((mLength + 1) * sizeof(PRUnichar) <= nsStringBuffer::FromData(mString)->StorageSize() && mString[mLength] == 0, "Not initialized atom"); @@ -90,7 +90,7 @@ public: PRUint32 mLength; // This always points to the data owned by a nsStringBuffer - char* mString; + PRUnichar* mString; }; /** @@ -99,7 +99,7 @@ public: class PermanentAtomImpl : public AtomImpl { public: - PermanentAtomImpl(const nsACString& aString) + PermanentAtomImpl(const nsAString& aString) : AtomImpl(aString) {} PermanentAtomImpl(nsStringBuffer* aData, PRUint32 aLength) diff --git a/xpcom/ds/nsCRT.cpp b/xpcom/ds/nsCRT.cpp index 62b1c4595384..06ac61c33d2c 100644 --- a/xpcom/ds/nsCRT.cpp +++ b/xpcom/ds/nsCRT.cpp @@ -55,6 +55,7 @@ #include "nsIServiceManager.h" #include "nsCharTraits.h" #include "prbit.h" +#include "nsUTF8Utils.h" #define ADD_TO_HASHVAL(hashval, c) \ hashval = PR_ROTATE_LEFT32(hashval, 4) ^ (c); @@ -237,125 +238,44 @@ PRUint32 nsCRT::HashCode(const PRUnichar* str, PRUint32* resultingStrLen) return h; } -PRUint32 nsCRT::HashCodeAsUTF8(const PRUnichar* start, PRUint32 length) +PRUint32 nsCRT::HashCode(const PRUnichar* start, PRUint32 length) { PRUint32 h = 0; const PRUnichar* s = start; const PRUnichar* end = start + length; - PRUint16 W1 = 0; // the first UTF-16 word in a two word tuple - PRUint32 U = 0; // the current char as UCS-4 - int code_length = 0; // the number of bytes in the UTF-8 sequence for the current char - - PRUint16 W; - while ( s < end ) - { - W = *s++; - /* - * On the fly, decoding from UTF-16 (and/or UCS-2) into UTF-8 as per - * http://www.ietf.org/rfc/rfc2781.txt - * http://www.ietf.org/rfc/rfc3629.txt - */ - - if ( !W1 ) - { - if ( !IS_SURROGATE(W) ) - { - U = W; - if ( W <= 0x007F ) - code_length = 1; - else if ( W <= 0x07FF ) - code_length = 2; - else - code_length = 3; - } - else if ( NS_IS_HIGH_SURROGATE(W) && s < end) - { - W1 = W; - - continue; - } - else - { - // Treat broken characters as the Unicode replacement - // character 0xFFFD - U = 0xFFFD; - - code_length = 3; - - NS_WARNING("Got low surrogate but no previous high surrogate"); - } - } - else - { - // as required by the standard, this code is careful to - // throw out illegal sequences - - if ( NS_IS_LOW_SURROGATE(W) ) - { - U = SURROGATE_TO_UCS4(W1, W); - NS_ASSERTION(IS_VALID_CHAR(U), "How did this happen?"); - code_length = 4; - } - else - { - // Treat broken characters as the Unicode replacement - // character 0xFFFD - U = 0xFFFD; - - code_length = 3; - - NS_WARNING("High surrogate not followed by low surrogate"); - - // The pointer to the next character points to the second 16-bit - // value, not beyond it, as per Unicode 5.0.0 Chapter 3 C10, only - // the first code unit of an illegal sequence must be treated as - // an illegally terminated code unit sequence (also Chapter 3 - // D91, "isolated [not paired and ill-formed] UTF-16 code units - // in the range D800..DFFF are ill-formed"). - --s; - } - - W1 = 0; - } - - - static const PRUint16 sBytePrefix[5] = { 0x0000, 0x0000, 0x00C0, 0x00E0, 0x00F0 }; - static const PRUint16 sShift[5] = { 0, 0, 6, 12, 18 }; - - /* - * Unlike the algorithm in - * http://www.ietf.org/rfc/rfc3629.txt we must calculate the - * bytes in left to right order so that our hash result - * matches what the narrow version would calculate on an - * already UTF-8 string. - */ - - // hash the first (and often, only, byte) - ADD_TO_HASHVAL(h, (sBytePrefix[code_length] | (U>>sShift[code_length]))); - - // an unrolled loop for hashing any remaining bytes in this - // sequence - switch ( code_length ) - { // falling through in each case - case 4: ADD_TO_HASHVAL(h, (0x80 | ((U>>12) & 0x003F))); - case 3: ADD_TO_HASHVAL(h, (0x80 | ((U>>6 ) & 0x003F))); - case 2: ADD_TO_HASHVAL(h, (0x80 | ( U & 0x003F))); - default: code_length = 0; - break; - } - } + PRUnichar c; + while ( s < end ) { + c = *s++; + ADD_TO_HASHVAL(h, c); + } return h; } -PRUint32 nsCRT::BufferHashCode(const PRUnichar* s, PRUint32 len) +PRUint32 nsCRT::HashCodeAsUTF16(const char* start, PRUint32 length) { PRUint32 h = 0; - const PRUnichar* done = s + len; + const char* s = start; + const char* end = start + length; + + while ( s < end ) + { + PRBool err; + PRUint32 ucs4 = UTF8CharEnumerator::NextChar(&s, end, &err); + if (err) { + return 0; + } + + if (ucs4 < PLANE1_BASE) { + ADD_TO_HASHVAL(h, ucs4); + } + else { + ADD_TO_HASHVAL(h, H_SURROGATE(ucs4)); + ADD_TO_HASHVAL(h, L_SURROGATE(ucs4)); + } + } - while ( s < done ) - h = PR_ROTATE_LEFT32(h, 4) ^ PRUint16(*s++); // cast to unsigned to prevent possible sign extension return h; } diff --git a/xpcom/ds/nsCRT.h b/xpcom/ds/nsCRT.h index bd38f15a3871..8901130adff6 100644 --- a/xpcom/ds/nsCRT.h +++ b/xpcom/ds/nsCRT.h @@ -236,15 +236,13 @@ public: static PRUint32 HashCode(const PRUnichar* str, PRUint32* resultingStrLen = nsnull); - // Computes a hashcode for a length number of UTF16 - // characters. Returns the same hash code as the HashCode method - // taking a |char*| would if the string were converted to UTF8. This - // hash function treats invalid UTF16 data as 0xFFFD (0xEFBFBD in - // UTF-8). - static PRUint32 HashCodeAsUTF8(const PRUnichar* start, PRUint32 length); - // Computes the hashcode for a buffer with a specified length. - static PRUint32 BufferHashCode(const PRUnichar* str, PRUint32 strLen); + static PRUint32 HashCode(const PRUnichar* str, PRUint32 strLen); + + // Computes a hashcode for a length number of UTF8 + // characters. Returns the same hash code as the HashCode method + // taking a |PRUnichar*| would if the string were converted to UTF16. + static PRUint32 HashCodeAsUTF16(const char* start, PRUint32 length); // String to longlong static PRInt64 atoll(const char *str); diff --git a/xpcom/ds/nsIAtom.idl b/xpcom/ds/nsIAtom.idl index 6b34cdcc376a..2b25ab09bb7c 100644 --- a/xpcom/ds/nsIAtom.idl +++ b/xpcom/ds/nsIAtom.idl @@ -48,7 +48,7 @@ * pointer identity. */ -[scriptable, uuid(fbffe332-0856-421a-9b83-aaed0081fc40)] +[scriptable, uuid(96c82146-56f3-4b43-817f-25d6db1ad8e8)] interface nsIAtom : nsISupports { /** @@ -58,9 +58,10 @@ interface nsIAtom : nsISupports AUTF8String toUTF8String(); /** - * Return a pointer to a zero terminated UTF8 string. + * Return a pointer to a zero terminated UTF16 string. */ - [noscript] void getUTF8String([shared, retval] out string aResult); + [noscript] void getUTF16String([shared, retval] out wstring aResult); + [notxpcom] unsigned long getLength(); /** * Compare the atom to a specific string value @@ -83,6 +84,13 @@ interface nsIAtom : nsISupports EqualsUTF8(s, &result); return result; } + + inline const PRUnichar* GetUTF16String() { + const PRUnichar* result; + GetUTF16String(&result); + return result; + } + %} /** @@ -123,7 +131,6 @@ inline already_AddRefed do_GetAtom(const char* aUTF8String) * Find an atom that matches the given UTF-8 string. */ extern NS_COM nsIAtom* NS_NewAtom(const nsACString& aUTF8String); -extern NS_COM nsIAtom* NS_NewPermanentAtom(const nsACString& aUTF8String); inline already_AddRefed do_GetAtom(const nsACString& aUTF8String) { return NS_NewAtom(aUTF8String); } @@ -139,6 +146,7 @@ inline already_AddRefed do_GetAtom(const PRUnichar* aUTF16String) * Find an atom that matches the given UTF-16 string. */ extern NS_COM nsIAtom* NS_NewAtom(const nsAString& aUTF16String); +extern NS_COM nsIAtom* NS_NewPermanentAtom(const nsAString& aUTF16String); inline already_AddRefed do_GetAtom(const nsAString& aUTF16String) { return NS_NewAtom(aUTF16String); } @@ -159,4 +167,31 @@ extern NS_COM nsIAtom* NS_GetStaticAtom(const nsAString& aUTF16String); */ extern NS_COM void NS_SealStaticAtomTable(); +class nsAtomString : public nsString +{ +public: + nsAtomString(nsIAtom* aAtom) + { + aAtom->ToString(*this); + } +}; + +class nsAtomCString : public nsCString +{ +public: + nsAtomCString(nsIAtom* aAtom) + { + aAtom->ToUTF8String(*this); + } +}; + +class nsDependentAtomString : public nsDependentString +{ +public: + nsDependentAtomString(nsIAtom* aAtom) + : nsDependentString(aAtom->GetUTF16String(), aAtom->GetLength()) + { + } +}; + %} diff --git a/xpcom/ds/nsStaticAtom.h b/xpcom/ds/nsStaticAtom.h index 87f238dcabff..0736a9ecd370 100644 --- a/xpcom/ds/nsStaticAtom.h +++ b/xpcom/ds/nsStaticAtom.h @@ -43,8 +43,18 @@ #include "nsStringBuffer.h" #include "prlog.h" +#if defined(HAVE_CPP_CHAR16_T) +#define NS_STATIC_ATOM_USE_WIDE_STRINGS +typedef char16_t nsStaticAtomStringType; +#elif defined(HAVE_CPP_2BYTE_WCHAR_T) +#define NS_STATIC_ATOM_USE_WIDE_STRINGS +typedef wchar_t nsStaticAtomStringType; +#else +typedef char nsStaticAtomStringType; +#endif + #define NS_STATIC_ATOM(buffer_name, atom_ptr) { (nsStringBuffer*) &buffer_name, atom_ptr } -#define NS_STATIC_ATOM_BUFFER(buffer_name, str_data) static nsFakeStringBuffer< sizeof(str_data) > buffer_name = { 1, sizeof(str_data), str_data }; +#define NS_STATIC_ATOM_BUFFER(buffer_name, str_data) static nsFakeStringBuffer< sizeof(str_data) > buffer_name = { 1, sizeof(str_data) * sizeof(nsStaticAtomStringType), NS_L(str_data) }; /** * Holds data used to initialize large number of atoms during startup. Use @@ -63,11 +73,10 @@ template struct nsFakeStringBuffer { PRInt32 mRefCnt; PRUint32 mSize; - char mStringData[size]; + nsStaticAtomStringType mStringData[size]; }; -// register your lookup function with the atom table. Your function -// will be called when at atom is not found in the main atom table. +// Register static atoms with the atom table NS_COM nsresult NS_RegisterStaticAtoms(const nsStaticAtom*, PRUint32 aAtomCount); diff --git a/xpcom/tests/TestAtoms.cpp b/xpcom/tests/TestAtoms.cpp index 096c3c4bab69..6167c8ea4c63 100644 --- a/xpcom/tests/TestAtoms.cpp +++ b/xpcom/tests/TestAtoms.cpp @@ -81,9 +81,9 @@ int main(int argc, char** argv) // Now make sure we can find all the idents we just made for (i = 0; i < count; i++) { - const char *utf8String; - ids[i]->GetUTF8String(&utf8String); - nsIAtom* id = NS_NewAtom(utf8String); + const PRUnichar *utf16String; + ids[i]->GetUTF16String(&utf16String); + nsIAtom* id = NS_NewAtom(utf16String); if (id != ids[i]) { id->ToString(s1); ids[i]->ToString(s2); diff --git a/xpcom/tests/TestPermanentAtoms.cpp b/xpcom/tests/TestPermanentAtoms.cpp index 0fd4d7cd511c..b04cfb7bdd4c 100644 --- a/xpcom/tests/TestPermanentAtoms.cpp +++ b/xpcom/tests/TestPermanentAtoms.cpp @@ -51,9 +51,7 @@ static void Assert(PRBool aCondition, const char* aStatement) static void AssertString(nsIAtom *aAtom, const nsACString& aString) { - const char *str; - static_cast(aAtom)->GetUTF8String(&str); - Assert(nsDependentCString(str) == aString, "string is correct"); + Assert(aAtom->EqualsUTF8(aString), "string is correct"); } static void AssertPermanence(nsIAtom *aAtom, PRBool aPermanence) @@ -68,13 +66,13 @@ int main() AssertString(foo, NS_LITERAL_CSTRING("foo")); AssertPermanence(foo, PR_FALSE); - nsCOMPtr foop = do_GetPermanentAtom("foo"); + nsCOMPtr foop = NS_NewPermanentAtom(NS_LITERAL_STRING("foo")); AssertString(foop, NS_LITERAL_CSTRING("foo")); AssertPermanence(foop, PR_TRUE); Assert(foo == foop, "atoms are equal"); - nsCOMPtr barp = do_GetPermanentAtom("bar"); + nsCOMPtr barp = NS_NewPermanentAtom(NS_LITERAL_STRING("bar")); AssertString(barp, NS_LITERAL_CSTRING("bar")); AssertPermanence(barp, PR_TRUE); diff --git a/xpcom/tests/TestUTF.cpp b/xpcom/tests/TestUTF.cpp index 1b828ad0e5d4..8dfbbb535953 100644 --- a/xpcom/tests/TestUTF.cpp +++ b/xpcom/tests/TestUTF.cpp @@ -140,6 +140,32 @@ test_malformed8() return PR_TRUE; } +PRBool +test_hashas16() +{ + for (unsigned int i = 0; i < NS_ARRAY_LENGTH(ValidStrings); ++i) { + nsDependentCString str8(ValidStrings[i].m8); + if (nsCRT::HashCode(ValidStrings[i].m16) != + nsCRT::HashCodeAsUTF16(str8.get(), str8.Length())) + return PR_FALSE; + } + + for (unsigned int i = 0; i < NS_ARRAY_LENGTH(Invalid8Strings); ++i) { + nsDependentCString str8(Invalid8Strings[i].m8); + if (nsCRT::HashCode(Invalid8Strings[i].m16) != + nsCRT::HashCodeAsUTF16(str8.get(), str8.Length())) + return PR_FALSE; + } + + for (unsigned int i = 0; i < NS_ARRAY_LENGTH(Malformed8Strings); ++i) { + nsDependentCString str8(Malformed8Strings[i]); + if (nsCRT::HashCodeAsUTF16(str8.get(), str8.Length()) != 0) + return PR_FALSE; + } + + return PR_TRUE; +} + typedef PRBool (*TestFunc)(); static const struct Test @@ -156,6 +182,7 @@ tests[] = // Don't run this test in debug builds as that intentionally asserts { "test_malformed8", test_malformed8 }, #endif + { "test_hashas16", test_hashas16 }, { nsnull, nsnull } };