diff --git a/mozilla/content/xml/document/src/nsXMLContentSink.cpp b/mozilla/content/xml/document/src/nsXMLContentSink.cpp index 9d7f1389489..5da2c3a040d 100644 --- a/mozilla/content/xml/document/src/nsXMLContentSink.cpp +++ b/mozilla/content/xml/document/src/nsXMLContentSink.cpp @@ -264,36 +264,6 @@ NS_INTERFACE_MAP_BEGIN(nsXMLContentSink) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXMLContentSink) NS_INTERFACE_MAP_END -/** - * DOCTYPE declaration is covered with very strict rules, which - * makes our life here simpler because the XML parser has already - * detected errors. The only slightly problematic case is whitespace - * between the tokens. There MUST be whitespace between the tokens - * EXCEPT right before > and [. - */ -static const char* kWhitespace = " \r\n\t\b"; // Optimized for typical cases - -static void -GetDocTypeToken(nsString& aStr, - nsString& aToken, - PRBool aQuotedString) -{ - aStr.Trim(kWhitespace,PR_TRUE,PR_FALSE); // If we don't do this we must look ahead - // before Cut() and adjust the cut amount. - - if (aQuotedString) { - PRInt32 endQuote = aStr.FindChar(aStr[0],1); - aStr.Mid(aToken,1,endQuote-1); - aStr.Cut(0,endQuote+1); - } else { - static const char* kDelimiter = " >[\r\n\t\b"; // Optimized for typical cases - PRInt32 tokenEnd = aStr.FindCharInSet(kDelimiter); - if (tokenEnd > 0) { - aStr.Left(aToken, tokenEnd); - aStr.Cut(0, tokenEnd); - } - } -} // nsIContentSink NS_IMETHODIMP nsXMLContentSink::WillBuildModel(void) @@ -1874,8 +1844,10 @@ nsXMLContentSink::HandleCDataSection(const PRUnichar *aData, } NS_IMETHODIMP -nsXMLContentSink::HandleDoctypeDecl(const PRUnichar *aDoctype, - PRUint32 aLength, +nsXMLContentSink::HandleDoctypeDecl(const nsAString & aSubset, + const nsAString & aName, + const nsAString & aSystemId, + const nsAString & aPublicId, nsISupports* aCatalogData) { nsresult rv = NS_OK; @@ -1884,31 +1856,12 @@ nsXMLContentSink::HandleDoctypeDecl(const PRUnichar *aDoctype, if (!doc) return NS_OK; - nsAutoString str(aDoctype, aLength); - nsAutoString name, publicId, systemId; - - GetDocTypeToken(str, name, PR_FALSE); - - nsAutoString token; - - GetDocTypeToken(str, token, PR_FALSE); - if (token.Equals(NS_LITERAL_STRING("PUBLIC"))) { - GetDocTypeToken(str, publicId, PR_TRUE); - GetDocTypeToken(str, systemId, PR_TRUE); - } - else if (token.Equals(NS_LITERAL_STRING("SYSTEM"))) { - GetDocTypeToken(str, systemId, PR_TRUE); - } - - // The rest is the internal subset (minus whitespace) - str.Trim(kWhitespace); - nsCOMPtr docType; // Create a new doctype node rv = NS_NewDOMDocumentType(getter_AddRefs(docType), - name, nsnull, nsnull, - publicId, systemId, str); + aName, nsnull, nsnull, + aPublicId, aSystemId, aSubset); if (NS_FAILED(rv) || !docType) { return rv; } diff --git a/mozilla/content/xul/document/src/nsXULContentSink.cpp b/mozilla/content/xul/document/src/nsXULContentSink.cpp index 48253b361ab..3b6b79add02 100644 --- a/mozilla/content/xul/document/src/nsXULContentSink.cpp +++ b/mozilla/content/xul/document/src/nsXULContentSink.cpp @@ -1009,7 +1009,10 @@ XULContentSinkImpl::HandleCDataSection(const PRUnichar *aData, PRUint32 aLength) } NS_IMETHODIMP -XULContentSinkImpl::HandleDoctypeDecl(const PRUnichar *aDoctype, PRUint32 aLength, +XULContentSinkImpl::HandleDoctypeDecl(const nsAString & aSubset, + const nsAString & aName, + const nsAString & aSystemId, + const nsAString & aPublicId, nsISupports* aCatalogData) { return NS_OK; diff --git a/mozilla/htmlparser/public/nsIExpatSink.idl b/mozilla/htmlparser/public/nsIExpatSink.idl index feee46c0c84..5ccdfd035d1 100644 --- a/mozilla/htmlparser/public/nsIExpatSink.idl +++ b/mozilla/htmlparser/public/nsIExpatSink.idl @@ -54,8 +54,10 @@ interface nsIExpatSink : nsISupports void HandleCDataSection(in wstring aData, in unsigned long aLength); - void HandleDoctypeDecl(in wstring aDoctype, - in unsigned long aLength, + void HandleDoctypeDecl(in AString aSubset, + in AString aName, + in AString aSystemId, + in AString aPublicId, in nsISupports aCatalogData); void HandleCharacterData(in wstring aData, diff --git a/mozilla/htmlparser/src/nsExpatDriver.cpp b/mozilla/htmlparser/src/nsExpatDriver.cpp index 5339551e1c3..26ff6740be4 100644 --- a/mozilla/htmlparser/src/nsExpatDriver.cpp +++ b/mozilla/htmlparser/src/nsExpatDriver.cpp @@ -51,7 +51,7 @@ #include "prmem.h" #include "nsTextFormatter.h" -static const PRUint32 kNotInDoctype = PRUint32(-1); +static const char* kWhitespace = " \r\n\t"; // Optimized for typical cases static const char* kDTDDirectory = "res/dtd/"; /***************************** EXPAT CALL BACKS *******************************/ @@ -300,12 +300,11 @@ NS_NewExpatDriver(nsIDTD** aResult) { nsExpatDriver::nsExpatDriver() :mExpatParser(0), mSink(0), - mBuffer(0), - mInCData(0), + mInCData(0), + mInDoctype(0), mBytesParsed(0), mBytePosition(0), mInternalState(NS_OK), - mDoctypePos(-1), mCatalogData(nsnull) { NS_INIT_REFCNT(); @@ -372,7 +371,10 @@ nsExpatDriver::HandleComment(const PRUnichar *aValue) { NS_ASSERTION(mSink, "content sink not found!"); - if (mSink && mDoctypePos == kNotInDoctype){ + if (mInDoctype) { + mDoctypeText.Append(aValue); + } + else if (mSink){ mInternalState = mSink->HandleComment(aValue); } @@ -402,7 +404,10 @@ nsExpatDriver::HandleDefault(const PRUnichar *aValue, { NS_ASSERTION(mSink, "content sink not found!"); - if (mSink && mDoctypePos == kNotInDoctype) { + if (mInDoctype) { + mDoctypeText.Append(aValue, aLength); + } + else if (mSink) { static const PRUnichar newline[] = {'\n','\0'}; for (PRUint32 i = 0; i < aLength && NS_SUCCEEDED(mInternalState); i++) { if (aValue[i] == '\n' || aValue[i] == '\r') { @@ -435,10 +440,42 @@ nsExpatDriver::HandleEndCdataSection() return NS_OK; } +/** + * DOCTYPE declaration is covered with very strict rules, which + * makes our life here simpler because the XML parser has already + * detected errors. The only slightly problematic case is whitespace + * between the tokens. There MUST be whitespace between the tokens + * EXCEPT right before > and [. + */ +static void +GetDocTypeToken(nsString& aStr, + nsString& aToken, + PRBool aQuotedString) +{ + aStr.Trim(kWhitespace,PR_TRUE,PR_FALSE); // If we don't do this we must look ahead + // before Cut() and adjust the cut amount. + if (aQuotedString) { + PRInt32 endQuote = aStr.FindChar(aStr[0],1); + aStr.Mid(aToken,1,endQuote-1); + aStr.Cut(0,endQuote+1); + } else { + static const char* kDelimiter = " >[\r\n\t"; // Optimized for typical cases + PRInt32 tokenEnd = aStr.FindCharInSet(kDelimiter); + if (tokenEnd > 0) { + aStr.Left(aToken, tokenEnd); + aStr.Cut(0, tokenEnd); + } + } +} + nsresult nsExpatDriver::HandleStartDoctypeDecl() { - mDoctypePos = XML_GetCurrentByteIndex(mExpatParser); + mInDoctype = PR_TRUE; + // Consuming a huge DOCTYPE translates to numerous + // allocations. In an effort to avoid too many allocations + // setting mDoctypeText's capacity to be 20K ( just a guesstimate! ). + mDoctypeText.SetCapacity(20480); return NS_OK; } @@ -446,10 +483,9 @@ nsresult nsExpatDriver::HandleEndDoctypeDecl() { NS_ASSERTION(mSink, "content sink not found!"); - - const PRUnichar* doctypeStart = mBuffer + ( mDoctypePos - mBytesParsed ) / 2; - const PRUnichar* doctypeEnd = mBuffer + ( XML_GetCurrentByteIndex(mExpatParser) - mBytesParsed ) / 2; + mInDoctype = PR_FALSE; + if(mSink) { // let the sink know any additional knowledge that we have about the document // (currently, from bug 124570, we only expect to pass additional agent sheets @@ -458,11 +494,32 @@ nsExpatDriver::HandleEndDoctypeDecl() if (mCatalogData && mCatalogData->mAgentSheet) { NS_NewURI(&data, mCatalogData->mAgentSheet); } - mInternalState = mSink->HandleDoctypeDecl(doctypeStart, doctypeEnd - doctypeStart, data); + + nsAutoString name; + GetDocTypeToken(mDoctypeText, name, PR_FALSE); + + nsAutoString token, publicId, systemId; + GetDocTypeToken(mDoctypeText, token, PR_FALSE); + if (token.Equals(NS_LITERAL_STRING("PUBLIC"))) { + GetDocTypeToken(mDoctypeText, publicId, PR_TRUE); + GetDocTypeToken(mDoctypeText, systemId, PR_TRUE); + } + else if (token.Equals(NS_LITERAL_STRING("SYSTEM"))) { + GetDocTypeToken(mDoctypeText, systemId, PR_TRUE); + } + + // The rest is the internal subset (minus whitespace) + mDoctypeText.Trim(kWhitespace); + + mInternalState = mSink->HandleDoctypeDecl(mDoctypeText, + name, + systemId, + publicId, + data); NS_IF_RELEASE(data); } - mDoctypePos = kNotInDoctype; + mDoctypeText.SetCapacity(0); return NS_OK; } @@ -767,9 +824,8 @@ nsExpatDriver::ConsumeToken(nsScanner& aScanner, while (start != end) { PRUint32 fragLength = PRUint32(start.size_forward()); - mBuffer = start.get(); - mInternalState = ParseBuffer((const char *)mBuffer, + mInternalState = ParseBuffer((const char *)start.get(), fragLength * sizeof(PRUnichar), aFlushTokens); diff --git a/mozilla/htmlparser/src/nsExpatDriver.h b/mozilla/htmlparser/src/nsExpatDriver.h index 83344cc72e0..749cf27561c 100644 --- a/mozilla/htmlparser/src/nsExpatDriver.h +++ b/mozilla/htmlparser/src/nsExpatDriver.h @@ -88,16 +88,15 @@ protected: void GetLine(const char* aSourceBuffer, PRUint32 aLength, PRUint32 aOffset, nsString& aLine); XML_Parser mExpatParser; - nsIExpatSink* mSink; - const PRUnichar* mBuffer; // weak - nsString mLastLine; nsString mCDataText; + nsString mDoctypeText; PRPackedBool mInCData; + PRPackedBool mInDoctype; PRInt32 mBytePosition; nsresult mInternalState; PRUint32 mBytesParsed; - PRUint32 mDoctypePos; + nsIExpatSink* mSink; const nsCatalogData* mCatalogData; // weak }; diff --git a/mozilla/parser/htmlparser/public/nsIExpatSink.idl b/mozilla/parser/htmlparser/public/nsIExpatSink.idl index feee46c0c84..5ccdfd035d1 100644 --- a/mozilla/parser/htmlparser/public/nsIExpatSink.idl +++ b/mozilla/parser/htmlparser/public/nsIExpatSink.idl @@ -54,8 +54,10 @@ interface nsIExpatSink : nsISupports void HandleCDataSection(in wstring aData, in unsigned long aLength); - void HandleDoctypeDecl(in wstring aDoctype, - in unsigned long aLength, + void HandleDoctypeDecl(in AString aSubset, + in AString aName, + in AString aSystemId, + in AString aPublicId, in nsISupports aCatalogData); void HandleCharacterData(in wstring aData, diff --git a/mozilla/parser/htmlparser/src/nsExpatDriver.cpp b/mozilla/parser/htmlparser/src/nsExpatDriver.cpp index 5339551e1c3..26ff6740be4 100644 --- a/mozilla/parser/htmlparser/src/nsExpatDriver.cpp +++ b/mozilla/parser/htmlparser/src/nsExpatDriver.cpp @@ -51,7 +51,7 @@ #include "prmem.h" #include "nsTextFormatter.h" -static const PRUint32 kNotInDoctype = PRUint32(-1); +static const char* kWhitespace = " \r\n\t"; // Optimized for typical cases static const char* kDTDDirectory = "res/dtd/"; /***************************** EXPAT CALL BACKS *******************************/ @@ -300,12 +300,11 @@ NS_NewExpatDriver(nsIDTD** aResult) { nsExpatDriver::nsExpatDriver() :mExpatParser(0), mSink(0), - mBuffer(0), - mInCData(0), + mInCData(0), + mInDoctype(0), mBytesParsed(0), mBytePosition(0), mInternalState(NS_OK), - mDoctypePos(-1), mCatalogData(nsnull) { NS_INIT_REFCNT(); @@ -372,7 +371,10 @@ nsExpatDriver::HandleComment(const PRUnichar *aValue) { NS_ASSERTION(mSink, "content sink not found!"); - if (mSink && mDoctypePos == kNotInDoctype){ + if (mInDoctype) { + mDoctypeText.Append(aValue); + } + else if (mSink){ mInternalState = mSink->HandleComment(aValue); } @@ -402,7 +404,10 @@ nsExpatDriver::HandleDefault(const PRUnichar *aValue, { NS_ASSERTION(mSink, "content sink not found!"); - if (mSink && mDoctypePos == kNotInDoctype) { + if (mInDoctype) { + mDoctypeText.Append(aValue, aLength); + } + else if (mSink) { static const PRUnichar newline[] = {'\n','\0'}; for (PRUint32 i = 0; i < aLength && NS_SUCCEEDED(mInternalState); i++) { if (aValue[i] == '\n' || aValue[i] == '\r') { @@ -435,10 +440,42 @@ nsExpatDriver::HandleEndCdataSection() return NS_OK; } +/** + * DOCTYPE declaration is covered with very strict rules, which + * makes our life here simpler because the XML parser has already + * detected errors. The only slightly problematic case is whitespace + * between the tokens. There MUST be whitespace between the tokens + * EXCEPT right before > and [. + */ +static void +GetDocTypeToken(nsString& aStr, + nsString& aToken, + PRBool aQuotedString) +{ + aStr.Trim(kWhitespace,PR_TRUE,PR_FALSE); // If we don't do this we must look ahead + // before Cut() and adjust the cut amount. + if (aQuotedString) { + PRInt32 endQuote = aStr.FindChar(aStr[0],1); + aStr.Mid(aToken,1,endQuote-1); + aStr.Cut(0,endQuote+1); + } else { + static const char* kDelimiter = " >[\r\n\t"; // Optimized for typical cases + PRInt32 tokenEnd = aStr.FindCharInSet(kDelimiter); + if (tokenEnd > 0) { + aStr.Left(aToken, tokenEnd); + aStr.Cut(0, tokenEnd); + } + } +} + nsresult nsExpatDriver::HandleStartDoctypeDecl() { - mDoctypePos = XML_GetCurrentByteIndex(mExpatParser); + mInDoctype = PR_TRUE; + // Consuming a huge DOCTYPE translates to numerous + // allocations. In an effort to avoid too many allocations + // setting mDoctypeText's capacity to be 20K ( just a guesstimate! ). + mDoctypeText.SetCapacity(20480); return NS_OK; } @@ -446,10 +483,9 @@ nsresult nsExpatDriver::HandleEndDoctypeDecl() { NS_ASSERTION(mSink, "content sink not found!"); - - const PRUnichar* doctypeStart = mBuffer + ( mDoctypePos - mBytesParsed ) / 2; - const PRUnichar* doctypeEnd = mBuffer + ( XML_GetCurrentByteIndex(mExpatParser) - mBytesParsed ) / 2; + mInDoctype = PR_FALSE; + if(mSink) { // let the sink know any additional knowledge that we have about the document // (currently, from bug 124570, we only expect to pass additional agent sheets @@ -458,11 +494,32 @@ nsExpatDriver::HandleEndDoctypeDecl() if (mCatalogData && mCatalogData->mAgentSheet) { NS_NewURI(&data, mCatalogData->mAgentSheet); } - mInternalState = mSink->HandleDoctypeDecl(doctypeStart, doctypeEnd - doctypeStart, data); + + nsAutoString name; + GetDocTypeToken(mDoctypeText, name, PR_FALSE); + + nsAutoString token, publicId, systemId; + GetDocTypeToken(mDoctypeText, token, PR_FALSE); + if (token.Equals(NS_LITERAL_STRING("PUBLIC"))) { + GetDocTypeToken(mDoctypeText, publicId, PR_TRUE); + GetDocTypeToken(mDoctypeText, systemId, PR_TRUE); + } + else if (token.Equals(NS_LITERAL_STRING("SYSTEM"))) { + GetDocTypeToken(mDoctypeText, systemId, PR_TRUE); + } + + // The rest is the internal subset (minus whitespace) + mDoctypeText.Trim(kWhitespace); + + mInternalState = mSink->HandleDoctypeDecl(mDoctypeText, + name, + systemId, + publicId, + data); NS_IF_RELEASE(data); } - mDoctypePos = kNotInDoctype; + mDoctypeText.SetCapacity(0); return NS_OK; } @@ -767,9 +824,8 @@ nsExpatDriver::ConsumeToken(nsScanner& aScanner, while (start != end) { PRUint32 fragLength = PRUint32(start.size_forward()); - mBuffer = start.get(); - mInternalState = ParseBuffer((const char *)mBuffer, + mInternalState = ParseBuffer((const char *)start.get(), fragLength * sizeof(PRUnichar), aFlushTokens); diff --git a/mozilla/parser/htmlparser/src/nsExpatDriver.h b/mozilla/parser/htmlparser/src/nsExpatDriver.h index 83344cc72e0..749cf27561c 100644 --- a/mozilla/parser/htmlparser/src/nsExpatDriver.h +++ b/mozilla/parser/htmlparser/src/nsExpatDriver.h @@ -88,16 +88,15 @@ protected: void GetLine(const char* aSourceBuffer, PRUint32 aLength, PRUint32 aOffset, nsString& aLine); XML_Parser mExpatParser; - nsIExpatSink* mSink; - const PRUnichar* mBuffer; // weak - nsString mLastLine; nsString mCDataText; + nsString mDoctypeText; PRPackedBool mInCData; + PRPackedBool mInDoctype; PRInt32 mBytePosition; nsresult mInternalState; PRUint32 mBytesParsed; - PRUint32 mDoctypePos; + nsIExpatSink* mSink; const nsCatalogData* mCatalogData; // weak }; diff --git a/mozilla/rdf/base/src/nsRDFContentSink.cpp b/mozilla/rdf/base/src/nsRDFContentSink.cpp index f7d7d492de5..f85f4e3ab57 100644 --- a/mozilla/rdf/base/src/nsRDFContentSink.cpp +++ b/mozilla/rdf/base/src/nsRDFContentSink.cpp @@ -604,8 +604,11 @@ RDFContentSinkImpl::HandleCDataSection(const PRUnichar *aData, } NS_IMETHODIMP -RDFContentSinkImpl::HandleDoctypeDecl(const PRUnichar *aDoctype, PRUint32 aLength, - nsISupports *aCatalogData) +RDFContentSinkImpl::HandleDoctypeDecl(const nsAString & aSubset, + const nsAString & aName, + const nsAString & aSystemId, + const nsAString & aPublicId, + nsISupports* aCatalogData) { return NS_OK; }