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);
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);
}
}
}

View file

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

View file

@ -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<short>(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());
}

View file

@ -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.
*/

View file

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

View file

@ -510,7 +510,7 @@ nsAttrValue::HashValue() const
nsStringBuffer* str = static_cast<nsStringBuffer*>(GetPtr());
if (str) {
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;
@ -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;
}
}

View file

@ -532,11 +532,9 @@ nsContentSink::ProcessHeaderData(nsIAtom* aHeader, const nsAString& aValue,
if (NS_SUCCEEDED(mParser->GetChannel(getter_AddRefs(channel)))) {
nsCOMPtr<nsIHttpChannel> 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);
}
}
}

View file

@ -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()

View file

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

View file

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

View file

@ -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 ':'

View file

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

View file

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

View file

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

View file

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

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
// 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 == '-') {

View file

@ -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<nsIRDFResource> attr;
rv = gRDFService->GetResource(nsDependentCString(attrstr),
rv = gRDFService->GetResource(attrstr,
getter_AddRefs(attr));
if (NS_FAILED(rv)) return rv;

View file

@ -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]" : "")));
}

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
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) {

View file

@ -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<nsRefPtr<gfxFontEntry>, 5> fonts;
this->GetPrefFonts(langGroup, fonts);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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)
nsCOMPtr<nsIContent>content;
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");

View file

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

View file

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

View file

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

View file

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

View file

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

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...
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!");
}

View file

@ -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<nsIRDFResource> 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<nsIRDFResource> 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<nsIRDFResource> property;
rv = gRDFService->GetResource(propertyStr, getter_AddRefs(property));

View file

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

View file

@ -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<const AtomTableEntry*>(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<const AtomTableEntry*>(entry);
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
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<PRUint32*>(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<char*>(buf->Data());
mString = static_cast<PRUnichar*>(buf->Data());
}
else {
buf = nsStringBuffer::Alloc((mLength + 1) * sizeof(char));
mString = static_cast<char*>(buf->Data());
memcpy(mString, aString.BeginReading(), mLength * sizeof(char));
buf = nsStringBuffer::Alloc((mLength + 1) * sizeof(PRUnichar));
mString = static_cast<PRUnichar*>(buf->Data());
CopyUnicodeTo(aString, 0, mString, mLength);
mString[mLength] = PRUnichar(0);
}
}
AtomImpl::AtomImpl(nsStringBuffer* aStringBuffer, PRUint32 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
// 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; 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!");
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

View file

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

View file

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

View file

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

View file

@ -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<nsIAtom> 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<nsIAtom> do_GetAtom(const nsACString& 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.
*/
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)
{ 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())
{
}
};
%}

View file

@ -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 <PRUint32 size>
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);

View file

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

View file

@ -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<AtomImpl*>(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<nsIAtom> foop = do_GetPermanentAtom("foo");
nsCOMPtr<nsIAtom> foop = NS_NewPermanentAtom(NS_LITERAL_STRING("foo"));
AssertString(foop, NS_LITERAL_CSTRING("foo"));
AssertPermanence(foop, PR_TRUE);
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"));
AssertPermanence(barp, PR_TRUE);

View file

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