Bug 534136 Part 2: Use 16bit-char buffers inside atoms. r=bz sr=mrbkap

This commit is contained in:
Jonas Sicking 2010-03-08 07:45:00 -08:00
parent c24e5442a9
commit c7c7514f75
43 changed files with 361 additions and 352 deletions

View file

@ -1491,9 +1491,8 @@ nsAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
const nsAttrName *attr = content->GetAttrNameAt(count); const nsAttrName *attr = content->GetAttrNameAt(count);
if (attr && attr->NamespaceEquals(kNameSpaceID_None)) { if (attr && attr->NamespaceEquals(kNameSpaceID_None)) {
nsIAtom *attrAtom = attr->Atom(); nsIAtom *attrAtom = attr->Atom();
const char *attrStr; nsDependentAtomString attrStr(attrAtom);
attrAtom->GetUTF8String(&attrStr); if (!StringBeginsWith(attrStr, NS_LITERAL_STRING("aria-")))
if (PL_strncmp(attrStr, "aria-", 5))
continue; // Not ARIA continue; // Not ARIA
PRUint8 attrFlags = nsAccUtils::GetAttributeCharacteristics(attrAtom); PRUint8 attrFlags = nsAccUtils::GetAttributeCharacteristics(attrAtom);
if (attrFlags & ATTR_BYPASSOBJ) if (attrFlags & ATTR_BYPASSOBJ)
@ -1503,7 +1502,7 @@ nsAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
continue; // only expose token based attributes if they are defined continue; // only expose token based attributes if they are defined
nsAutoString value; nsAutoString value;
if (content->GetAttr(kNameSpaceID_None, attrAtom, value)) { if (content->GetAttr(kNameSpaceID_None, attrAtom, value)) {
attributes->SetStringProperty(nsDependentCString(attrStr + 5), value, oldValueUnused); attributes->SetStringProperty(NS_ConvertUTF16toUTF8(Substring(attrStr, 5)), value, oldValueUnused);
} }
} }
} }

View file

@ -1112,9 +1112,8 @@ nsDocAccessible::AttributeChangedImpl(nsIContent* aContent, PRInt32 aNameSpaceID
// Check for namespaced ARIA attribute // Check for namespaced ARIA attribute
if (aNameSpaceID == kNameSpaceID_None) { if (aNameSpaceID == kNameSpaceID_None) {
// Check for hyphenated aria-foo property? // Check for hyphenated aria-foo property?
const char* attributeName; if (StringBeginsWith(nsDependentAtomString(aAttribute),
aAttribute->GetUTF8String(&attributeName); NS_LITERAL_STRING("aria-"))) {
if (!PL_strncmp("aria-", attributeName, 5)) {
ARIAAttributeChanged(aContent, aAttribute); ARIAAttributeChanged(aContent, aAttribute);
} }
} }

View file

@ -249,12 +249,10 @@ __try{
for (PRUint32 index = 0; index < numAttribs; index++) { for (PRUint32 index = 0; index < numAttribs; index++) {
aNameSpaceIDs[index] = 0; aAttribValues[index] = aAttribNames[index] = nsnull; aNameSpaceIDs[index] = 0; aAttribValues[index] = aAttribNames[index] = nsnull;
nsAutoString attributeValue; nsAutoString attributeValue;
const char *pszAttributeName;
const nsAttrName* name = content->GetAttrNameAt(index); const nsAttrName* name = content->GetAttrNameAt(index);
aNameSpaceIDs[index] = static_cast<short>(name->NamespaceID()); aNameSpaceIDs[index] = static_cast<short>(name->NamespaceID());
name->LocalName()->GetUTF8String(&pszAttributeName); aAttribNames[index] = ::SysAllocString(name->LocalName()->GetUTF16String());
aAttribNames[index] = ::SysAllocString(NS_ConvertUTF8toUTF16(pszAttributeName).get());
content->GetAttr(name->NamespaceID(), name->LocalName(), attributeValue); content->GetAttr(name->NamespaceID(), name->LocalName(), attributeValue);
aAttribValues[index] = ::SysAllocString(attributeValue.get()); aAttribValues[index] = ::SysAllocString(attributeValue.get());
} }

View file

@ -1455,6 +1455,13 @@ public:
static JSContext *GetCurrentJSContext(); 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. * Convert ASCII A-Z to a-z.
*/ */

View file

@ -270,9 +270,7 @@ public:
if (!GetPrefixAtom()) if (!GetPrefixAtom())
return Equals(aNameAtom); return Equals(aNameAtom);
const char* utf8; return QualifiedNameEqualsInternal(nsAtomCString(aNameAtom));
aNameAtom->GetUTF8String(&utf8);
return QualifiedNameEqualsInternal(nsDependentCString(utf8));
} }
PRBool QualifiedNameEquals(const nsACString& aQualifiedName) const PRBool QualifiedNameEquals(const nsACString& aQualifiedName) const

View file

@ -510,7 +510,7 @@ nsAttrValue::HashValue() const
nsStringBuffer* str = static_cast<nsStringBuffer*>(GetPtr()); nsStringBuffer* str = static_cast<nsStringBuffer*>(GetPtr());
if (str) { if (str) {
PRUint32 len = str->StorageSize()/sizeof(PRUnichar) - 1; PRUint32 len = str->StorageSize()/sizeof(PRUnichar) - 1;
return nsCRT::BufferHashCode(static_cast<PRUnichar*>(str->Data()), len); return nsCRT::HashCode(static_cast<PRUnichar*>(str->Data()), len);
} }
return 0; return 0;
@ -776,11 +776,11 @@ nsAttrValue::Contains(nsIAtom* aValue, nsCaseTreatment aCaseSensitive) const
return aValue == atom; return aValue == atom;
} }
const char *val1, *val2; // For performance reasons, don't do a full on unicode case insensitive
aValue->GetUTF8String(&val1); // string comparison. This is only used for quirks mode anyway.
atom->GetUTF8String(&val2); return
nsContentUtils::EqualsIgnoreASCIICase(nsDependentAtomString(aValue),
return nsCRT::strcasecmp(val1, val2) == 0; nsDependentAtomString(atom));
} }
default: default:
{ {
@ -790,12 +790,14 @@ nsAttrValue::Contains(nsIAtom* aValue, nsCaseTreatment aCaseSensitive) const
return array->IndexOf(aValue) >= 0; return array->IndexOf(aValue) >= 0;
} }
const char *val1, *val2; nsDependentAtomString val1(aValue);
aValue->GetUTF8String(&val1);
for (PRInt32 i = 0, count = array->Count(); i < count; ++i) { for (PRInt32 i = 0, count = array->Count(); i < count; ++i) {
array->ObjectAt(i)->GetUTF8String(&val2); // For performance reasons, don't do a full on unicode case
if (nsCRT::strcasecmp(val1, val2) == 0) { // insensitive string comparison. This is only used for quirks mode
// anyway.
if (nsContentUtils::EqualsIgnoreASCIICase(val1,
nsDependentAtomString(array->ObjectAt(i)))) {
return PR_TRUE; return PR_TRUE;
} }
} }

View file

@ -532,9 +532,7 @@ nsContentSink::ProcessHeaderData(nsIAtom* aHeader, const nsAString& aValue,
if (NS_SUCCEEDED(mParser->GetChannel(getter_AddRefs(channel)))) { if (NS_SUCCEEDED(mParser->GetChannel(getter_AddRefs(channel)))) {
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel)); nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
if (httpChannel) { if (httpChannel) {
const char* header; httpChannel->SetResponseHeader(nsAtomCString(aHeader),
(void)aHeader->GetUTF8String(&header);
(void)httpChannel->SetResponseHeader(nsDependentCString(header),
NS_ConvertUTF16toUTF8(aValue), NS_ConvertUTF16toUTF8(aValue),
PR_TRUE); PR_TRUE);
} }

View file

@ -1897,10 +1897,7 @@ static inline void KeyAppendAtom(nsIAtom* aAtom, nsACString& aKey)
{ {
NS_PRECONDITION(aAtom, "KeyAppendAtom: aAtom can not be null!\n"); NS_PRECONDITION(aAtom, "KeyAppendAtom: aAtom can not be null!\n");
const char* atomString = nsnull; KeyAppendString(nsAtomCString(aAtom), aKey);
aAtom->GetUTF8String(&atomString);
KeyAppendString(nsDependentCString(atomString), aKey);
} }
static inline PRBool IsAutocompleteOff(nsIDOMElement* aElement) static inline PRBool IsAutocompleteOff(nsIDOMElement* aElement)
@ -3210,8 +3207,7 @@ nsAutoGCRoot::RemoveJSGCRoot(void* aPtr)
PRBool PRBool
nsContentUtils::IsEventAttributeName(nsIAtom* aName, PRInt32 aType) nsContentUtils::IsEventAttributeName(nsIAtom* aName, PRInt32 aType)
{ {
const char* name; const PRUnichar* name = aName->GetUTF16String();
aName->GetUTF8String(&name);
if (name[0] != 'o' || name[1] != 'n') if (name[0] != 'o' || name[1] != 'n')
return PR_FALSE; 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 */ /* static */
void void
nsAutoGCRoot::Shutdown() nsAutoGCRoot::Shutdown()

View file

@ -6718,9 +6718,7 @@ nsDocument::CreateElem(nsIAtom *aName, nsIAtom *aPrefix, PRInt32 aNamespaceID,
aPrefix->ToString(qName); aPrefix->ToString(qName);
qName.Append(':'); qName.Append(':');
} }
const char *name; qName.Append(nsAtomString(aName));
aName->GetUTF8String(&name);
AppendUTF8toUTF16(name, qName);
// Note: "a:b:c" is a valid name in non-namespaces XML, and // 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, // nsDocument::CreateElement can call us with such a name and no prefix,

View file

@ -69,8 +69,6 @@
#include "nsIScriptElement.h" #include "nsIScriptElement.h"
#include "nsAttrName.h" #include "nsAttrName.h"
static const char kMozStr[] = "moz";
static const PRInt32 kLongLineLen = 128; static const PRInt32 kLongLineLen = 128;
nsresult NS_NewHTMLContentSerializer(nsIContentSerializer** aSerializer) nsresult NS_NewHTMLContentSerializer(nsIContentSerializer** aSerializer)
@ -123,10 +121,9 @@ nsHTMLContentSerializer::SerializeHTMLAttributes(nsIContent* aContent,
nsIAtom* attrName = name->LocalName(); nsIAtom* attrName = name->LocalName();
// Filter out any attribute starting with [-|_]moz // Filter out any attribute starting with [-|_]moz
const char* sharedName; nsDependentAtomString attrNameStr(attrName);
attrName->GetUTF8String(&sharedName); if (StringBeginsWith(attrNameStr, NS_LITERAL_STRING("_moz")) ||
if ((('_' == *sharedName) || ('-' == *sharedName)) && StringBeginsWith(attrNameStr, NS_LITERAL_STRING("-moz"))) {
!nsCRT::strncmp(sharedName+1, kMozStr, PRUint32(sizeof(kMozStr)-1))) {
continue; continue;
} }
aContent->GetAttr(namespaceID, attrName, valueStr); aContent->GetAttr(namespaceID, attrName, valueStr);

View file

@ -257,16 +257,13 @@ nsNodeInfo::QualifiedNameEqualsInternal(const nsACString& aQualifiedName) const
nsACString::const_iterator colon(start); nsACString::const_iterator colon(start);
const char* prefix; nsAtomCString prefix(mInner.mPrefix);
mInner.mPrefix->GetUTF8String(&prefix);
PRUint32 len = strlen(prefix); if (prefix.Length() >= aQualifiedName.Length()) {
if (len >= aQualifiedName.Length()) {
return PR_FALSE; return PR_FALSE;
} }
colon.advance(len); colon.advance(prefix.Length());
// If the character at the prefix length index is not a colon, // If the character at the prefix length index is not a colon,
// aQualifiedName is not equal to this string. // 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 // 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; return PR_FALSE;
++colon; // Skip the ':' ++colon; // Skip the ':'

View file

@ -346,10 +346,9 @@ nsXHTMLContentSerializer::SerializeAttributes(nsIContent* aContent,
nsIAtom* attrPrefix = name->GetPrefix(); nsIAtom* attrPrefix = name->GetPrefix();
// Filter out any attribute starting with [-|_]moz // Filter out any attribute starting with [-|_]moz
const char* sharedName; nsDependentAtomString attrNameStr(attrName);
attrName->GetUTF8String(&sharedName); if (StringBeginsWith(attrNameStr, NS_LITERAL_STRING("_moz")) ||
if ((('_' == *sharedName) || ('-' == *sharedName)) && StringBeginsWith(attrNameStr, NS_LITERAL_STRING("-moz"))) {
!nsCRT::strncmp(sharedName+1, kMozStr, PRUint32(sizeof(kMozStr)-1))) {
continue; continue;
} }

View file

@ -942,13 +942,10 @@ SinkContext::CloseContainer(const nsHTMLTag aTag, PRBool aMalformed)
#ifdef NS_DEBUG #ifdef NS_DEBUG
{ {
// Tracing code // Tracing code
const char *tagStr;
mStack[mStackPos].mContent->Tag()->GetUTF8String(&tagStr);
SINK_TRACE(gSinkLogModuleInfo, SINK_TRACE_REFLOW, SINK_TRACE(gSinkLogModuleInfo, SINK_TRACE_REFLOW,
("SinkContext::CloseContainer: reflow on notifyImmediate " ("SinkContext::CloseContainer: reflow on notifyImmediate "
"tag=%s newIndex=%d stackPos=%d", "tag=%s newIndex=%d stackPos=%d",
tagStr, nsAtomCString(mStack[mStackPos].mContent->Tag()).get(),
mStack[mStackPos].mNumFlushed, mStackPos)); mStack[mStackPos].mNumFlushed, mStackPos));
} }
#endif #endif
@ -1353,12 +1350,10 @@ SinkContext::FlushTags()
#ifdef NS_DEBUG #ifdef NS_DEBUG
{ {
// Tracing code // Tracing code
const char* tagStr;
mStack[stackPos].mContent->Tag()->GetUTF8String(&tagStr);
SINK_TRACE(gSinkLogModuleInfo, SINK_TRACE_REFLOW, SINK_TRACE(gSinkLogModuleInfo, SINK_TRACE_REFLOW,
("SinkContext::FlushTags: tag=%s from newindex=%d at " ("SinkContext::FlushTags: tag=%s from newindex=%d at "
"stackPos=%d", tagStr, "stackPos=%d",
nsAtomCString(mStack[stackPos].mContent->Tag()).get(),
mStack[stackPos].mNumFlushed, stackPos)); mStack[stackPos].mNumFlushed, stackPos));
} }
#endif #endif

View file

@ -51,10 +51,8 @@ nsSMILCompositor::KeyEquals(KeyTypePointer aKey) const
nsSMILCompositor::HashKey(KeyTypePointer aKey) nsSMILCompositor::HashKey(KeyTypePointer aKey)
{ {
// Combine the 3 values into one numeric value, which will be hashed // Combine the 3 values into one numeric value, which will be hashed
const char *attrName = nsnull; return NS_PTR_TO_UINT32(aKey->mElement.get()) >> 4 +
aKey->mAttributeName->GetUTF8String(&attrName); NS_PTR_TO_INT32(aKey->mAttributeName.get()) +
return NS_PTR_TO_UINT32(aKey->mElement.get()) +
HashString(attrName) +
(aKey->mIsCSS ? 1 : 0); (aKey->mIsCSS ? 1 : 0);
} }

View file

@ -49,10 +49,7 @@
inline PRBool inline PRBool
TX_StringEqualsAtom(const nsASingleFragmentString& aString, nsIAtom* aAtom) TX_StringEqualsAtom(const nsASingleFragmentString& aString, nsIAtom* aAtom)
{ {
const char* ASCIIAtom; return aAtom->Equals(aString);
aAtom->GetUTF8String(&ASCIIAtom);
return aString.EqualsASCII(ASCIIAtom);
} }
#ifndef TX_EXE #ifndef TX_EXE

View file

@ -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 // foo-bar becomes fooBar). Note that if there are any names that already
// have uppercase letters they might cause false matches (both fooBar and // have uppercase letters they might cause false matches (both fooBar and
// foo-bar matching fooBar). // foo-bar matching fooBar).
const char *name; const PRUnichar *name = aName->GetUTF16String();
aName->GetUTF8String(&name);
nsCAutoString methodName; nsCAutoString methodName;
char letter; PRUnichar letter;
PRBool upperNext = PR_FALSE; PRBool upperNext = PR_FALSE;
while ((letter = *name)) { while ((letter = *name)) {
if (letter == '-') { if (letter == '-') {

View file

@ -1408,20 +1408,17 @@ nsXULDocument::Persist(nsIContent* aElement, PRInt32 aNameSpaceID,
// Ick. Construct a property from the attribute. Punt on // Ick. Construct a property from the attribute. Punt on
// namespaces for now. // 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, // Don't bother with unreasonable attributes. We clamp long values,
// but truncating attribute names turns it into a different attribute // but truncating attribute names turns it into a different attribute
// so there's no point in persisting anything at all // 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"); NS_WARNING("Can't persist, Attribute name too long");
return NS_ERROR_ILLEGAL_VALUE; return NS_ERROR_ILLEGAL_VALUE;
} }
nsCOMPtr<nsIRDFResource> attr; nsCOMPtr<nsIRDFResource> attr;
rv = gRDFService->GetResource(nsDependentCString(attrstr), rv = gRDFService->GetResource(attrstr,
getter_AddRefs(attr)); getter_AddRefs(attr));
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;

View file

@ -483,17 +483,14 @@ nsXULContentBuilder::BuildContentFromTemplate(nsIContent *aTemplateNode,
("nsXULContentBuilder::BuildContentFromTemplate (is unique: %d)", ("nsXULContentBuilder::BuildContentFromTemplate (is unique: %d)",
aIsUnique)); aIsUnique));
const char *tmpln, *resn, *realn;
aTemplateNode->Tag()->GetUTF8String(&tmpln);
aResourceNode->Tag()->GetUTF8String(&resn);
aRealNode->Tag()->GetUTF8String(&realn);
nsAutoString id; nsAutoString id;
aChild->GetId(id); aChild->GetId(id);
PR_LOG(gXULTemplateLog, PR_LOG_ALWAYS, PR_LOG(gXULTemplateLog, PR_LOG_ALWAYS,
("Tags: [Template: %s Resource: %s Real: %s] for id %s", ("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 #endif
@ -562,11 +559,9 @@ nsXULContentBuilder::BuildContentFromTemplate(nsIContent *aTemplateNode,
#ifdef PR_LOGGING #ifdef PR_LOGGING
if (PR_LOG_TEST(gXULTemplateLog, PR_LOG_DEBUG)) { if (PR_LOG_TEST(gXULTemplateLog, PR_LOG_DEBUG)) {
const char *tagname;
tag->GetUTF8String(&tagname);
PR_LOG(gXULTemplateLog, PR_LOG_DEBUG, PR_LOG(gXULTemplateLog, PR_LOG_DEBUG,
("xultemplate[%p] building %s %s %s", ("xultemplate[%p] building %s %s %s",
this, tagname, this, nsAtomCString(tag).get(),
(isGenerationElement ? "[resource]" : ""), (isGenerationElement ? "[resource]" : ""),
(isUnique ? "[unique]" : ""))); (isUnique ? "[unique]" : "")));
} }

View file

@ -1927,26 +1927,24 @@ nsJSContext::ExecuteScript(void *aScriptObject,
} }
static inline const char *
AtomToEventHandlerName(nsIAtom *aName)
{
const char *name;
aName->GetUTF8String(&name);
#ifdef DEBUG #ifdef DEBUG
const char *cp; PRBool
char c; AtomIsEventHandlerName(nsIAtom *aName)
{
const PRUnichar *name = aName->GetUTF16String();
const PRUnichar *cp;
PRUnichar c;
for (cp = name; *cp != '\0'; ++cp) for (cp = name; *cp != '\0'; ++cp)
{ {
c = *cp; c = *cp;
NS_ASSERTION (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z'), if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z'))
"non-ASCII non-alphabetic event handler name"); return PR_FALSE;
} }
#endif
return name; return PR_TRUE;
} }
#endif
// Helper function to find the JSObject associated with a (presumably DOM) // Helper function to find the JSObject associated with a (presumably DOM)
// interface. // interface.
@ -1992,6 +1990,7 @@ nsJSContext::CompileEventHandler(nsIAtom *aName,
{ {
NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED); NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
NS_PRECONDITION(AtomIsEventHandlerName(aName), "Bad event name");
NS_PRECONDITION(!::JS_IsExceptionPending(mContext), NS_PRECONDITION(!::JS_IsExceptionPending(mContext),
"Why are we being called with a pending exception?"); "Why are we being called with a pending exception?");
@ -2008,8 +2007,6 @@ nsJSContext::CompileEventHandler(nsIAtom *aName,
return NS_ERROR_ILLEGAL_VALUE; return NS_ERROR_ILLEGAL_VALUE;
} }
const char *charName = AtomToEventHandlerName(aName);
#ifdef DEBUG #ifdef DEBUG
JSContext* top = nsContentUtils::GetCurrentJSContext(); JSContext* top = nsContentUtils::GetCurrentJSContext();
NS_ASSERTION(mContext == top, "Context not properly pushed!"); NS_ASSERTION(mContext == top, "Context not properly pushed!");
@ -2024,7 +2021,7 @@ nsJSContext::CompileEventHandler(nsIAtom *aName,
JSFunction* fun = JSFunction* fun =
::JS_CompileUCFunctionForPrincipals(mContext, ::JS_CompileUCFunctionForPrincipals(mContext,
nsnull, nsnull, nsnull, nsnull,
charName, aArgCount, aArgNames, nsAtomCString(aName).get(), aArgCount, aArgNames,
(jschar*)PromiseFlatString(aBody).get(), (jschar*)PromiseFlatString(aBody).get(),
aBody.Length(), aBody.Length(),
aURL, aLineNo); aURL, aLineNo);
@ -2206,7 +2203,7 @@ nsJSContext::BindCompiledEventHandler(nsISupports* aTarget, void *aScope,
NS_ENSURE_ARG(aHandler); NS_ENSURE_ARG(aHandler);
NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED); NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_NOT_INITIALIZED);
const char *charName = AtomToEventHandlerName(aName); NS_PRECONDITION(AtomIsEventHandlerName(aName), "Bad event name");
nsresult rv; nsresult rv;
// Get the jsobject associated with this target // Get the jsobject associated with this target
@ -2240,7 +2237,7 @@ nsJSContext::BindCompiledEventHandler(nsISupports* aTarget, void *aScope,
if (NS_SUCCEEDED(rv) && if (NS_SUCCEEDED(rv) &&
// Make sure the flags here match those in nsEventReceiverSH::NewResolve // 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, OBJECT_TO_JSVAL(funobj), nsnull, nsnull,
JSPROP_ENUMERATE | JSPROP_PERMANENT)) { JSPROP_ENUMERATE | JSPROP_PERMANENT)) {
ReportPendingException(); ReportPendingException();
@ -2262,6 +2259,8 @@ nsJSContext::GetBoundEventHandler(nsISupports* aTarget, void *aScope,
nsIAtom* aName, nsIAtom* aName,
nsScriptObjectHolder &aHandler) nsScriptObjectHolder &aHandler)
{ {
NS_PRECONDITION(AtomIsEventHandlerName(aName), "Bad event name");
nsresult rv; nsresult rv;
JSObject *obj = nsnull; JSObject *obj = nsnull;
nsAutoGCRoot root(&obj, &rv); nsAutoGCRoot root(&obj, &rv);
@ -2270,11 +2269,9 @@ nsJSContext::GetBoundEventHandler(nsISupports* aTarget, void *aScope,
rv = JSObjectFromInterface(aTarget, aScope, &obj); rv = JSObjectFromInterface(aTarget, aScope, &obj);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
const char *charName = AtomToEventHandlerName(aName);
jsval funval; jsval funval;
if (!JS_LookupProperty(mContext, obj, if (!JS_LookupProperty(mContext, obj,
charName, &funval)) nsAtomCString(aName).get(), &funval))
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
if (JS_TypeOfValue(mContext, funval) != JSTYPE_FUNCTION) { if (JS_TypeOfValue(mContext, funval) != JSTYPE_FUNCTION) {

View file

@ -1860,9 +1860,7 @@ gfxWindowsFontGroup::WhichPrefFontSupportsChar(PRUint32 aCh)
nsIAtom *langGroup = LangGroupFromUnicodeRange(unicodeRange); nsIAtom *langGroup = LangGroupFromUnicodeRange(unicodeRange);
if (langGroup) { if (langGroup) {
#ifdef PR_LOGGING #ifdef PR_LOGGING
const char *langGroupStr; PR_LOG(gFontLog, PR_LOG_DEBUG, (" - Trying to find fonts for: %s", nsAtomCString(langGroup).get()));
langGroup->GetUTF8String(&langGroupStr);
PR_LOG(gFontLog, PR_LOG_DEBUG, (" - Trying to find fonts for: %s", langGroupStr));
#endif #endif
nsAutoTArray<nsRefPtr<gfxFontEntry>, 5> fonts; nsAutoTArray<nsRefPtr<gfxFontEntry>, 5> fonts;
this->GetPrefFonts(langGroup, fonts); this->GetPrefFonts(langGroup, fonts);

View file

@ -109,7 +109,7 @@ SetupTests()
NS_FONT_STRETCH_NORMAL, NS_FONT_STRETCH_NORMAL,
400, 400,
16.0, 16.0,
NS_NewPermanentAtom(NS_LITERAL_CSTRING("en")), NS_NewPermanentAtom(NS_LITERAL_STRING("en")),
0.0, 0.0,
PR_FALSE, PR_FALSE, PR_FALSE); PR_FALSE, PR_FALSE, PR_FALSE);
@ -117,7 +117,7 @@ SetupTests()
NS_FONT_STRETCH_NORMAL, NS_FONT_STRETCH_NORMAL,
700, 700,
16.0, 16.0,
NS_NewPermanentAtom(NS_LITERAL_CSTRING("en")), NS_NewPermanentAtom(NS_LITERAL_STRING("en")),
0.0, 0.0,
PR_FALSE, PR_FALSE, PR_FALSE); PR_FALSE, PR_FALSE, PR_FALSE);

View file

@ -93,7 +93,7 @@ RunTest (TestEntry *test, gfxContext *ctx) {
NS_FONT_STRETCH_NORMAL, NS_FONT_STRETCH_NORMAL,
400, 400,
16.0, 16.0,
NS_NewPermanentAtom(NS_LITERAL_CSTRING("en")), NS_NewPermanentAtom(NS_LITERAL_STRING("en")),
0.0, 0.0,
PR_FALSE, PR_FALSE, PR_FALSE); PR_FALSE, PR_FALSE, PR_FALSE);

View file

@ -159,7 +159,7 @@ main (int argc, char **argv) {
NS_FONT_STRETCH_NORMAL, NS_FONT_STRETCH_NORMAL,
139, 139,
10.0, 10.0,
NS_NewPermanentAtom(NS_LITERAL_CSTRING("en")), NS_NewPermanentAtom(NS_LITERAL_STRING("en")),
0.0, 0.0,
PR_FALSE, PR_FALSE, PR_FALSE); PR_FALSE, PR_FALSE, PR_FALSE);

View file

@ -431,13 +431,19 @@ nsPresContext::GetFontPreferences()
mDefaultFixedFont.size = CSSPixelsToAppUnits(13); mDefaultFixedFont.size = CSSPixelsToAppUnits(13);
// the font prefs are based on langGroup, not actual language // 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) { if (mLanguage && mLangService) {
nsresult rv; nsresult rv;
nsIAtom *group = mLangService->GetLanguageGroup(mLanguage, &rv); nsIAtom *group = mLangService->GetLanguageGroup(mLanguage, &rv);
if (NS_SUCCEEDED(rv) && group) { 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; nsCAutoString pref;

View file

@ -6734,11 +6734,13 @@ static void
GetTagName(nsFrame* aFrame, nsIContent* aContent, PRIntn aResultSize, GetTagName(nsFrame* aFrame, nsIContent* aContent, PRIntn aResultSize,
char* aResult) char* aResult)
{ {
const char *nameStr = "";
if (aContent) { 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 void

View file

@ -4881,9 +4881,8 @@ nsTypedSelection::Collapse(nsINode* aParentNode, PRInt32 aOffset)
if (!content) if (!content)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
const char *tagString; printf ("Sel. Collapse to %p %s %d\n", content.get(),
content->Tag()->GetUTF8String(&tagString); nsAtomCString(content->Tag()).get(), aOffset);
printf ("Sel. Collapse to %p %s %d\n", content.get(), tagString, aOffset);
} }
else { else {
printf ("Sel. Collapse set to null parent.\n"); printf ("Sel. Collapse set to null parent.\n");
@ -5274,9 +5273,8 @@ nsTypedSelection::Extend(nsINode* aParentNode, PRInt32 aOffset)
nsCOMPtr<nsIContent>content; nsCOMPtr<nsIContent>content;
content = do_QueryInterface(aParentNode); content = do_QueryInterface(aParentNode);
const char *tagString; printf ("Sel. Extend to %p %s %d\n", content.get(),
content->Tag()->GetUTF8String(&tagString); nsAtomCString(content->Tag()).get(), aOffset);
printf ("Sel. Extend to %p %s %d\n", content.get(), tagString, aOffset);
} }
else { else {
printf ("Sel. Extend set to null parent.\n"); printf ("Sel. Extend set to null parent.\n");

View file

@ -2164,10 +2164,10 @@ static PRBool IsChineseOrJapanese(nsIFrame* aFrame)
if (!language) { if (!language) {
return PR_FALSE; return PR_FALSE;
} }
const char *lang; const PRUnichar *lang = language->GetUTF16String();
language->GetUTF8String(&lang); return (!nsCRT::strncmp(lang, NS_LITERAL_STRING("ja").get(), 2) ||
return (!strncmp(lang, "ja", 2) || !strncmp(lang, "zh", 2)) && !nsCRT::strncmp(lang, NS_LITERAL_STRING("zh").get(), 2)) &&
(lang[2] == '\0' || lang[2] == '-'); (language->GetLength() == 2 || lang[2] == '-');
} }
#ifdef DEBUG #ifdef DEBUG

View file

@ -78,9 +78,7 @@ PRBool nsCSSAnonBoxes::IsAnonBox(nsIAtom *aAtom)
/* static */ PRBool /* static */ PRBool
nsCSSAnonBoxes::IsTreePseudoElement(nsIAtom* aPseudo) nsCSSAnonBoxes::IsTreePseudoElement(nsIAtom* aPseudo)
{ {
const char* str; return StringBeginsWith(nsDependentAtomString(aPseudo),
aPseudo->GetUTF8String(&str); NS_LITERAL_STRING(":-moz-tree-"));
static const char moz_tree[] = ":-moz-tree-";
return nsCRT::strncmp(str, moz_tree, PRInt32(sizeof(moz_tree)-1)) == 0;
} }
#endif #endif

View file

@ -196,11 +196,13 @@ RuleHash_CIMatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
if (match_atom == entry_atom) if (match_atom == entry_atom)
return PR_TRUE; return PR_TRUE;
const char *match_str, *entry_str; // Use EqualsIgnoreASCIICase instead of full on unicode case conversion
match_atom->GetUTF8String(&match_str); // in order to save on performance. This is only used in quirks mode
entry_atom->GetUTF8String(&entry_str); // anyway.
return (nsCRT::strcasecmp(entry_str, match_str) == 0); return
nsContentUtils::EqualsIgnoreASCIICase(nsDependentAtomString(entry_atom),
nsDependentAtomString(match_atom));
} }
static PRBool static PRBool
@ -1834,13 +1836,13 @@ static PRBool SelectorMatches(RuleProcessorData &data,
IDList = IDList->mNext; IDList = IDList->mNext;
} while (IDList); } while (IDList);
} else { } else {
const char* id1Str; // Use EqualsIgnoreASCIICase instead of full on unicode case conversion
data.mContentID->GetUTF8String(&id1Str); // in order to save on performance. This is only used in quirks mode
nsDependentCString id1(id1Str); // anyway.
nsDependentAtomString id1Str(data.mContentID);
do { do {
const char* id2Str; if (!nsContentUtils::EqualsIgnoreASCIICase(id1Str,
IDList->mAtom->GetUTF8String(&id2Str); nsDependentAtomString(IDList->mAtom))) {
if (!id1.Equals(id2Str, nsCaseInsensitiveCStringComparator())) {
return PR_FALSE; return PR_FALSE;
} }
IDList = IDList->mNext; IDList = IDList->mNext;

View file

@ -4294,10 +4294,9 @@ nsComputedDOMStyle::GetTransitionProperty(nsIDOMCSSValue** aValue)
property->SetIdent(eCSSKeyword_none); property->SetIdent(eCSSKeyword_none);
else if (cssprop == eCSSProperty_UNKNOWN) else if (cssprop == eCSSProperty_UNKNOWN)
{ {
const char *str;
transition->GetUnknownProperty()->GetUTF8String(&str);
nsAutoString escaped; nsAutoString escaped;
nsStyleUtil::AppendEscapedCSSIdent(NS_ConvertUTF8toUTF16(str), escaped); nsStyleUtil::AppendEscapedCSSIdent(
nsDependentAtomString(transition->GetUnknownProperty()), escaped);
property->SetString(escaped); // really want SetIdent property->SetString(escaped); // really want SetIdent
} }
else else

View file

@ -82,9 +82,16 @@ nsHtml5Atom::ToUTF8String(nsACString& aReturn)
} }
NS_IMETHODIMP 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; return NS_ERROR_NOT_IMPLEMENTED;
} }

View file

@ -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... // let's verify that all names in the the table are lowercase...
for (i = 0; i < NS_HTML_TAG_MAX; ++i) { for (i = 0; i < NS_HTML_TAG_MAX; ++i) {
nsCAutoString temp1((char*)sTagAtoms_info[i].mStringBuffer->Data()); nsAutoString temp1((PRUnichar*)sTagAtoms_info[i].mStringBuffer->Data());
nsCAutoString temp2((char*)sTagAtoms_info[i].mStringBuffer->Data()); nsAutoString temp2((PRUnichar*)sTagAtoms_info[i].mStringBuffer->Data());
ToLowerCase(temp1); ToLowerCase(temp1);
NS_ASSERTION(temp1.Equals(temp2), "upper case char in table"); NS_ASSERTION(temp1.Equals(temp2), "upper case char in table");
} }
@ -382,7 +382,7 @@ nsHTMLTags::AddRefTable(void)
// correct. // correct.
for (i = 0; i < NS_HTML_TAG_MAX; ++i) { for (i = 0; i < NS_HTML_TAG_MAX; ++i) {
nsAutoString temp1(sTagUnicodeTable[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!"); NS_ASSERTION(temp1.Equals(temp2), "Bad unicode tag name!");
} }

View file

@ -1026,11 +1026,8 @@ RDFContentSinkImpl::AddProperties(const PRUnichar** aAttributes,
} }
} }
const char* attrName;
localName->GetUTF8String(&attrName);
NS_ConvertUTF16toUTF8 propertyStr(nameSpaceURI); NS_ConvertUTF16toUTF8 propertyStr(nameSpaceURI);
propertyStr.Append(attrName); propertyStr.Append(nsAtomCString(localName));
// Add the assertion to RDF // Add the assertion to RDF
nsCOMPtr<nsIRDFResource> property; nsCOMPtr<nsIRDFResource> property;
@ -1158,11 +1155,8 @@ RDFContentSinkImpl::OpenObject(const PRUnichar* aName,
} }
if (isaTypedNode) { if (isaTypedNode) {
const char* attrName;
localName->GetUTF8String(&attrName);
NS_ConvertUTF16toUTF8 typeStr(nameSpaceURI); NS_ConvertUTF16toUTF8 typeStr(nameSpaceURI);
typeStr.Append(attrName); typeStr.Append(nsAtomCString(localName));
nsCOMPtr<nsIRDFResource> type; nsCOMPtr<nsIRDFResource> type;
nsresult rv = gRDFService->GetResource(typeStr, getter_AddRefs(type)); nsresult rv = gRDFService->GetResource(typeStr, getter_AddRefs(type));
@ -1190,11 +1184,8 @@ RDFContentSinkImpl::OpenProperty(const PRUnichar* aName, const PRUnichar** aAttr
const nsDependentSubstring& nameSpaceURI = const nsDependentSubstring& nameSpaceURI =
SplitExpatName(aName, getter_AddRefs(localName)); SplitExpatName(aName, getter_AddRefs(localName));
const char* attrName;
localName->GetUTF8String(&attrName);
NS_ConvertUTF16toUTF8 propertyStr(nameSpaceURI); NS_ConvertUTF16toUTF8 propertyStr(nameSpaceURI);
propertyStr.Append(attrName); propertyStr.Append(nsAtomCString(localName));
nsCOMPtr<nsIRDFResource> property; nsCOMPtr<nsIRDFResource> property;
rv = gRDFService->GetResource(propertyStr, getter_AddRefs(property)); rv = gRDFService->GetResource(propertyStr, getter_AddRefs(property));

View file

@ -59,7 +59,7 @@ nsAtomService::GetAtom(const nsAString& aString, nsIAtom ** aResult)
nsresult nsresult
nsAtomService::GetPermanentAtom(const nsAString& aString, nsIAtom ** aResult) nsAtomService::GetPermanentAtom(const nsAString& aString, nsIAtom ** aResult)
{ {
*aResult = NS_NewPermanentAtom(NS_ConvertUTF16toUTF8(aString)); *aResult = NS_NewPermanentAtom(aString);
if (!*aResult) if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
@ -81,7 +81,7 @@ nsAtomService::GetAtomUTF8(const char *aValue, nsIAtom* *aResult)
NS_IMETHODIMP NS_IMETHODIMP
nsAtomService::GetPermanentAtomUTF8(const char *aValue, nsIAtom* *aResult) nsAtomService::GetPermanentAtomUTF8(const char *aValue, nsIAtom* *aResult)
{ {
*aResult = NS_NewPermanentAtom(nsDependentCString(aValue)); *aResult = NS_NewPermanentAtom(NS_ConvertUTF8toUTF16(aValue));
if (!*aResult) if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;

View file

@ -153,7 +153,7 @@ struct AtomTableEntry : public PLDHashEntryHdr {
// type-agnostic accessors // type-agnostic accessors
// get the string buffer // get the string buffer
inline const char* getAtomString() const { inline const PRUnichar* getAtomString() const {
NS_ASSERTION(keyHash > 1, NS_ASSERTION(keyHash > 1,
"getAtomString() called on non-atom AtomTableEntry!"); "getAtomString() called on non-atom AtomTableEntry!");
@ -200,14 +200,14 @@ AtomTableGetHash(PLDHashTable *table, const void *key)
{ {
const AtomTableEntry *e = static_cast<const AtomTableEntry*>(key); const AtomTableEntry *e = static_cast<const AtomTableEntry*>(key);
if (e->IsUTF16String()) { if (e->IsUTF8String()) {
return nsCRT::HashCodeAsUTF8(e->getUTF16String(), e->getLength());; return nsCRT::HashCodeAsUTF16(e->getUTF8String(), e->getLength());;
} }
NS_ASSERTION(e->IsUTF8String(), NS_ASSERTION(e->IsUTF16String(),
"AtomTableGetHash() called on non-string-key AtomTableEntry!"); "AtomTableGetHash() called on non-string-key AtomTableEntry!");
return nsCRT::HashCode(e->getUTF8String(), e->getLength()); return nsCRT::HashCode(e->getUTF16String(), e->getLength());
} }
static PRBool static PRBool
@ -217,13 +217,13 @@ AtomTableMatchKey(PLDHashTable *table, const PLDHashEntryHdr *entry,
const AtomTableEntry *he = static_cast<const AtomTableEntry*>(entry); const AtomTableEntry *he = static_cast<const AtomTableEntry*>(entry);
const AtomTableEntry *strKey = static_cast<const AtomTableEntry*>(key); const AtomTableEntry *strKey = static_cast<const AtomTableEntry*>(key);
const char *atomString = he->getAtomString(); const PRUnichar *atomString = he->getAtomString();
if (strKey->IsUTF16String()) { if (strKey->IsUTF8String()) {
return return
CompareUTF8toUTF16(nsDependentCSubstring(atomString, atomString + he->getLength()), CompareUTF8toUTF16(nsDependentCSubstring(strKey->getUTF8String(),
nsDependentSubstring(strKey->getUTF16String(), strKey->getUTF8String() + strKey->getLength()),
strKey->getUTF16String() + strKey->getLength())) == 0; nsDependentSubstring(atomString, atomString + he->getLength())) == 0;
} }
PRUint32 length = he->getLength(); PRUint32 length = he->getLength();
@ -231,15 +231,15 @@ AtomTableMatchKey(PLDHashTable *table, const PLDHashEntryHdr *entry,
return PR_FALSE; return PR_FALSE;
} }
const char *str; const PRUnichar *str;
if (strKey->IsUTF8String()) { if (strKey->IsUTF16String()) {
str = strKey->getUTF8String(); str = strKey->getUTF16String();
} else { } else {
str = strKey->getAtomString(); str = strKey->getAtomString();
} }
return memcmp(atomString, str, length * sizeof(char)) == 0; return memcmp(atomString, str, length * sizeof(PRUnichar)) == 0;
} }
static void static void
@ -298,9 +298,9 @@ DumpAtomLeaks(PLDHashTable *table, PLDHashEntryHdr *he,
AtomImpl* atom = entry->GetAtomImpl(); AtomImpl* atom = entry->GetAtomImpl();
if (!atom->IsPermanent()) { if (!atom->IsPermanent()) {
++*static_cast<PRUint32*>(arg); ++*static_cast<PRUint32*>(arg);
const char *str; nsCAutoString str;
atom->GetUTF8String(&str); atom->ToUTF8String(str);
fputs(str, stdout); fputs(str.get(), stdout);
fputs("\n", stdout); fputs("\n", stdout);
} }
return PL_DHASH_NEXT; return PL_DHASH_NEXT;
@ -343,25 +343,25 @@ NS_PurgeAtomTable()
} }
} }
AtomImpl::AtomImpl(const nsACString& aString) AtomImpl::AtomImpl(const nsAString& aString)
: mLength(aString.Length()) : mLength(aString.Length())
{ {
nsStringBuffer* buf = nsStringBuffer::FromString(aString); nsStringBuffer* buf = nsStringBuffer::FromString(aString);
if (buf) { if (buf) {
buf->AddRef(); buf->AddRef();
mString = static_cast<char*>(buf->Data()); mString = static_cast<PRUnichar*>(buf->Data());
} }
else { else {
buf = nsStringBuffer::Alloc((mLength + 1) * sizeof(char)); buf = nsStringBuffer::Alloc((mLength + 1) * sizeof(PRUnichar));
mString = static_cast<char*>(buf->Data()); mString = static_cast<PRUnichar*>(buf->Data());
memcpy(mString, aString.BeginReading(), mLength * sizeof(char)); CopyUnicodeTo(aString, 0, mString, mLength);
mString[mLength] = PRUnichar(0); mString[mLength] = PRUnichar(0);
} }
} }
AtomImpl::AtomImpl(nsStringBuffer* aStringBuffer, PRUint32 aLength) AtomImpl::AtomImpl(nsStringBuffer* aStringBuffer, PRUint32 aLength)
: mLength(aLength), : mLength(aLength),
mString(static_cast<char*>(aStringBuffer->Data())) mString(static_cast<PRUnichar*>(aStringBuffer->Data()))
{ {
// Technically we could currently avoid doing this addref by instead making // Technically we could currently avoid doing this addref by instead making
// the static atom buffers have an initial refcount of 2. // 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 NS_IMETHODIMP
AtomImpl::ToString(nsAString& aBuf) AtomImpl::ToString(nsAString& aBuf)
{ {
CopyUTF8toUTF16(nsDependentCString(mString, mLength), aBuf); nsStringBuffer::FromData(mString)->ToString(mLength, aBuf);
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
AtomImpl::ToUTF8String(nsACString& aBuf) AtomImpl::ToUTF8String(nsACString& aBuf)
{ {
nsStringBuffer::FromData(mString)->ToString(mLength, aBuf); CopyUTF16toUTF8(nsDependentString(mString, mLength), aBuf);
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
AtomImpl::GetUTF8String(const char **aResult) AtomImpl::GetUTF16String(const PRUnichar **aResult)
{ {
NS_PRECONDITION(aResult, "null out param"); NS_PRECONDITION(aResult, "null out param");
*aResult = mString; *aResult = mString;
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP_(PRUint32)
AtomImpl::GetLength()
{
return mLength;
}
NS_IMETHODIMP NS_IMETHODIMP
AtomImpl::EqualsUTF8(const nsACString& aString, PRBool* aResult) AtomImpl::EqualsUTF8(const nsACString& aString, PRBool* aResult)
{ {
*aResult = aString.Equals(nsDependentCString(mString, mLength)); *aResult = CompareUTF8toUTF16(aString,
nsDependentString(mString, mLength)) == 0;
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
AtomImpl::Equals(const nsAString& aString, PRBool* aResult) AtomImpl::Equals(const nsAString& aString, PRBool* aResult)
{ {
*aResult = CompareUTF8toUTF16(nsDependentCString(mString, mLength), *aResult = aString.Equals(nsDependentString(mString, mLength));
aString) == 0;
return NS_OK; return NS_OK;
} }
@ -540,14 +546,15 @@ NS_RegisterStaticAtoms(const nsStaticAtom* aAtoms, PRUint32 aAtomCount)
} }
for (PRUint32 i=0; i<aAtomCount; i++) { for (PRUint32 i=0; i<aAtomCount; i++) {
NS_ASSERTION(nsCRT::IsAscii((char*)aAtoms[i].mStringBuffer->Data()), #ifdef NS_STATIC_ATOM_USE_WIDE_STRINGS
NS_ASSERTION(nsCRT::IsAscii((PRUnichar*)aAtoms[i].mStringBuffer->Data()),
"Static atoms must be ASCII!"); "Static atoms must be ASCII!");
PRUint32 stringLen = PRUint32 stringLen =
aAtoms[i].mStringBuffer->StorageSize() / sizeof(char) - 1; aAtoms[i].mStringBuffer->StorageSize() / sizeof(PRUnichar) - 1;
AtomTableEntry *he = AtomTableEntry *he =
GetAtomHashEntry((char*)aAtoms[i].mStringBuffer->Data(), GetAtomHashEntry((PRUnichar*)aAtoms[i].mStringBuffer->Data(),
stringLen); stringLen);
if (he->HasValue()) { if (he->HasValue()) {
@ -569,11 +576,25 @@ NS_RegisterStaticAtoms(const nsStaticAtom* aAtoms, PRUint32 aAtomCount)
*aAtoms[i].mAtom = atom; *aAtoms[i].mAtom = atom;
if (!gStaticAtomTableSealed) { if (!gStaticAtomTableSealed) {
nsAutoString key; gStaticAtomTable->Put(nsAtomString(atom), atom);
atom->ToString(key);
gStaticAtomTable->Put(key, 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; return NS_OK;
} }
@ -594,13 +615,15 @@ NS_NewAtom(const nsACString& aUTF8String)
return nsnull; return nsnull;
} }
NS_ASSERTION(!he->IsUTF8String() && !he->IsUTF16String(),
"Atom hash entry is string? Should be atom!");
if (he->HasValue()) if (he->HasValue())
return he->GetAtom(); 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); he->SetAtomImpl(atom);
NS_ADDREF(atom); NS_ADDREF(atom);
@ -622,12 +645,7 @@ NS_NewAtom(const nsAString& aUTF16String)
if (he->HasValue()) if (he->HasValue())
return he->GetAtom(); return he->GetAtom();
// This results in an extra addref/release of the nsStringBuffer. AtomImpl* atom = new AtomImpl(aUTF16String);
// Unfortunately there doesn't seem to be any APIs to avoid that.
nsCString str;
CopyUTF16toUTF8(aUTF16String, str);
AtomImpl* atom = new AtomImpl(str);
he->SetAtomImpl(atom); he->SetAtomImpl(atom);
NS_ADDREF(atom); NS_ADDREF(atom);
@ -635,10 +653,10 @@ NS_NewAtom(const nsAString& aUTF16String)
} }
NS_COM nsIAtom* NS_COM nsIAtom*
NS_NewPermanentAtom(const nsACString& aUTF8String) NS_NewPermanentAtom(const nsAString& aUTF16String)
{ {
AtomTableEntry *he = GetAtomHashEntry(aUTF8String.Data(), AtomTableEntry *he = GetAtomHashEntry(aUTF16String.Data(),
aUTF8String.Length()); aUTF16String.Length());
if (he->HasValue()) { if (he->HasValue()) {
AtomImpl* atom = he->GetAtomImpl(); AtomImpl* atom = he->GetAtomImpl();
@ -648,7 +666,7 @@ NS_NewPermanentAtom(const nsACString& aUTF8String)
return atom; return atom;
} }
AtomImpl* atom = new PermanentAtomImpl(aUTF8String); AtomImpl* atom = new PermanentAtomImpl(aUTF16String);
he->SetAtomImpl(atom); he->SetAtomImpl(atom);
// No need to addref since permanent atoms aren't refcounted anyway // No need to addref since permanent atoms aren't refcounted anyway

View file

@ -48,7 +48,7 @@
class AtomImpl : public nsIAtom { class AtomImpl : public nsIAtom {
public: public:
AtomImpl(const nsACString& aString); AtomImpl(const nsAString& aString);
// This is currently only used during startup when creating a permanent atom // This is currently only used during startup when creating a permanent atom
// from NS_RegisterStaticAtoms // from NS_RegisterStaticAtoms
@ -60,7 +60,7 @@ protected:
AtomImpl() { AtomImpl() {
// We can't really assert that mString is a valid nsStringBuffer string, // We can't really assert that mString is a valid nsStringBuffer string,
// so do the best we can do and check for some consistencies. // 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() && nsStringBuffer::FromData(mString)->StorageSize() &&
mString[mLength] == 0, mString[mLength] == 0,
"Not initialized atom"); "Not initialized atom");
@ -90,7 +90,7 @@ public:
PRUint32 mLength; PRUint32 mLength;
// This always points to the data owned by a nsStringBuffer // This always points to the data owned by a nsStringBuffer
char* mString; PRUnichar* mString;
}; };
/** /**
@ -99,7 +99,7 @@ public:
class PermanentAtomImpl : public AtomImpl { class PermanentAtomImpl : public AtomImpl {
public: public:
PermanentAtomImpl(const nsACString& aString) PermanentAtomImpl(const nsAString& aString)
: AtomImpl(aString) : AtomImpl(aString)
{} {}
PermanentAtomImpl(nsStringBuffer* aData, PRUint32 aLength) PermanentAtomImpl(nsStringBuffer* aData, PRUint32 aLength)

View file

@ -55,6 +55,7 @@
#include "nsIServiceManager.h" #include "nsIServiceManager.h"
#include "nsCharTraits.h" #include "nsCharTraits.h"
#include "prbit.h" #include "prbit.h"
#include "nsUTF8Utils.h"
#define ADD_TO_HASHVAL(hashval, c) \ #define ADD_TO_HASHVAL(hashval, c) \
hashval = PR_ROTATE_LEFT32(hashval, 4) ^ (c); hashval = PR_ROTATE_LEFT32(hashval, 4) ^ (c);
@ -237,125 +238,44 @@ PRUint32 nsCRT::HashCode(const PRUnichar* str, PRUint32* resultingStrLen)
return h; return h;
} }
PRUint32 nsCRT::HashCodeAsUTF8(const PRUnichar* start, PRUint32 length) PRUint32 nsCRT::HashCode(const PRUnichar* start, PRUint32 length)
{ {
PRUint32 h = 0; PRUint32 h = 0;
const PRUnichar* s = start; const PRUnichar* s = start;
const PRUnichar* end = start + length; const PRUnichar* end = start + length;
PRUint16 W1 = 0; // the first UTF-16 word in a two word tuple PRUnichar c;
PRUint32 U = 0; // the current char as UCS-4 while ( s < end ) {
int code_length = 0; // the number of bytes in the UTF-8 sequence for the current char c = *s++;
ADD_TO_HASHVAL(h, c);
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;
}
} }
return h; return h;
} }
PRUint32 nsCRT::BufferHashCode(const PRUnichar* s, PRUint32 len) PRUint32 nsCRT::HashCodeAsUTF16(const char* start, PRUint32 length)
{ {
PRUint32 h = 0; 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; return h;
} }

View file

@ -236,15 +236,13 @@ public:
static PRUint32 HashCode(const PRUnichar* str, static PRUint32 HashCode(const PRUnichar* str,
PRUint32* resultingStrLen = nsnull); 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. // 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 // String to longlong
static PRInt64 atoll(const char *str); static PRInt64 atoll(const char *str);

View file

@ -48,7 +48,7 @@
* pointer identity. * pointer identity.
*/ */
[scriptable, uuid(fbffe332-0856-421a-9b83-aaed0081fc40)] [scriptable, uuid(96c82146-56f3-4b43-817f-25d6db1ad8e8)]
interface nsIAtom : nsISupports interface nsIAtom : nsISupports
{ {
/** /**
@ -58,9 +58,10 @@ interface nsIAtom : nsISupports
AUTF8String toUTF8String(); 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 * Compare the atom to a specific string value
@ -83,6 +84,13 @@ interface nsIAtom : nsISupports
EqualsUTF8(s, &result); EqualsUTF8(s, &result);
return result; return result;
} }
inline const PRUnichar* GetUTF16String() {
const PRUnichar* result;
GetUTF16String(&result);
return result;
}
%} %}
/** /**
@ -123,7 +131,6 @@ inline already_AddRefed<nsIAtom> do_GetAtom(const char* aUTF8String)
* Find an atom that matches the given UTF-8 string. * Find an atom that matches the given UTF-8 string.
*/ */
extern NS_COM nsIAtom* NS_NewAtom(const nsACString& aUTF8String); extern NS_COM nsIAtom* NS_NewAtom(const nsACString& aUTF8String);
extern NS_COM nsIAtom* NS_NewPermanentAtom(const nsACString& aUTF8String);
inline already_AddRefed<nsIAtom> do_GetAtom(const nsACString& aUTF8String) inline already_AddRefed<nsIAtom> do_GetAtom(const nsACString& aUTF8String)
{ return NS_NewAtom(aUTF8String); } { return NS_NewAtom(aUTF8String); }
@ -139,6 +146,7 @@ inline already_AddRefed<nsIAtom> do_GetAtom(const PRUnichar* aUTF16String)
* Find an atom that matches the given UTF-16 string. * Find an atom that matches the given UTF-16 string.
*/ */
extern NS_COM nsIAtom* NS_NewAtom(const nsAString& aUTF16String); extern NS_COM nsIAtom* NS_NewAtom(const nsAString& aUTF16String);
extern NS_COM nsIAtom* NS_NewPermanentAtom(const nsAString& aUTF16String);
inline already_AddRefed<nsIAtom> do_GetAtom(const nsAString& aUTF16String) inline already_AddRefed<nsIAtom> do_GetAtom(const nsAString& aUTF16String)
{ return NS_NewAtom(aUTF16String); } { return NS_NewAtom(aUTF16String); }
@ -159,4 +167,31 @@ extern NS_COM nsIAtom* NS_GetStaticAtom(const nsAString& aUTF16String);
*/ */
extern NS_COM void NS_SealStaticAtomTable(); 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())
{
}
};
%} %}

View file

@ -43,8 +43,18 @@
#include "nsStringBuffer.h" #include "nsStringBuffer.h"
#include "prlog.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_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 * Holds data used to initialize large number of atoms during startup. Use
@ -63,11 +73,10 @@ template <PRUint32 size>
struct nsFakeStringBuffer { struct nsFakeStringBuffer {
PRInt32 mRefCnt; PRInt32 mRefCnt;
PRUint32 mSize; PRUint32 mSize;
char mStringData[size]; nsStaticAtomStringType mStringData[size];
}; };
// register your lookup function with the atom table. Your function // Register static atoms with the atom table
// will be called when at atom is not found in the main atom table.
NS_COM nsresult NS_COM nsresult
NS_RegisterStaticAtoms(const nsStaticAtom*, PRUint32 aAtomCount); NS_RegisterStaticAtoms(const nsStaticAtom*, PRUint32 aAtomCount);

View file

@ -81,9 +81,9 @@ int main(int argc, char** argv)
// Now make sure we can find all the idents we just made // Now make sure we can find all the idents we just made
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
const char *utf8String; const PRUnichar *utf16String;
ids[i]->GetUTF8String(&utf8String); ids[i]->GetUTF16String(&utf16String);
nsIAtom* id = NS_NewAtom(utf8String); nsIAtom* id = NS_NewAtom(utf16String);
if (id != ids[i]) { if (id != ids[i]) {
id->ToString(s1); id->ToString(s1);
ids[i]->ToString(s2); ids[i]->ToString(s2);

View file

@ -51,9 +51,7 @@ static void Assert(PRBool aCondition, const char* aStatement)
static void AssertString(nsIAtom *aAtom, const nsACString& aString) static void AssertString(nsIAtom *aAtom, const nsACString& aString)
{ {
const char *str; Assert(aAtom->EqualsUTF8(aString), "string is correct");
static_cast<AtomImpl*>(aAtom)->GetUTF8String(&str);
Assert(nsDependentCString(str) == aString, "string is correct");
} }
static void AssertPermanence(nsIAtom *aAtom, PRBool aPermanence) static void AssertPermanence(nsIAtom *aAtom, PRBool aPermanence)
@ -68,13 +66,13 @@ int main()
AssertString(foo, NS_LITERAL_CSTRING("foo")); AssertString(foo, NS_LITERAL_CSTRING("foo"));
AssertPermanence(foo, PR_FALSE); AssertPermanence(foo, PR_FALSE);
nsCOMPtr<nsIAtom> foop = do_GetPermanentAtom("foo"); nsCOMPtr<nsIAtom> foop = NS_NewPermanentAtom(NS_LITERAL_STRING("foo"));
AssertString(foop, NS_LITERAL_CSTRING("foo")); AssertString(foop, NS_LITERAL_CSTRING("foo"));
AssertPermanence(foop, PR_TRUE); AssertPermanence(foop, PR_TRUE);
Assert(foo == foop, "atoms are equal"); Assert(foo == foop, "atoms are equal");
nsCOMPtr<nsIAtom> barp = do_GetPermanentAtom("bar"); nsCOMPtr<nsIAtom> barp = NS_NewPermanentAtom(NS_LITERAL_STRING("bar"));
AssertString(barp, NS_LITERAL_CSTRING("bar")); AssertString(barp, NS_LITERAL_CSTRING("bar"));
AssertPermanence(barp, PR_TRUE); AssertPermanence(barp, PR_TRUE);

View file

@ -140,6 +140,32 @@ test_malformed8()
return PR_TRUE; 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)(); typedef PRBool (*TestFunc)();
static const struct Test static const struct Test
@ -156,6 +182,7 @@ tests[] =
// Don't run this test in debug builds as that intentionally asserts // Don't run this test in debug builds as that intentionally asserts
{ "test_malformed8", test_malformed8 }, { "test_malformed8", test_malformed8 },
#endif #endif
{ "test_hashas16", test_hashas16 },
{ nsnull, nsnull } { nsnull, nsnull }
}; };