Fixing bug 121485. Un-nsAutoString:ifying nsXULContentSink::NormalizeAttributeString(), ::PushNameSpacesFrom(), and ::ParseTag() in favor of new string iterators n' other neat features. r=nisheeth@netscape.com, sr=waterson@netscape.com

This commit is contained in:
jst%netscape.com 2002-01-24 10:23:04 +00:00
Родитель ad92bcd618
Коммит 0e0a1ed594
1 изменённых файлов: 124 добавлений и 93 удалений

Просмотреть файл

@ -169,8 +169,8 @@ protected:
PRBool mConstrainSize;
// namespace management -- XXX combine with ContextStack?
void PushNameSpacesFrom(const PRUnichar** aAttributes);
nsresult PushNameSpacesFrom(const PRUnichar** aAttributes);
// RDF-specific parsing
nsresult ParseTag(const PRUnichar* aText, nsINodeInfo*& aNodeInfo);
nsresult AddAttributes(const PRUnichar** aAttributes,
@ -206,7 +206,7 @@ protected:
nsCOMPtr<nsINodeInfoManager> mNodeInfoManager;
nsresult NormalizeAttributeString(const nsAReadableString& aText,
nsresult NormalizeAttributeString(const nsAFlatString& aText,
nsINodeInfo*& aNodeInfo);
nsresult CreateElement(nsINodeInfo *aNodeInfo, nsXULPrototypeElement** aResult);
@ -785,39 +785,46 @@ XULContentSinkImpl::FlushText(PRBool aCreateTextNode)
//----------------------------------------------------------------------
nsresult
XULContentSinkImpl::NormalizeAttributeString(const nsAReadableString& aText,
XULContentSinkImpl::NormalizeAttributeString(const nsAFlatString& aText,
nsINodeInfo*& aNodeInfo)
{
nsresult rv;
PRInt32 nameSpaceID = kNameSpaceID_None;
// Split the attribute into prefix and tag substrings.
nsAutoString prefixStr;
nsAutoString attrStr(aText);
PRInt32 nsoffset = attrStr.FindChar(kNameSpaceSeparator);
if (nsoffset >= 0) {
attrStr.Left(prefixStr, nsoffset);
attrStr.Cut(0, nsoffset + 1);
}
nsAFlatString::const_iterator start, end;
aText.BeginReading(start);
aText.EndReading(end);
nsAFlatString::const_iterator colon(start);
nsCOMPtr<nsIAtom> prefix;
if (!prefixStr.IsEmpty()) {
prefix = dont_AddRef( NS_NewAtom(prefixStr) );
if (!FindCharInReadable(kNameSpaceSeparator, colon, end)) {
colon = start; // No ':' found, reset colon
} else if (start != colon) {
prefix = dont_AddRef(NS_NewAtom(Substring(start, colon)));
nsCOMPtr<nsINameSpace> ns;
rv = GetTopNameSpace(address_of(ns));
if (NS_FAILED(rv)) return rv;
GetTopNameSpace(address_of(ns));
rv = ns->FindNameSpaceID(prefix, nameSpaceID);
if (NS_FAILED(rv)) return rv;
if (ns) {
ns->FindNameSpaceID(prefix, nameSpaceID);
if (nameSpaceID == kNameSpaceID_Unknown) {
NS_WARNING("Undeclared prefix used in attribute name.");
nameSpaceID = kNameSpaceID_None;
}
} else {
NS_WARNING("Undeclared prefix used in attribute name.");
}
++colon; // Skip over the ':'
}
mNodeInfoManager->GetNodeInfo(attrStr, prefixStr, nameSpaceID, aNodeInfo);
return NS_OK;
return mNodeInfoManager->GetNodeInfo(Substring(colon, end), prefix,
nameSpaceID, aNodeInfo);
}
nsresult
XULContentSinkImpl::CreateElement(nsINodeInfo *aNodeInfo,
nsXULPrototypeElement** aResult)
@ -878,9 +885,8 @@ XULContentSinkImpl::HandleStartElement(const PRUnichar *aName,
// list of an element before creating the element. This is because
// the namespace prefix for an element might be declared within
// the attribute list.
PushNameSpacesFrom(aAtts);
nsresult rv;
nsresult rv = PushNameSpacesFrom(aAtts);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsINodeInfo> nodeInfo;
rv = ParseTag(aName, *getter_AddRefs(nodeInfo));
@ -1177,59 +1183,74 @@ XULContentSinkImpl::ReportError(const PRUnichar* aErrorText,
// Namespace management
//
void
nsresult
XULContentSinkImpl::PushNameSpacesFrom(const PRUnichar** aAttributes)
{
nsINameSpace* nameSpace = nsnull;
if (0 < mNameSpaceStack.Count()) {
nameSpace = (nsINameSpace*)mNameSpaceStack[mNameSpaceStack.Count() - 1];
NS_ADDREF(nameSpace);
}
else {
gNameSpaceManager->CreateRootNameSpace(nameSpace);
}
nsCOMPtr<nsINameSpace> nameSpace;
NS_ASSERTION(nameSpace != nsnull, "no parent namespace");
if (! nameSpace)
return;
if (mNameSpaceStack.Count() > 0) {
nameSpace =
(nsINameSpace*)mNameSpaceStack.ElementAt(mNameSpaceStack.Count() - 1);
} else {
gNameSpaceManager->CreateRootNameSpace(*getter_AddRefs(nameSpace));
if (! nameSpace)
return NS_ERROR_OUT_OF_MEMORY;
}
for (; *aAttributes; aAttributes += 2) {
nsAutoString k(aAttributes[0]);
static const NS_NAMED_LITERAL_STRING(kNameSpaceDef, "xmlns");
static const PRUint32 xmlns_len = 5; // kNameSpaceDef.Length();
NS_ASSERTION(kNameSpaceDef.Length() == xmlns_len,
"xmlns_len incorrectly set!");
// Look for "xmlns" at the start of the attribute name
PRInt32 offset = k.Find(kNameSpaceDef);
if (0 != offset) {
continue;
}
for (; *aAttributes; aAttributes += 2) {
nsDependentString key(aAttributes[0]);
nsAutoString prefix;
if (k.Length() >= PRInt32(sizeof kNameSpaceDef)) {
// If the next character is a :, there is a namespace prefix
PRUnichar next = k.CharAt(sizeof(kNameSpaceDef)-1);
if (':' == next) {
k.Right(prefix, k.Length()-sizeof(kNameSpaceDef));
// Look for "xmlns" at the start of the attribute name
PRUint32 key_len = key.Length();
if (key_len >= xmlns_len &&
Substring(key, 0, xmlns_len).Equals(kNameSpaceDef)) {
nsCOMPtr<nsIAtom> prefixAtom;
// If key_len > xmlns_len we have a xmlns:foo type attribute,
// extract the prefix. If not, we have a xmlns attribute in
// which case there is no prefix.
if (key_len > xmlns_len) {
nsDependentString::const_iterator start, end;
key.BeginReading(start);
key.EndReading(end);
start.advance(xmlns_len);
if (*start == ':' && ++start != end) {
prefixAtom =
dont_AddRef(NS_NewAtom(Substring(start, end)));
} else {
NS_WARNING("Bad XML namespace declaration 'xmlns:' "
"found!");
}
}
nsDependentString value(aAttributes[1]);
nsCOMPtr<nsINameSpace> child;
nsresult rv =
nameSpace->CreateChildNameSpace(prefixAtom, value,
*getter_AddRefs(child));
NS_ENSURE_SUCCESS(rv, rv);
nameSpace = child;
}
else {
aAttributes += 2;
continue; // it's not "xmlns:"
}
}
}
// Get the attribute value (the URI for the namespace)
// Open a local namespace
nsIAtom* prefixAtom = ((prefix.IsEmpty()) ? nsnull : NS_NewAtom(prefix));
nsINameSpace* child = nsnull;
nameSpace->CreateChildNameSpace(prefixAtom, nsDependentString(aAttributes[1]), child);
if (nsnull != child) {
NS_RELEASE(nameSpace);
nameSpace = child;
}
nsINameSpace *tmp = nameSpace;
mNameSpaceStack.AppendElement(tmp);
NS_ADDREF(tmp);
NS_IF_RELEASE(prefixAtom);
}
// Now push the *last* namespace that we discovered on to the stack.
mNameSpaceStack.AppendElement(nameSpace);
return NS_OK;
}
void
@ -1264,35 +1285,45 @@ nsresult
XULContentSinkImpl::ParseTag(const PRUnichar* aText,
nsINodeInfo*& aNodeInfo)
{
nsresult rv;
// Split the tag into prefix and tag substrings.
// Split the tag into prefix and tag substrings.
nsAutoString prefixStr;
nsAutoString tagStr(aText);
PRInt32 nsoffset = tagStr.FindChar(kNameSpaceSeparator);
if (nsoffset >= 0) {
tagStr.Left(prefixStr, nsoffset);
tagStr.Cut(0, nsoffset + 1);
}
nsDependentString text(aText);
nsCOMPtr<nsIAtom> prefix;
if (!prefixStr.IsEmpty()) {
prefix = dont_AddRef( NS_NewAtom(prefixStr) );
}
nsDependentString::const_iterator start, end;
text.BeginReading(start);
text.EndReading(end);
nsCOMPtr<nsINameSpace> ns;
rv = GetTopNameSpace(address_of(ns));
if (NS_FAILED(rv)) return rv;
nsDependentString::const_iterator colon(start);
PRInt32 namespaceID;
rv = ns->FindNameSpaceID(prefix, namespaceID);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIAtom> prefix;
nsCOMPtr<nsIAtom> tag(dont_AddRef(NS_NewAtom(tagStr)));
if (! tag)
return NS_ERROR_OUT_OF_MEMORY;
if (!FindCharInReadable(kNameSpaceSeparator, colon, end)) {
colon = start; // No ':' found, reset colon
} else if (colon != start) {
prefix = dont_AddRef(NS_NewAtom(Substring(start, colon)));
return mNodeInfoManager->GetNodeInfo(tag, prefix, namespaceID, aNodeInfo);
++colon; // Step over ':'
}
nsCOMPtr<nsINameSpace> ns;
GetTopNameSpace(address_of(ns));
PRInt32 namespaceID = kNameSpaceID_None;
if (ns) {
ns->FindNameSpaceID(prefix, namespaceID);
if (namespaceID == kNameSpaceID_Unknown) {
NS_WARNING("Undeclared prefix used in tag name!");
namespaceID = kNameSpaceID_None;
}
} else {
NS_WARNING("Undeclared prefix used in tag name!");
}
return mNodeInfoManager->GetNodeInfo(Substring(colon, end), prefix,
namespaceID, aNodeInfo);
}
nsresult