diff --git a/mozilla/htmlparser/robot/nsRobotSink.cpp b/mozilla/htmlparser/robot/nsRobotSink.cpp index 0ebf4280ef1..1b0d6ebd512 100644 --- a/mozilla/htmlparser/robot/nsRobotSink.cpp +++ b/mozilla/htmlparser/robot/nsRobotSink.cpp @@ -226,9 +226,8 @@ NS_IMETHODIMP RobotSink::OpenContainer(const nsIParserNode& aNode) PRInt32 ac = aNode.GetAttributeCount(); for (PRInt32 i = 0; i < ac; i++) { // Get upper-cased key - const nsString& key = aNode.GetKeyAt(i); - k.Truncate(); - k.Append(key); + const nsAReadableString& key = aNode.GetKeyAt(i); + k.Assign(key); k.ToLowerCase(); if (k.EqualsWithConversion("href")) { // Get value and remove mandatory quotes diff --git a/mozilla/htmlparser/src/CNavDTD.cpp b/mozilla/htmlparser/src/CNavDTD.cpp index 101fce2d5a6..eb034927890 100644 --- a/mozilla/htmlparser/src/CNavDTD.cpp +++ b/mozilla/htmlparser/src/CNavDTD.cpp @@ -52,6 +52,7 @@ #include "nsLinebreakConverter.h" #include "nsIFormProcessor.h" #include "nsVoidArray.h" +#include "nsReadableUtils.h" #include "prmem.h" @@ -164,10 +165,6 @@ CNavDTD::CNavDTD() : nsIDTD(), mHeadContext=new nsDTDContext(); mBodyContext=new nsDTDContext(); - if(!gHTMLElements) { - InitializeElementTable(); - } - mNodeRecycler=0; #ifdef RICKG_DEBUG @@ -178,13 +175,6 @@ CNavDTD::CNavDTD() : nsIDTD(), #endif } -void CNavDTD::ReleaseTable(void) { - if(gHTMLElements) { - delete [] gHTMLElements; //fixed bug 49564 - gHTMLElements=0; - } -} - /** * This method recycles the nodes on a nodestack. * NOTE: Unlike recycleNode(), we force the usecount @@ -347,7 +337,7 @@ eAutoDetectResult CNavDTD::CanParse(CParserContext& aParserContext,nsString& aBu if(BufferContainsHTML(aBuffer,theBufHasXML)){ result = eValidDetect ; if(0==aParserContext.mMimeType.Length()) { - aParserContext.SetMimeType(NS_ConvertToString(kHTMLTextContentType)); + aParserContext.SetMimeType(NS_ConvertASCIItoUCS2(kHTMLTextContentType, sizeof(kHTMLTextContentType))); if(!theBufHasXML) { switch(aParserContext.mDTDMode) { case eDTDMode_strict: @@ -455,13 +445,13 @@ nsresult CNavDTD::BuildModel(nsIParser* aParser,nsITokenizer* aTokenizer,nsIToke CStartToken* theToken=nsnull; if(ePlainText==mDocType) { //we do this little trick for text files, in both normal and viewsource mode... - theToken=(CStartToken*)mTokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_pre); + theToken=NS_STATIC_CAST(CStartToken*,mTokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_pre)); if(theToken) { mTokenizer->PushTokenFront(theToken); } } //if the content model is empty, then begin by opening ... - theToken=(CStartToken*)mTokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_html,NS_ConvertToString("html")); + theToken=NS_STATIC_CAST(CStartToken*,mTokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_html,NS_ConvertToString("html"))); if(theToken) { mTokenizer->PushTokenFront(theToken); //this token should get pushed on the context stack. } @@ -514,7 +504,7 @@ nsresult CNavDTD::DidBuildModel(nsresult anErrorCode,PRBool aNotifySink,nsIParse mSkipTarget=eHTMLTag_unknown; //clear this in case we were searching earlier. - CStartToken *theToken=(CStartToken*)mTokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_body,NS_ConvertToString("body")); + CStartToken *theToken=NS_STATIC_CAST(CStartToken*,mTokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_body,NS_ConvertToString("body"))); mTokenizer->PushTokenFront(theToken); //this token should get pushed on the context stack, don't recycle it result=BuildModel(aParser,mTokenizer,0,aSink); } @@ -524,7 +514,7 @@ nsresult CNavDTD::DidBuildModel(nsresult anErrorCode,PRBool aNotifySink,nsIParse if((NS_OK==anErrorCode) && (mBodyContext->GetCount()>0)) { if(mSkipTarget) { CHTMLToken* theEndToken=nsnull; - theEndToken=(CHTMLToken*)mTokenAllocator->CreateTokenOfType(eToken_end,mSkipTarget); + theEndToken=NS_STATIC_CAST(CHTMLToken*,mTokenAllocator->CreateTokenOfType(eToken_end,mSkipTarget)); if(theEndToken) { result=HandleToken(theEndToken,mParser); } @@ -629,7 +619,7 @@ nsresult CNavDTD::HandleToken(CToken* aToken,nsIParser* aParser){ nsresult result=NS_OK; if(aToken) { - CHTMLToken* theToken= (CHTMLToken*)(aToken); + CHTMLToken* theToken= NS_STATIC_CAST(CHTMLToken*, aToken); eHTMLTokenTypes theType=eHTMLTokenTypes(theToken->GetTokenType()); eHTMLTags theTag=(eHTMLTags)theToken->GetTypeID(); PRBool execSkipContent=PR_FALSE; @@ -723,7 +713,7 @@ nsresult CNavDTD::HandleToken(CToken* aToken,nsIParser* aParser){ //However, in quirks mode, a few tags request, ambiguosly, for a BODY. - Bugs 18928, 24204.- mMisplacedContent.Push(aToken); if(mDTDMode==eDTDMode_quirks && (gHTMLElements[theTag].HasSpecialProperty(kRequiresBody))) { - CToken* theBodyToken=(CToken*)mTokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_body,NS_ConvertToString("body")); + CToken* theBodyToken=NS_STATIC_CAST(CToken*,mTokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_body,NS_ConvertToString("body"))); result=HandleToken(theBodyToken,aParser); } return result; @@ -856,9 +846,10 @@ nsresult CNavDTD::DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag){ MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::DidHandleStartTag(), this=%p\n", this)); const nsString& theString=aNode.GetSkippedContent(); if(0CreateTokenOfType(eToken_text,eHTMLTag_text,theString); + CTextToken *theToken=NS_STATIC_CAST(CTextToken*,mTokenAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text,theString)); nsCParserNode theNode(theToken,0); - result=mSink->AddLeaf(theNode); //when the node get's destructed, so does the new token + result=mSink->AddLeaf(theNode); + IF_FREE(theToken); } MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::DidHandleStartTag(), this=%p\n", this)); START_TIMER() @@ -892,7 +883,7 @@ nsresult CNavDTD::DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag){ if(theCount) { PRInt32 theIndex=0; for(theIndex=0;theIndexCreateTokenOfType(eToken_attribute,aTag); + CAttributeToken* theToken= NS_STATIC_CAST(CAttributeToken*,mTokenAllocator->CreateTokenOfType(eToken_attribute,aTag)); if(theToken) { - theToken->mTextKey.AssignWithConversion("_moz-userdefined"); + theToken->SetKey(NS_LITERAL_STRING("_moz-userdefined")); aNode.AddAttribute(theToken); } } @@ -1266,7 +1257,7 @@ nsresult CNavDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsCParserNode CObserverService* theService=mParser->GetObserverService(); if(theService) { const nsISupportsParserBundle* bundle=mParser->GetParserBundle(); - result=theService->Notify(aTag,aNode,(void*)bundle, NS_ConvertToString(kHTMLTextContentType), mParser); + result=theService->Notify(aTag,aNode,(void*)bundle, mMimeType, mParser); } } @@ -1283,11 +1274,11 @@ nsresult CNavDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsCParserNode PRInt32 theCount=aNode.GetAttributeCount(); if(1CreateTokenOfType(eToken_attribute,eHTMLTag_unknown,theAttribute); - nsString& theKey=((CAttributeToken*)theToken)->GetKey(); - theKey.AssignWithConversion("_moz-type"); + ((CAttributeToken*)theToken)->SetKey(NS_LITERAL_STRING("_moz-type")); mTokenizer->PushTokenFront(theToken); // Pop out NAME and CHALLENGE attributes ( from the keygen NODE ) @@ -1837,7 +1827,7 @@ nsresult CNavDTD::HandleEndToken(CToken* aToken) { //to use
, even though that isn't a legitimate tag. if(eDTDMode_quirks==mDTDMode) { // Use recycler and pass the token thro' HandleToken() to fix bugs like 32782. - CHTMLToken* theToken = (CHTMLToken*)mTokenAllocator->CreateTokenOfType(eToken_start,theChildTag); + CHTMLToken* theToken = NS_STATIC_CAST(CHTMLToken*,mTokenAllocator->CreateTokenOfType(eToken_start,theChildTag)); result=HandleToken(theToken,mParser); } } @@ -1888,7 +1878,7 @@ nsresult CNavDTD::HandleEndToken(CToken* aToken) { if(!CanOmit(theParentTag,theChildTag,theParentContains)) { IF_HOLD(aToken); mTokenizer->PushTokenFront(aToken); //put this end token back... - CHTMLToken* theToken = (CHTMLToken*)mTokenAllocator->CreateTokenOfType(eToken_start,theChildTag); + CHTMLToken* theToken = NS_STATIC_CAST(CHTMLToken*,mTokenAllocator->CreateTokenOfType(eToken_start,theChildTag)); mTokenizer->PushTokenFront(theToken); //put this new token onto stack... } } @@ -2025,7 +2015,7 @@ nsresult CNavDTD::HandleEntityToken(CToken* aToken) { nsresult result=NS_OK; - nsString& theStr=aToken->GetStringValueXXX(); + nsAutoString theStr(aToken->GetStringValue()); PRUnichar theChar=theStr.CharAt(0); if((kHashsign!=theChar) && (-1==nsHTMLEntities::EntityToUnicode(theStr))){ @@ -2033,16 +2023,15 @@ nsresult CNavDTD::HandleEntityToken(CToken* aToken) { CNamedEntity *theEntity=mBodyContext->GetEntity(theStr); CToken *theToken=0; if(theEntity) { - theToken=(CTextToken*)mTokenAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text,theEntity->mValue); + theToken=NS_STATIC_CAST(CTextToken*,mTokenAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text,theEntity->mValue)); } else { //if you're here we have a bogus entity. //convert it into a text token. - theToken=(CTextToken*)mTokenAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text,NS_ConvertToString("&")); - if(theToken) { - nsString &theTokenStr=theToken->GetStringValueXXX(); - theTokenStr.Append(theStr); //should append the entity name; fix bug 51161. - } + nsAutoString entityName; + entityName.AssignWithConversion("&"); + entityName.Append(theStr); //should append the entity name; fix bug 51161. + theToken = mTokenAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text,entityName); } return HandleToken(theToken,mParser); //theToken should get recycled automagically... } @@ -2084,8 +2073,9 @@ nsresult CNavDTD::HandleCommentToken(CToken* aToken) { nsresult result=NS_OK; - nsString& theComment=aToken->GetStringValueXXX(); - mLineNumber += (theComment).CountChar(kNewLine); + CCommentToken* theToken = NS_STATIC_CAST(CCommentToken*,aToken); + const nsAReadableString& theComment = theToken->GetStringValue(); + mLineNumber += CountCharInReadable(theComment, PRUnichar(kNewLine)); nsCParserNode* theNode=mNodeRecycler->CreateNode(); if(theNode) { @@ -2203,8 +2193,9 @@ nsresult CNavDTD::HandleDocTypeDeclToken(CToken* aToken){ WriteTokenToLog(aToken); #endif - nsString& docTypeStr=aToken->GetStringValueXXX(); - mLineNumber += (docTypeStr).CountChar(kNewLine); + CDoctypeDeclToken* theToken = NS_STATIC_CAST(CDoctypeDeclToken*,aToken); + nsAutoString docTypeStr(theToken->GetStringValue()); + mLineNumber += docTypeStr.CountChar(kNewLine); PRInt32 len=docTypeStr.Length(); PRInt32 pos=docTypeStr.RFindChar(kGreaterThan); @@ -2212,6 +2203,7 @@ nsresult CNavDTD::HandleDocTypeDeclToken(CToken* aToken){ docTypeStr.Cut(pos,len-pos);// First remove '>' from the end. } docTypeStr.Cut(0,2); // Now remove "SetStringValue(docTypeStr); nsCParserNode* theNode=mNodeRecycler->CreateNode(); if(theNode) { @@ -2265,7 +2257,7 @@ nsresult CNavDTD::CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt32 eHTMLTags theSkipTarget=gHTMLElements[aTag].mSkipTarget; for(attr=0;attrPopToken(); if(theToken) { eHTMLTokenTypes theType=eHTMLTokenTypes(theToken->GetTokenType()); diff --git a/mozilla/htmlparser/src/CNavDTD.h b/mozilla/htmlparser/src/CNavDTD.h index 0e8a8d069ca..e9cfd65f7c6 100644 --- a/mozilla/htmlparser/src/CNavDTD.h +++ b/mozilla/htmlparser/src/CNavDTD.h @@ -481,7 +481,6 @@ CLASS_EXPORT_HTMLPARS CNavDTD : public nsIDTD { nsresult DoFragment(PRBool aFlag); - static void ReleaseTable(void); protected: diff --git a/mozilla/htmlparser/src/COtherDTD.cpp b/mozilla/htmlparser/src/COtherDTD.cpp index 8a5bd5cf7ef..9b2f7bcd696 100644 --- a/mozilla/htmlparser/src/COtherDTD.cpp +++ b/mozilla/htmlparser/src/COtherDTD.cpp @@ -174,13 +174,6 @@ COtherDTD::COtherDTD() : nsIDTD(), mSharedNodes(0) { #endif } -void COtherDTD::ReleaseTable(void) { - if(gElementTable) { - delete gElementTable; - gElementTable=0; - } -} - /** * This method creates a new parser node. It tries to get one from * the recycle list before allocating a new one. @@ -647,7 +640,7 @@ nsresult COtherDTD::DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag){ if(theCount) { PRInt32 theIndex=0; for(theIndex=0;theIndexGetStringValueXXX(); + nsAutoString theStr; + aToken->GetSource(theStr); PRUnichar theChar=theStr.CharAt(0); CToken *theToken=0; @@ -916,8 +910,10 @@ nsresult COtherDTD::HandleEntityToken(CToken* aToken) { else { //if you're here we have a bogus entity. //convert it into a text token. - theToken=(CTextToken*)mTokenAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text,NS_ConvertToString("&")); - + nsAutoString entityName; + entityName.AssignWithConversion("&"); + entityName.Append(theStr); //should append the entity name; fix bug 51161. + theToken=(CTextToken*)mTokenAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text,entityName); } result=HandleStartToken(theToken); } diff --git a/mozilla/htmlparser/src/COtherDTD.h b/mozilla/htmlparser/src/COtherDTD.h index 6297bdd6380..d2fd78f245e 100644 --- a/mozilla/htmlparser/src/COtherDTD.h +++ b/mozilla/htmlparser/src/COtherDTD.h @@ -311,8 +311,6 @@ CLASS_EXPORT_HTMLPARS COtherDTD : public nsIDTD { //by the parser to manage its context-stack. //************************************************* - static void ReleaseTable(void); - protected: nsresult CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt32 aCount); @@ -356,6 +354,7 @@ protected: extern NS_HTMLPARS nsresult NS_NewOtherHTMLDTD(nsIDTD** aInstancePtrResult); + CLASS_EXPORT_HTMLPARS CTransitionalDTD : public COtherDTD { public: diff --git a/mozilla/htmlparser/src/COtherElements.h b/mozilla/htmlparser/src/COtherElements.h index 8f542b343a7..6f261ba8817 100644 --- a/mozilla/htmlparser/src/COtherElements.h +++ b/mozilla/htmlparser/src/COtherElements.h @@ -1715,7 +1715,7 @@ public: nsCParserNode *theNode=(nsCParserNode*)aNode; nsresult result=NS_OK; if(theNode) { - nsString theStr=theNode->mToken->GetStringValueXXX(); + nsAutoString theStr(theNode->mToken->GetStringValue()); PRInt32 theLen=theStr.Length(); //PRInt32 thePos=theStr.RFindChar(kGreaterThan); diff --git a/mozilla/htmlparser/src/Makefile.in b/mozilla/htmlparser/src/Makefile.in index 97c9856e15c..933d6d5766f 100644 --- a/mozilla/htmlparser/src/Makefile.in +++ b/mozilla/htmlparser/src/Makefile.in @@ -60,7 +60,6 @@ CPPSRCS = \ nsElementTable.cpp \ CNavDTD.cpp \ COtherDTD.cpp \ - CRtfDTD.cpp \ nsHTMLEntities.cpp \ nsHTMLNullSink.cpp \ nsHTMLTags.cpp \ @@ -78,7 +77,6 @@ CPPSRCS = \ nsValidDTD.cpp \ nsWellFormedDTD.cpp \ nsViewSourceHTML.cpp \ - nsXIFDTD.cpp \ nsExpatDTD.cpp \ $(NULL) @@ -117,8 +115,6 @@ EXPORTS = \ COtherDTD.h \ nsWellFormedDTD.h \ nsValidDTD.h \ - CRtfDTD.h \ - nsXIFDTD.h \ nsParserCIID.h \ nsExpatDTD.h \ nsParserError.h \ diff --git a/mozilla/htmlparser/src/makefile.win b/mozilla/htmlparser/src/makefile.win index fdedcd06545..1546be84bfa 100644 --- a/mozilla/htmlparser/src/makefile.win +++ b/mozilla/htmlparser/src/makefile.win @@ -37,7 +37,6 @@ CPPSRCS= \ nsElementTable.cpp \ CNavDTD.cpp \ COtherDTD.cpp \ - CRtfDTD.cpp \ nsDTDDebug.cpp \ nsHTMLEntities.cpp \ nsHTMLNullSink.cpp \ @@ -55,11 +54,9 @@ CPPSRCS= \ nsValidDTD.cpp \ nsWellFormedDTD.cpp \ nsViewSourceHTML.cpp \ - nsXIFDTD.cpp \ nsExpatDTD.cpp \ prstrm.cpp \ nsParserModule.cpp \ - nsXIFDTD.cpp \ $(NULL) CPP_OBJS= \ @@ -70,7 +67,6 @@ CPP_OBJS= \ .\$(OBJDIR)\nsElementTable.obj \ .\$(OBJDIR)\CNavDTD.obj \ .\$(OBJDIR)\COtherDTD.obj \ - .\$(OBJDIR)\CRtfDTD.obj \ .\$(OBJDIR)\nsDTDDebug.obj \ .\$(OBJDIR)\nsHTMLEntities.obj \ .\$(OBJDIR)\nsHTMLNullSink.obj \ @@ -88,11 +84,9 @@ CPP_OBJS= \ .\$(OBJDIR)\nsValidDTD.obj \ .\$(OBJDIR)\nsWellFormedDTD.obj \ .\$(OBJDIR)\nsViewSourceHTML.obj \ - .\$(OBJDIR)\nsXIFDTD.obj \ .\$(OBJDIR)\nsExpatDTD.obj \ .\$(OBJDIR)\prstrm.obj \ .\$(OBJDIR)\nsParserModule.obj \ - .\$(OBJDIR)\nsXIFDTD.obj \ $(NULL) EXPORTS= \ @@ -119,10 +113,8 @@ EXPORTS= \ CNavDTD.h \ nsWellFormedDTD.h \ nsValidDTD.h \ - CRTFDTD.h \ COtherDTD.h \ nsIDTD.h \ - nsXIFDTD.h \ nsExpatDTD.h \ nsParserCIID.h \ nsParserError.h \ diff --git a/mozilla/htmlparser/src/nsDTDUtils.cpp b/mozilla/htmlparser/src/nsDTDUtils.cpp index 65d73a01952..bba36f66711 100644 --- a/mozilla/htmlparser/src/nsDTDUtils.cpp +++ b/mozilla/htmlparser/src/nsDTDUtils.cpp @@ -802,7 +802,7 @@ PRInt32 nsDTDContext::IncrementCounter(eHTMLTags aTag,nsCParserNode& aNode,nsStr CAbacus::eNumFormat theNumFormat=CAbacus::eDecimal; for(theIndex=0;theIndexAddRef(); } #define IF_FREE(_ptr) if(_ptr) { _ptr->Release(); _ptr=0; } // recycles _ptr @@ -226,9 +225,8 @@ public: nsTokenAllocator(); virtual ~nsTokenAllocator(); - virtual CToken* CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag, const nsString& aString); + virtual CToken* CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag, const nsAReadableString& aString); virtual CToken* CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag); - virtual CToken* CreateRTFTokenOfType(eRTFTokenTypes aType,eRTFTags aTag); protected: nsFixedSizeAllocator mArenaPool; diff --git a/mozilla/htmlparser/src/nsElementTable.cpp b/mozilla/htmlparser/src/nsElementTable.cpp index f9d081bf74f..21bd12e240c 100644 --- a/mozilla/htmlparser/src/nsElementTable.cpp +++ b/mozilla/htmlparser/src/nsElementTable.cpp @@ -1307,6 +1307,14 @@ void InitializeElementTable(void) { }//if }; +void DeleteElementTable(void) +{ + if(gHTMLElements) { + delete [] gHTMLElements; //fixed bug 49564 + gHTMLElements=0; + } +} + int nsHTMLElement::GetSynonymousGroups(eHTMLTags aTag) { int result=0; diff --git a/mozilla/htmlparser/src/nsElementTable.h b/mozilla/htmlparser/src/nsElementTable.h index 23e16a3675c..6c77d16aa24 100644 --- a/mozilla/htmlparser/src/nsElementTable.h +++ b/mozilla/htmlparser/src/nsElementTable.h @@ -78,7 +78,7 @@ static const int kAllTags = 0xffffff; extern void InitializeElementTable(void); - +extern void DeleteElementTable(void); /** * We're asking the question: is aTest a member of bitset. diff --git a/mozilla/htmlparser/src/nsExpatTokenizer.cpp b/mozilla/htmlparser/src/nsExpatTokenizer.cpp index b5d32e0c713..99e8b53aa88 100644 --- a/mozilla/htmlparser/src/nsExpatTokenizer.cpp +++ b/mozilla/htmlparser/src/nsExpatTokenizer.cpp @@ -44,10 +44,16 @@ typedef struct _XMLParserState { XML_Parser parser; + nsScanner* scanner; + const PRUnichar* bufferStart; + const PRUnichar* bufferEnd; + nsReadingIterator currentIterator; nsDeque* tokenDeque; nsTokenAllocator* tokenAllocator; - CToken* doctypeToken; - CToken* cdataToken; // Used by the begin and end handlers of the cdata section + nsString doctypeText; + PRBool indoctype; + nsString cdataText; + PRBool incdata; } XMLParserState; /************************************************************************ @@ -176,10 +182,10 @@ nsExpatTokenizer::nsExpatTokenizer(nsString* aURL) : nsHTMLTokenizer() { mBytesParsed = 0; mState = new XMLParserState; mState->tokenAllocator = nsnull; - mState->cdataToken = nsnull; mState->parser = nsnull; mState->tokenDeque = nsnull; - mState->doctypeToken = nsnull; + mState->indoctype = PR_FALSE; + mState->incdata = PR_FALSE; nsAutoString buffer; buffer.AssignWithConversion("UTF-16"); const PRUnichar* encoding = buffer.GetUnicode(); @@ -341,18 +347,15 @@ nsExpatTokenizer::AddErrorMessageTokens(nsParserError* aError) AddToken(newToken, NS_OK, mState->tokenDeque, mState->tokenAllocator); CAttributeToken* attrToken = (CAttributeToken*) - mState->tokenAllocator->CreateTokenOfType(eToken_attribute, eHTMLTag_unknown); - nsString& key = attrToken->GetKey(); - key.AssignWithConversion("xmlns"); - attrToken->SetCStringValue(kHTMLNameSpaceURI); + mState->tokenAllocator->CreateTokenOfType(eToken_attribute, eHTMLTag_unknown, NS_ConvertASCIItoUCS2(kHTMLNameSpaceURI)); + attrToken->SetKey(NS_LITERAL_STRING("xmlns")); newToken->SetAttributeCount(1); newToken = (CToken*) attrToken; AddToken(newToken, NS_OK, mState->tokenDeque, mState->tokenAllocator); nsAutoString textStr; CreateErrorText(aError, textStr); - newToken = mState->tokenAllocator->CreateTokenOfType(eToken_text, eHTMLTag_unknown); - newToken->SetStringValue(textStr); + newToken = mState->tokenAllocator->CreateTokenOfType(eToken_text, eHTMLTag_unknown, textStr); AddToken(newToken, NS_OK, mState->tokenDeque, mState->tokenAllocator); newToken = mState->tokenAllocator->CreateTokenOfType(eToken_start, eHTMLTag_sourcetext); @@ -360,8 +363,7 @@ nsExpatTokenizer::AddErrorMessageTokens(nsParserError* aError) textStr.Truncate(); CreateSourceText(aError, textStr); - newToken = mState->tokenAllocator->CreateTokenOfType(eToken_text, eHTMLTag_unknown); - newToken->SetStringValue(textStr); + newToken = mState->tokenAllocator->CreateTokenOfType(eToken_text, eHTMLTag_unknown,textStr); AddToken(newToken, NS_OK, mState->tokenDeque, mState->tokenAllocator); newToken = mState->tokenAllocator->CreateTokenOfType(eToken_end, eHTMLTag_sourcetext); @@ -470,19 +472,35 @@ nsresult nsExpatTokenizer::ConsumeToken(nsScanner& aScanner,PRBool& aFlushTokens // Ask the scanner to send us all the data it has // scanned and pass that data to expat. nsresult result = NS_OK; - nsString& theBuffer = aScanner.GetBuffer(); - PRUint32 bufLength = theBuffer.Length() * sizeof(PRUnichar); - const PRUnichar* expatBuffer = (bufLength) ? theBuffer.GetUnicode() : nsnull; - + nsReadingIterator start, end; + aScanner.CurrentPosition(start); + aScanner.EndReading(end); mState->tokenDeque = &mTokenDeque; mState->parser = mExpatParser; + mState->scanner = &aScanner; - result = ParseXMLBuffer((const char *)expatBuffer, bufLength); - - theBuffer.Truncate(0); + while (start != end) { + PRUint32 fragLength = PRUint32(start.size_forward()); + PRUint32 bufLength = fragLength * sizeof(PRUnichar); + const PRUnichar* expatBuffer = start.get(); + + mState->bufferStart = expatBuffer; + mState->bufferEnd = expatBuffer + fragLength; + mState->currentIterator = start; + result = ParseXMLBuffer((const char *)expatBuffer, bufLength); + if (NS_FAILED(result)) return result; + + start.advance(fragLength); + } + + aScanner.SetPosition(end, PR_TRUE); if(NS_OK==result) result=aScanner.Eof(); + + mState->scanner = nsnull; + mState->bufferStart = mState->bufferEnd = nsnull; + return result; } @@ -506,7 +524,7 @@ void nsExpatTokenizer::FrontloadMisplacedContent(nsDeque& aDeque){ void nsExpatTokenizer::HandleStartElement(void *userData, const XML_Char *name, const XML_Char **atts) { XMLParserState* state = (XMLParserState*) userData; - CToken* theToken = state->tokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_unknown); + CToken* theToken = state->tokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_unknown, nsLiteralString((PRUnichar*)name)); if(theToken) { // If an ID attribute exists for this element, set it on the start token PRInt32 index = XML_GetIdAttributeIndex(state->parser); @@ -516,9 +534,6 @@ void nsExpatTokenizer::HandleStartElement(void *userData, const XML_Char *name, startToken->SetIDAttributeAtom(attributeAtom); } - // Set the element name on the start token and add the token to the token queue - nsString& theString=theToken->GetStringValueXXX(); - theString.Assign((PRUnichar *) name); AddToken(theToken, NS_OK, state->tokenDeque, state->tokenAllocator); // For each attribute on this element, create and add attribute tokens to the token queue @@ -526,15 +541,25 @@ void nsExpatTokenizer::HandleStartElement(void *userData, const XML_Char *name, while(*atts){ theAttrCount++; CAttributeToken* theAttrToken = (CAttributeToken*) - state->tokenAllocator->CreateTokenOfType(eToken_attribute, eHTMLTag_unknown); + state->tokenAllocator->CreateTokenOfType(eToken_attribute, eHTMLTag_unknown, nsLiteralString((PRUnichar*)atts[1])); if(theAttrToken){ - nsString& theKey=theAttrToken->GetKey(); - theKey.Assign((PRUnichar *) (*atts++)); - nsString& theValue=theAttrToken->GetStringValueXXX(); - theValue.Assign((PRUnichar *) (*atts++)); + PRUnichar* ptr = (PRUnichar*)atts[0]; + if ((ptr >= state->bufferStart) && (ptr < state->bufferEnd)) { + PRUint32 len = nsCRT::strlen(ptr); + nsReadingIterator start, end; + start = state->currentIterator; + start.advance(ptr - state->bufferStart); + end = start; + end.advance(len); + theAttrToken->BindKey(state->scanner, start, end); + } + else { + theAttrToken->SetKey(nsLiteralString(ptr)); + } } CToken* theTok=(CToken*)theAttrToken; AddToken(theTok, NS_OK, state->tokenDeque, state->tokenAllocator); + atts += 2; } theToken->SetAttributeCount(theAttrCount); } @@ -545,10 +570,8 @@ void nsExpatTokenizer::HandleStartElement(void *userData, const XML_Char *name, void nsExpatTokenizer::HandleEndElement(void *userData, const XML_Char *name) { XMLParserState* state = (XMLParserState*) userData; - CToken* theToken = state->tokenAllocator->CreateTokenOfType(eToken_end,eHTMLTag_unknown); + CToken* theToken = state->tokenAllocator->CreateTokenOfType(eToken_end,eHTMLTag_unknown, nsLiteralString((PRUnichar *) name)); if(theToken) { - nsString& theString=theToken->GetStringValueXXX(); - theString.Assign((PRUnichar *) name); AddToken(theToken, NS_OK, state->tokenDeque, state->tokenAllocator); } else{ @@ -558,13 +581,11 @@ void nsExpatTokenizer::HandleEndElement(void *userData, const XML_Char *name) { void nsExpatTokenizer::HandleCharacterData(void *userData, const XML_Char *s, int len) { XMLParserState* state = (XMLParserState*) userData; - CCDATASectionToken* currentCDataToken = (CCDATASectionToken*) state->cdataToken; - if (currentCDataToken) { - // While there exists a current CDATA token, keep appending all strings + if (state->incdata) { + // While we're in a CDATASection, keep appending all strings // from expat into it. - nsString& theString = currentCDataToken->GetStringValueXXX(); - theString.Append((PRUnichar *) s,len); + state->cdataText.Append((PRUnichar *) s,len); } else { CToken* newToken = 0; @@ -575,17 +596,28 @@ void nsExpatTokenizer::HandleCharacterData(void *userData, const XML_Char *s, in break; case kSpace: case kTab: - newToken = state->tokenAllocator->CreateTokenOfType(eToken_whitespace,eHTMLTag_unknown); + newToken = state->tokenAllocator->CreateTokenOfType(eToken_whitespace,eHTMLTag_unknown, nsLiteralString((PRUnichar*)s, len)); break; default: - newToken = state->tokenAllocator->CreateTokenOfType(eToken_text,eHTMLTag_unknown); + { + CTextToken* textToken = (CTextToken*)state->tokenAllocator->CreateTokenOfType(eToken_text, eHTMLTag_unknown); + PRUnichar* ptr = (PRUnichar*)s; + if ((ptr >= state->bufferStart) && (ptr < state->bufferEnd)) { + nsReadingIterator start, end; + start = state->currentIterator; + start.advance(ptr - state->bufferStart); + end = start; + end.advance(len); + textToken->Bind(state->scanner, start, end); + } + else { + textToken->Bind(nsLiteralString(ptr, len)); + } + newToken = textToken; + } } if(newToken) { - if ((((PRUnichar*)s)[0] != (XML_Char)kNewLine) && (((PRUnichar*)s)[0] != (XML_Char)kCR)) { - nsString& theString=newToken->GetStringValueXXX(); - theString.Append((PRUnichar *) s,len); - } AddToken(newToken, NS_OK, state->tokenDeque, state->tokenAllocator); } else { @@ -596,10 +628,8 @@ void nsExpatTokenizer::HandleCharacterData(void *userData, const XML_Char *s, in void nsExpatTokenizer::HandleComment(void *userData, const XML_Char *name) { XMLParserState* state = (XMLParserState*) userData; - CToken* theToken = state->tokenAllocator->CreateTokenOfType(eToken_comment, eHTMLTag_unknown); + CToken* theToken = state->tokenAllocator->CreateTokenOfType(eToken_comment, eHTMLTag_unknown, nsLiteralString((PRUnichar*)name)); if(theToken) { - nsString& theString=theToken->GetStringValueXXX(); - theString.Assign((PRUnichar *) name); AddToken(theToken, NS_OK, state->tokenDeque, state->tokenAllocator); } else{ @@ -609,21 +639,22 @@ void nsExpatTokenizer::HandleComment(void *userData, const XML_Char *name) { void nsExpatTokenizer::HandleStartCdataSection(void *userData) { XMLParserState* state = (XMLParserState*) userData; - CToken* cdataToken = state->tokenAllocator->CreateTokenOfType(eToken_cdatasection, - eHTMLTag_unknown); - state->cdataToken = cdataToken; + state->incdata = PR_TRUE; } void nsExpatTokenizer::HandleEndCdataSection(void *userData) { XMLParserState* state = (XMLParserState*) userData; - CToken* currentCDataToken = (CToken*) state->cdataToken; + CToken* cdataToken = state->tokenAllocator->CreateTokenOfType(eToken_cdatasection, + eHTMLTag_unknown, + state->cdataText); // We've reached the end of the current CDATA section. Push the current // CDATA token onto the token queue - AddToken(currentCDataToken, NS_OK, state->tokenDeque, state->tokenAllocator); + AddToken(cdataToken, NS_OK, state->tokenDeque, state->tokenAllocator); - state->cdataToken = nsnull; + state->incdata = PR_FALSE; + state->cdataText.Truncate(); } void nsExpatTokenizer::HandleProcessingInstruction(void *userData, @@ -631,16 +662,17 @@ void nsExpatTokenizer::HandleProcessingInstruction(void *userData, const XML_Char *data) { XMLParserState* state = (XMLParserState*) userData; - CToken* theToken = state->tokenAllocator->CreateTokenOfType(eToken_instruction,eHTMLTag_unknown); + nsAutoString theString; + theString. AppendWithConversion(""); + + CToken* theToken = state->tokenAllocator->CreateTokenOfType(eToken_instruction,eHTMLTag_unknown, theString); if(theToken) { - nsString& theString=theToken->GetStringValueXXX(); - theString. AppendWithConversion(""); AddToken(theToken, NS_OK, state->tokenDeque, state->tokenAllocator); } else{ @@ -650,9 +682,8 @@ void nsExpatTokenizer::HandleProcessingInstruction(void *userData, void nsExpatTokenizer::HandleDefault(void *userData, const XML_Char *s, int len) { XMLParserState* state = (XMLParserState*) userData; - if (state->doctypeToken) { - nsString& doctypestr = state->doctypeToken->GetStringValueXXX(); - doctypestr.Append((PRUnichar*)s, len); + if (state->indoctype) { + state->doctypeText.Append((PRUnichar*)s, len); } else { nsAutoString str((PRUnichar *)s, len); @@ -872,23 +903,20 @@ void nsExpatTokenizer::HandleStartDoctypeDecl(void *userData, const XML_Char *doctypeName) { XMLParserState* state = (XMLParserState*) userData; - CToken* token = state->tokenAllocator->CreateTokenOfType(eToken_doctypeDecl, eHTMLTag_unknown); - if (token) { - nsString& str = token->GetStringValueXXX(); - str.AppendWithConversion(kDocTypeDeclPrefix); - state->doctypeToken = token; - } + state->indoctype = PR_TRUE; + state->doctypeText.Assign((PRUnichar*)kDocTypeDeclPrefix); } void nsExpatTokenizer::HandleEndDoctypeDecl(void *userData) { XMLParserState* state = (XMLParserState*) userData; - CToken* token = state->doctypeToken; + + state->doctypeText.AppendWithConversion(">"); + CToken* token = state->tokenAllocator->CreateTokenOfType(eToken_doctypeDecl, eHTMLTag_unknown, state->doctypeText); if (token) { - nsString& str = token->GetStringValueXXX(); - str.AppendWithConversion(">"); AddToken(token, NS_OK, state->tokenDeque, state->tokenAllocator); - state->doctypeToken = nsnull; } + state->indoctype = PR_FALSE; + state->doctypeText.Truncate(); // Do nothing } diff --git a/mozilla/htmlparser/src/nsHTMLContentSinkStream.cpp b/mozilla/htmlparser/src/nsHTMLContentSinkStream.cpp index 04fcede6a29..47cc43332db 100644 --- a/mozilla/htmlparser/src/nsHTMLContentSinkStream.cpp +++ b/mozilla/htmlparser/src/nsHTMLContentSinkStream.cpp @@ -272,7 +272,7 @@ void nsHTMLContentSinkStream::EnsureBufferSize(PRInt32 aNewSize) * @param aString - the string to write. * @return The number of characters written. */ -PRInt32 nsHTMLContentSinkStream::Write(const nsString& aString) +PRInt32 nsHTMLContentSinkStream::Write(const nsAReadableString& aString) { if (mBodyOnly && !mInBody) return 0; @@ -289,7 +289,7 @@ PRInt32 nsHTMLContentSinkStream::Write(const nsString& aString) { nsresult res; PRUnichar *encodedBuffer = nsnull; - res = mEntityConverter->ConvertToEntities(aString.GetUnicode(), + res = mEntityConverter->ConvertToEntities(nsPromiseFlatString(aString), nsIEntityConverter::html40Latin1, &encodedBuffer); if (NS_SUCCEEDED(res) && encodedBuffer) @@ -328,7 +328,7 @@ PRInt32 nsHTMLContentSinkStream::Write(const nsString& aString) { // Call the converter to convert to the target charset. // Convert() takes a char* output param even though it's writing unicode. - res = mCharsetEncoder->Convert(aString.GetUnicode(), &encodedBuffer); + res = mCharsetEncoder->Convert(nsPromiseFlatString(aString), &encodedBuffer); if (NS_SUCCEEDED(res) && encodedBuffer) { charsWritten = nsCRT::strlen(encodedBuffer); @@ -339,7 +339,7 @@ PRInt32 nsHTMLContentSinkStream::Write(const nsString& aString) // If it didn't work, just write the unicode else { - const PRUnichar* unicode = aString.GetUnicode(); + const PRUnichar* unicode = nsPromiseFlatString(aString); charsWritten = aString.Length(); out.write(unicode, charsWritten); } @@ -348,7 +348,7 @@ PRInt32 nsHTMLContentSinkStream::Write(const nsString& aString) // If we couldn't get an encoder, just write the unicode else { - const PRUnichar* unicode = aString.GetUnicode(); + const PRUnichar* unicode = nsPromiseFlatString(aString); charsWritten = aString.Length(); out.write(unicode, charsWritten); } @@ -399,7 +399,7 @@ void nsHTMLContentSinkStream::WriteAttributes(const nsIParserNode& aNode) if(theCount) { int i=0; for(i=0;i 0) { Write(text); @@ -884,7 +884,7 @@ nsHTMLContentSinkStream::AddLeaf(const nsIParserNode& aNode) { if (!mDoFormat || mPreLevel > 0) { - const nsString& text = aNode.GetText(); + const nsAReadableString& text = aNode.GetText(); Write(text); mColPos += text.Length(); } @@ -904,15 +904,14 @@ nsHTMLContentSinkStream::AddLeaf(const nsIParserNode& aNode) // See if the string has any lines longer than longLineLen: // if so, we presume formatting is wonky (e.g. the node has been edited) // and we'd better rewrap the whole text node. -PRBool nsHTMLContentSinkStream::HasLongLines(const nsString& text) +PRBool nsHTMLContentSinkStream::HasLongLines(const nsAReadableString& text) { const PRUint32 longLineLen = 128; - nsString str = text; PRUint32 start=0; PRUint32 theLen=text.Length(); for (start = 0; start < theLen; ) { - PRInt32 eol = text.FindChar('\n', PR_FALSE, start); + PRInt32 eol = text.FindChar('\n', start); if (eol < 0) eol = text.Length(); if ((PRUint32)(eol - start) > longLineLen) return PR_TRUE; @@ -921,7 +920,7 @@ PRBool nsHTMLContentSinkStream::HasLongLines(const nsString& text) return PR_FALSE; } -void nsHTMLContentSinkStream::WriteWrapped(const nsString& text) +void nsHTMLContentSinkStream::WriteWrapped(const nsAReadableString& text) { // 1. Determine the length of the input string PRInt32 length = text.Length(); @@ -935,7 +934,7 @@ void nsHTMLContentSinkStream::WriteWrapped(const nsString& text) } else { - nsString str = text; + nsAutoString str(text); PRBool done = PR_FALSE; PRInt32 indx = 0; PRInt32 offset = mColPos; @@ -1051,16 +1050,16 @@ nsHTMLContentSinkStream::OpenContainer(const nsIParserNode& aNode) PRInt32 count=aNode.GetAttributeCount(); for(PRInt32 i=0;i" << endl; - delete[] cp; } #endif diff --git a/mozilla/htmlparser/src/nsHTMLToTXTSinkStream.cpp b/mozilla/htmlparser/src/nsHTMLToTXTSinkStream.cpp index 41768f72ded..2b99e82364a 100644 --- a/mozilla/htmlparser/src/nsHTMLToTXTSinkStream.cpp +++ b/mozilla/htmlparser/src/nsHTMLToTXTSinkStream.cpp @@ -449,8 +449,8 @@ nsHTMLToTXTSinkStream::GetValueOfAttribute(const nsIParserNode& aNode, PRInt32 count=aNode.GetAttributeCount(); for (PRInt32 i=0;i 1 && mTagStack[mTagStackIndex-2] == eHTMLTag_select) { diff --git a/mozilla/htmlparser/src/nsHTMLTokenizer.cpp b/mozilla/htmlparser/src/nsHTMLTokenizer.cpp index 8bfca2430d5..4e82e5744ec 100644 --- a/mozilla/htmlparser/src/nsHTMLTokenizer.cpp +++ b/mozilla/htmlparser/src/nsHTMLTokenizer.cpp @@ -33,6 +33,7 @@ #include "nsElementTable.h" #include "nsHTMLEntities.h" #include "CParserContext.h" +#include "nsReadableUtils.h" /************************************************************************ And now for the main class -- nsHTMLTokenizer... @@ -441,7 +442,7 @@ nsresult nsHTMLTokenizer::ConsumeToken(nsScanner& aScanner,PRBool& aFlushTokens) PRUnichar theChar; CToken* theToken=0; - nsresult result=aScanner.GetChar(theChar); + nsresult result=aScanner.Peek(theChar); switch(result) { case kEOF: @@ -468,8 +469,7 @@ nsresult nsHTMLTokenizer::ConsumeToken(nsScanner& aScanner,PRBool& aFlushTokens) } else { if(!nsCRT::IsAsciiSpace(theChar)) { - nsAutoString temp(theChar); - result=ConsumeText(temp,theToken,aScanner); + result=ConsumeText(theToken,aScanner); break; } result=ConsumeWhitespace(theChar,theToken,aScanner); @@ -494,16 +494,19 @@ nsresult nsHTMLTokenizer::ConsumeToken(nsScanner& aScanner,PRBool& aFlushTokens) */ nsresult nsHTMLTokenizer::ConsumeTag(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner,PRBool& aFlushTokens) { - nsresult result=aScanner.GetChar(aChar); + PRUnichar theNextChar, oldChar; + nsresult result=aScanner.Peek(aChar,1); if(NS_OK==result) { switch(aChar) { case kForwardSlash: - PRUnichar ch; - result=aScanner.Peek(ch); + // Get the original "<" (we've already seen it with a Peek) + aScanner.GetChar(oldChar); + + result=aScanner.Peek(theNextChar, 1); if(NS_OK==result) { - if(nsCRT::IsAsciiAlpha(ch)||(kGreaterThan==ch)) { + if(nsCRT::IsAsciiAlpha(theNextChar)||(kGreaterThan==theNextChar)) { result=ConsumeEndTag(aChar,aToken,aScanner); } else result=ConsumeComment(aChar,aToken,aScanner); @@ -511,8 +514,10 @@ nsresult nsHTMLTokenizer::ConsumeTag(PRUnichar aChar,CToken*& aToken,nsScanner& break; case kExclamation: - PRUnichar theNextChar; - result=aScanner.Peek(theNextChar); + // Get the original "<" (we've already seen it with a Peek) + aScanner.GetChar(oldChar); + + result=aScanner.Peek(theNextChar, 1); if(NS_OK==result) { if((kMinus==theNextChar) || (kGreaterThan==theNextChar)) { result=ConsumeComment(aChar,aToken,aScanner); @@ -523,18 +528,21 @@ nsresult nsHTMLTokenizer::ConsumeTag(PRUnichar aChar,CToken*& aToken,nsScanner& break; case kQuestionMark: //it must be an XML processing instruction... + // Get the original "<" (we've already seen it with a Peek) + aScanner.GetChar(oldChar); result=ConsumeProcessingInstruction(aChar,aToken,aScanner); break; default: - if(nsCRT::IsAsciiAlpha(aChar)) + if(nsCRT::IsAsciiAlpha(aChar)) { + // Get the original "<" (we've already seen it with a Peek) + aScanner.GetChar(oldChar); result=ConsumeStartTag(aChar,aToken,aScanner,aFlushTokens); + } else if(kEOF!=aChar) { - // We are not dealing with a tag. So, put back the char - // and leave the decision to ConsumeText(). - aScanner.PutBack(aChar); - nsAutoString temp; temp.AssignWithConversion("<"); - result=ConsumeText(temp,aToken,aScanner); + // We are not dealing with a tag. So, don't consume the original + // char and leave the decision to ConsumeText(). + result=ConsumeText(aToken,aScanner); } } //switch @@ -552,7 +560,7 @@ nsresult nsHTMLTokenizer::ConsumeTag(PRUnichar aChar,CToken*& aToken,nsScanner& * @param aLeadingWS: contains ws chars that preceeded the first attribute * @return */ -nsresult nsHTMLTokenizer::ConsumeAttributes(PRUnichar aChar,CStartToken* aToken,nsScanner& aScanner,nsString& aLeadingWS) { +nsresult nsHTMLTokenizer::ConsumeAttributes(PRUnichar aChar,CStartToken* aToken,nsScanner& aScanner) { PRBool done=PR_FALSE; nsresult result=NS_OK; PRInt16 theAttrCount=0; @@ -560,13 +568,8 @@ nsresult nsHTMLTokenizer::ConsumeAttributes(PRUnichar aChar,CStartToken* aToken, nsTokenAllocator* theAllocator=this->GetTokenAllocator(); while((!done) && (result==NS_OK)) { - CToken* theToken= (CAttributeToken*)theAllocator->CreateTokenOfType(eToken_attribute,eHTMLTag_unknown); + CAttributeToken* theToken= NS_STATIC_CAST(CAttributeToken*, theAllocator->CreateTokenOfType(eToken_attribute,eHTMLTag_unknown)); if(theToken){ - if(aLeadingWS.Length()) { - nsString& theKey=((CAttributeToken*)theToken)->GetKey(); - theKey=aLeadingWS; - aLeadingWS.Truncate(0); - } result=theToken->Consume(aChar,aScanner,PRBool(eViewSource==mParserCommand)); //tell new token to finish consuming text... //Much as I hate to do this, here's some special case code. @@ -575,8 +578,8 @@ nsresult nsHTMLTokenizer::ConsumeAttributes(PRUnichar aChar,CStartToken* aToken, //and a textkey of "/". We should destroy it, and tell the //start token it was empty. if(NS_SUCCEEDED(result)) { - nsString& key=((CAttributeToken*)theToken)->GetKey(); - nsString& text=theToken->GetStringValueXXX(); + const nsAReadableString& key=theToken->GetKey(); + const nsAReadableString& text=theToken->GetValue(); if((mDoXMLEmptyTags) && (kForwardSlash==key.CharAt(0)) && (0==text.Length())){ //tada! our special case! Treat it like an empty start tag... aToken->SetEmpty(PR_TRUE); @@ -584,7 +587,7 @@ nsresult nsHTMLTokenizer::ConsumeAttributes(PRUnichar aChar,CStartToken* aToken, } else { theAttrCount++; - AddToken(theToken,result,&mTokenDeque,theAllocator); + AddToken((CToken*&)theToken,result,&mTokenDeque,theAllocator); } } else { //if(NS_ERROR_HTMLPARSER_BADATTRIBUTE==result){ @@ -654,7 +657,10 @@ nsresult nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar,CToken*& aToken,nsScan aToken=theAllocator->CreateTokenOfType(eToken_start,eHTMLTag_unknown); if(aToken) { - ((CStartToken*)aToken)->mOrigin=aScanner.GetOffset()-1; // Save the position after '<' for use in recording traling contents. Ref: Bug. 15204. + // Save the position after '<' for use in recording traling contents. Ref: Bug. 15204. + nsReadingIterator origin; + aScanner.CurrentPosition(origin); + PRBool isHTML=((eHTML3Text==mDocType) || (eHTML4Text==mDocType)); result= aToken->Consume(aChar,aScanner,isHTML); //tell new token to finish consuming text... @@ -665,25 +671,33 @@ nsresult nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar,CToken*& aToken,nsScan //Good. Now, let's see if the next char is ">". //If so, we have a complete tag, otherwise, we have attributes. - nsString &theScratchStr=GetScratchString(); PRBool theTagHasAttributes=PR_FALSE; + nsReadingIterator start, end; if(NS_OK==result) { - result=(eViewSource==mParserCommand) ? aScanner.ReadWhitespace(theScratchStr) : aScanner.SkipWhitespace(); + result=(eViewSource==mParserCommand) ? aScanner.ReadWhitespace(start, end) : aScanner.SkipWhitespace(); aToken->mNewlineCount += aScanner.GetNewlinesSkipped(); if(NS_OK==result) { - result=aScanner.GetChar(aChar); + result=aScanner.Peek(aChar); if(NS_OK==result) { if(kGreaterThan!=aChar) { //look for '>' //push that char back, since we apparently have attributes... - result=aScanner.PutBack(aChar); theTagHasAttributes=PR_TRUE; } //if + else { + aScanner.GetChar(aChar); + } } //if }//if } if(theTagHasAttributes) { - result=ConsumeAttributes(aChar,(CStartToken*)aToken,aScanner,theScratchStr); + if (eViewSource==mParserCommand) { + // Since we conserve whitespace in view-source mode, + // go back to the beginning of the whitespace section + // and let the first attribute grab it. + aScanner.SetPosition(start, PR_FALSE, PR_TRUE); + } + result=ConsumeAttributes(aChar,(CStartToken*)aToken,aScanner); } /* Now that that's over with, we have one more problem to solve. @@ -699,7 +713,7 @@ nsresult nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar,CToken*& aToken,nsScan } if(mRecordTrailingContent) - RecordTrailingContent((CStartToken*)aToken,aScanner); + RecordTrailingContent((CStartToken*)aToken,aScanner,origin); //if((eHTMLTag_style==theTag) || (eHTMLTag_script==theTag)) { if(gHTMLElements[theTag].CanContainType(kCDATA)) { @@ -739,6 +753,9 @@ nsresult nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar,CToken*& aToken,nsScan * @return */ nsresult nsHTMLTokenizer::ConsumeEndTag(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner) { + + // Get the "/" (we've already seen it with a Peek) + aScanner.GetChar(aChar); nsTokenAllocator* theAllocator=this->GetTokenAllocator(); aToken=theAllocator->CreateTokenOfType(eToken_end,eHTMLTag_unknown); @@ -749,7 +766,8 @@ nsresult nsHTMLTokenizer::ConsumeEndTag(PRUnichar aChar,CToken*& aToken,nsScanne if((theTag==eHTMLTag_textarea || theTag==eHTMLTag_xmp) && mRecordTrailingContent) { mRecordTrailingContent=PR_FALSE; } - result= aToken->Consume(aChar,aScanner,mParseMode); //tell new token to finish consuming text... + PRBool isHTML=((eHTML3Text==mDocType) || (eHTML4Text==mDocType)); + result= aToken->Consume(aChar,aScanner,isHTML); //tell new token to finish consuming text... AddToken(aToken,result,&mTokenDeque,theAllocator); } //if return result; @@ -767,39 +785,33 @@ nsresult nsHTMLTokenizer::ConsumeEndTag(PRUnichar aChar,CToken*& aToken,nsScanne */ nsresult nsHTMLTokenizer::ConsumeEntity(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner) { PRUnichar theChar; - nsresult result=aScanner.GetChar(theChar); + nsresult result=aScanner.Peek(theChar, 1); nsTokenAllocator* theAllocator=this->GetTokenAllocator(); if(NS_OK==result) { if(nsCRT::IsAsciiAlpha(theChar)) { //handle common enity references &xxx; or �. + // Get the "&" + aScanner.GetChar(theChar); aToken = theAllocator->CreateTokenOfType(eToken_entity,eHTMLTag_entity); + + // Get the first entity character + aScanner.GetChar(theChar); result = aToken->Consume(theChar,aScanner,mParseMode); //tell new token to finish consuming text... } else if(kHashsign==theChar) { + // Get the "&" + aScanner.GetChar(theChar); aToken = theAllocator->CreateTokenOfType(eToken_entity,eHTMLTag_entity); + + // Get the first numerical entity character + aScanner.GetChar(theChar); result=aToken->Consume(theChar,aScanner,mParseMode); } else { //oops, we're actually looking at plain text... - nsAutoString temp; temp.AssignWithConversion("&"); - aScanner.PutBack(theChar); - return ConsumeText(temp,aToken,aScanner); + return ConsumeText(aToken,aScanner); }//if if(aToken){ -#if 0 - nsString& theStr=aToken->GetStringValueXXX(); - - if((kHashsign!=theChar) && (-1==nsHTMLEntities::EntityToUnicode(theStr))){ - //if you're here we have a bogus entity. - //convert it into a text token. - nsAutoString temp; temp.AssignWithConversion("&"); - temp.Append(theStr); - CToken* theToken=theAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text,temp); - IF_FREE(aToken); - aToken=theToken; - } -#endif - if(mIsFinalChunk && (kEOF==result)) { result=NS_OK; //use as much of the entity as you can get. } @@ -821,6 +833,9 @@ nsresult nsHTMLTokenizer::ConsumeEntity(PRUnichar aChar,CToken*& aToken,nsScanne * @return new token or null */ nsresult nsHTMLTokenizer::ConsumeWhitespace(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner) { + // Get the whitespace character + aScanner.GetChar(aChar); + nsTokenAllocator* theAllocator=this->GetTokenAllocator(); aToken = theAllocator->CreateTokenOfType(eToken_whitespace,eHTMLTag_whitespace); nsresult result=NS_OK; @@ -842,6 +857,9 @@ nsresult nsHTMLTokenizer::ConsumeWhitespace(PRUnichar aChar,CToken*& aToken,nsSc * @return new token or null */ nsresult nsHTMLTokenizer::ConsumeComment(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner){ + // Get the "!" + aScanner.GetChar(aChar); + nsTokenAllocator* theAllocator=this->GetTokenAllocator(); aToken = theAllocator->CreateTokenOfType(eToken_comment,eHTMLTag_comment); nsresult result=NS_OK; @@ -862,21 +880,21 @@ nsresult nsHTMLTokenizer::ConsumeComment(PRUnichar aChar,CToken*& aToken,nsScann * @param anErrorCode: arg that will hold error condition * @return new token or null */ -nsresult nsHTMLTokenizer::ConsumeText(const nsString& aString,CToken*& aToken,nsScanner& aScanner){ +nsresult nsHTMLTokenizer::ConsumeText(CToken*& aToken,nsScanner& aScanner){ nsresult result=NS_OK; nsTokenAllocator* theAllocator=this->GetTokenAllocator(); - aToken=theAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text,aString); - if(aToken) { + CTextToken* theToken = (CTextToken*)theAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text); + if(theToken) { PRUnichar ch=0; - result=aToken->Consume(ch,aScanner,mParseMode); + result=theToken->Consume(ch,aScanner,mParseMode); if(!NS_SUCCEEDED(result)) { - nsString& temp=aToken->GetStringValueXXX(); - if(0==temp.Length()){ + if(0==theToken->GetTextLength()){ IF_FREE(aToken); aToken = nsnull; } else result=NS_OK; } + aToken = theToken; AddToken(aToken,result,&mTokenDeque,theAllocator); } return result; @@ -894,10 +912,13 @@ nsresult nsHTMLTokenizer::ConsumeText(const nsString& aString,CToken*& aToken,ns * @return new token or null */ nsresult nsHTMLTokenizer::ConsumeSpecialMarkup(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner){ + + // Get the "!" + aScanner.GetChar(aChar); + nsresult result=NS_OK; nsAutoString theBufCopy; - nsString& theBuffer=aScanner.GetBuffer(); - theBuffer.Mid(theBufCopy,aScanner.GetOffset(),20); + aScanner.Peek(theBufCopy, 20); theBufCopy.ToUpperCase(); PRInt32 theIndex=theBufCopy.Find("DOCTYPE"); nsTokenAllocator* theAllocator=this->GetTokenAllocator(); @@ -927,6 +948,9 @@ nsresult nsHTMLTokenizer::ConsumeSpecialMarkup(PRUnichar aChar,CToken*& aToken,n * @return error code */ nsresult nsHTMLTokenizer::ConsumeNewline(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner){ + // Get the newline character + aScanner.GetChar(aChar); + nsTokenAllocator* theAllocator=this->GetTokenAllocator(); aToken=theAllocator->CreateTokenOfType(eToken_newline,eHTMLTag_newline); nsresult result=NS_OK; @@ -948,6 +972,10 @@ nsresult nsHTMLTokenizer::ConsumeNewline(PRUnichar aChar,CToken*& aToken,nsScann * @return error code */ nsresult nsHTMLTokenizer::ConsumeProcessingInstruction(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner){ + + // Get the "?" + aScanner.GetChar(aChar); + nsTokenAllocator* theAllocator=this->GetTokenAllocator(); aToken=theAllocator->CreateTokenOfType(eToken_instruction,eHTMLTag_unknown); nsresult result=NS_OK; @@ -969,16 +997,20 @@ nsresult nsHTMLTokenizer::ConsumeProcessingInstruction(PRUnichar aChar,CToken*& * */ -void nsHTMLTokenizer::RecordTrailingContent(CStartToken* aStartToken, nsScanner& aScanner) { +void nsHTMLTokenizer::RecordTrailingContent(CStartToken* aStartToken, nsScanner& aScanner, nsReadingIterator aOrigin) { if(aStartToken) { - PRInt32 theOrigin =aStartToken->mOrigin; - PRInt32 theCurrOffset =aScanner.GetOffset(); - PRInt32 theLength =(theCurrOffset>theOrigin)? theCurrOffset-theOrigin:-1; - if(theLength>0) { - nsString& theRawXXX =aStartToken->mTrailingContent; - const PRUnichar* theBuff =(aScanner.GetBuffer()).GetUnicode(); - theRawXXX.Append(&theBuff[theOrigin],theLength); - } + nsReadingIterator theCurrentPosition; + aScanner.CurrentPosition(theCurrentPosition); + + nsString& trailingContent =aStartToken->mTrailingContent; + PRUint32 oldLength = trailingContent.Length(); + trailingContent.SetLength(oldLength + Distance(aOrigin, theCurrentPosition)); + + nsWritingIterator beginWriting; + trailingContent.BeginWriting(beginWriting); + beginWriting.advance(oldLength); + + copy_string( aOrigin, theCurrentPosition, beginWriting ); } } diff --git a/mozilla/htmlparser/src/nsHTMLTokenizer.h b/mozilla/htmlparser/src/nsHTMLTokenizer.h index 4af4ce9c1d8..a22553eeaa7 100644 --- a/mozilla/htmlparser/src/nsHTMLTokenizer.h +++ b/mozilla/htmlparser/src/nsHTMLTokenizer.h @@ -81,18 +81,18 @@ protected: virtual nsresult ConsumeTag(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner,PRBool& aFlushTokens); virtual nsresult ConsumeStartTag(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner,PRBool& aFlushTokens); virtual nsresult ConsumeEndTag(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner); - virtual nsresult ConsumeAttributes(PRUnichar aChar,CStartToken* aToken,nsScanner& aScanner,nsString& aLeadingWS); + virtual nsresult ConsumeAttributes(PRUnichar aChar,CStartToken* aToken,nsScanner& aScanner); virtual nsresult ConsumeEntity(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner); virtual nsresult ConsumeWhitespace(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner); virtual nsresult ConsumeComment(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner); virtual nsresult ConsumeNewline(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner); - virtual nsresult ConsumeText(const nsString& aString,CToken*& aToken,nsScanner& aScanner); + virtual nsresult ConsumeText(CToken*& aToken,nsScanner& aScanner); virtual nsresult ConsumeSpecialMarkup(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner); virtual nsresult ConsumeProcessingInstruction(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner); nsresult ScanDocStructure(PRBool aIsFinalChunk); - virtual void RecordTrailingContent(CStartToken* aStartToken,nsScanner& aScanner); + virtual void RecordTrailingContent(CStartToken* aStartToken, nsScanner& aScanner, nsReadingIterator aOrigin); static void AddToken(CToken*& aToken,nsresult aResult,nsDeque* aDeque,nsTokenAllocator* aTokenAllocator); diff --git a/mozilla/htmlparser/src/nsHTMLTokens.cpp b/mozilla/htmlparser/src/nsHTMLTokens.cpp index 63cbe84738f..61f94a0bdc8 100644 --- a/mozilla/htmlparser/src/nsHTMLTokens.cpp +++ b/mozilla/htmlparser/src/nsHTMLTokens.cpp @@ -32,7 +32,8 @@ #include "nsHTMLTags.h" #include "nsHTMLEntities.h" #include "nsCRT.h" - +#include "nsReadableUtils.h" +#include "nsScanner.h" static const char* gUserdefined = "userdefined"; @@ -42,17 +43,6 @@ static const char* gUserdefined = "userdefined"; And now for the token classes... **************************************************************/ -/* - * default constructor - * - * @update gess 3/25/98 - * @param - * @return - */ -CHTMLToken::CHTMLToken(const nsString& aName,eHTMLTags aTag) : CToken(aName) { - mTypeID=aTag; -} - /* * constructor from tag id * @@ -68,35 +58,6 @@ CHTMLToken::~CHTMLToken() { } -/** - * Setter method that changes the string value of this token - * @update gess5/11/98 - * @param name is a char* value containing new string value - */ -void CHTMLToken::SetCStringValue(const char* name){ - if(name) { - mTextValue.AssignWithConversion(name); - mTypeID = nsHTMLTags::LookupTag(mTextValue); - } -} - - -/** - * This method retrieves the value of this internal string. - * - * @update gess 3/25/98 - * @return nsString reference to internal string value - */ -nsString& CHTMLToken::GetStringValueXXX(void) { - - if((eHTMLTag_unknown" nsresult result=NS_OK; - if(0==aMode) { - nsSubsumeStr theSubstr; - result=aScanner.GetIdentifier(theSubstr,!aMode); + if(1==aMode) { + nsAutoString theSubstr; + result=aScanner.GetIdentifier(theSubstr,PR_TRUE); mTypeID = (PRInt32)nsHTMLTags::LookupTag(theSubstr); if(eHTMLTag_userdefined==mTypeID) { mTextValue=theSubstr; } } else { - mTextValue.Assign(aChar); - //added PR_TRUE to readId() call below to fix bug 46083. The problem was that the tag given //was written but since we didn't respect the '_', we only saw . Then //we searched for end title, which never comes (they give </title_>). @@ -303,6 +241,16 @@ void CStartToken::DebugDumpSource(nsOutputStream& out) { out << ">"; } +const nsAReadableString& CStartToken::GetStringValue() +{ + if((eHTMLTag_unknown<mTypeID) && (mTypeID<eHTMLTag_text)) { + if(!mTextValue.Length()) { + mTextValue.AssignWithConversion(nsHTMLTags::GetStringValue((nsHTMLTag) mTypeID)); + } + } + return mTextValue; +} + /* * * @@ -357,18 +305,11 @@ void CStartToken::AppendSource(nsString& anOutputString){ * @return */ CEndToken::CEndToken(eHTMLTags aTag) : CHTMLToken(aTag) { - SetCStringValue(GetTagName(aTag)); } -/* - * default constructor for end token - * - * @update gess 3/25/98 - * @param aName -- char* containing token name - * @return - */ -CEndToken::CEndToken(const nsString& aName) : CHTMLToken(aName) { +CEndToken::CEndToken(const nsAReadableString& aName,eHTMLTags aTag) : CHTMLToken(aTag) { + mTextValue.Assign(aName); } /* @@ -377,6 +318,7 @@ CEndToken::CEndToken(const nsString& aName) : CHTMLToken(aName) { * @update gess 3/25/98 * @param aChar -- last char consumed from stream * @param aScanner -- controller of underlying input source + * @param aMode -- 1=HTML; 0=text (or other ML) * @return error result */ nsresult CEndToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) { @@ -385,15 +327,41 @@ nsresult CEndToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) //Stop consuming as soon as you see a space or a '>'. //NOTE: We don't Consume the tag attributes here, nor do we eat the ">" - mTextValue.SetLength(0); - nsresult result=aScanner.ReadUntil(mTextValue,kGreaterThan,PR_FALSE); + nsresult result=NS_OK; + nsAutoString buffer; + PRInt32 offset; + if(1==aMode) { + nsAutoString theSubstr; + result=aScanner.ReadUntil(theSubstr,kGreaterThan,PR_FALSE); + if (NS_FAILED(result)) { + return result; + } + + offset = theSubstr.FindCharInSet(" \r\n\t\b",0); + if (offset != kNotFound) { + theSubstr.Left(buffer, offset); + mTypeID = nsHTMLTags::LookupTag(buffer); + } + else { + mTypeID = nsHTMLTags::LookupTag(theSubstr); + } + + if(eHTMLTag_userdefined==mTypeID) { + mTextValue=theSubstr; + } - if(NS_OK==result){ - nsAutoString buffer; - mTextValue.Left(buffer, mTextValue.FindCharInSet(" \r\n\t\b",0)); - mTypeID= nsHTMLTags::LookupTag(buffer); - result=aScanner.GetChar(aChar); //eat the closing '>; } + else { + mTextValue.SetLength(0); + result=aScanner.ReadUntil(mTextValue,kGreaterThan,PR_FALSE); + if (NS_FAILED(result)) { + return result; + } + mTypeID = eHTMLTag_userdefined; + } + + result=aScanner.GetChar(aChar); //eat the closing '>; + return result; } @@ -457,6 +425,16 @@ void CEndToken::DebugDumpSource(nsOutputStream& out) { out << "</" << buffer << ">"; } +const nsAReadableString& CEndToken::GetStringValue() +{ + if((eHTMLTag_unknown<mTypeID) && (mTypeID<eHTMLTag_text)) { + if(!mTextValue.Length()) { + mTextValue.AssignWithConversion(nsHTMLTags::GetStringValue((nsHTMLTag) mTypeID)); + } + } + return mTextValue; +} + /* * * @@ -466,7 +444,10 @@ void CEndToken::DebugDumpSource(nsOutputStream& out) { */ void CEndToken::GetSource(nsString& anOutputString){ anOutputString.AppendWithConversion("</"); - anOutputString+=mTextValue; + if(mTextValue.Length()>0) + anOutputString.Append(mTextValue); + else + anOutputString.AppendWithConversion(GetTagName(mTypeID)); anOutputString.AppendWithConversion(">"); } @@ -479,7 +460,10 @@ void CEndToken::GetSource(nsString& anOutputString){ */ void CEndToken::AppendSource(nsString& anOutputString){ anOutputString.AppendWithConversion("</"); - anOutputString+=mTextValue; + if(mTextValue.Length()>0) + anOutputString.Append(mTextValue); + else + anOutputString.AppendWithConversion(GetTagName(mTypeID)); anOutputString.AppendWithConversion(">"); } @@ -501,8 +485,8 @@ CTextToken::CTextToken() : CHTMLToken(eHTMLTag_text) { * @param aName -- string to init token name with * @return */ -CTextToken::CTextToken(const nsString& aName) : CHTMLToken(aName) { - mTypeID=eHTMLTag_text; +CTextToken::CTextToken(const nsAReadableString& aName) : CHTMLToken(eHTMLTag_text) { + mTextValue.Rebind(aName); } /* @@ -527,6 +511,10 @@ PRInt32 CTextToken::GetTokenType(void) { return eToken_text; } +PRInt32 CTextToken::GetTextLength(void) { + return mTextValue.Length(); +} + /* * Consume as much clear text from scanner as possible. * @@ -539,9 +527,17 @@ nsresult CTextToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) static nsString theTerminals = NS_ConvertToString("\n\r&<",4); nsresult result=NS_OK; PRBool done=PR_FALSE; + nsReadingIterator<PRUnichar> origin, start, end; + + // Start scanning after the first character, because we know it to + // be part of this text token (we wouldn't have come here if it weren't) + aScanner.CurrentPosition(origin); + start = origin; + start++; + aScanner.SetPosition(start); while((NS_OK==result) && (!done)) { - result=aScanner.ReadUntil(mTextValue,theTerminals,PR_FALSE); + result=aScanner.ReadUntil(start, end, theTerminals,PR_FALSE); if(NS_OK==result) { result=aScanner.Peek(aChar); @@ -553,31 +549,21 @@ nsresult CTextToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) case kCR: // result=aScanner.GetChar(aChar); if(kLF==theNextChar) { + // If the "\r" is followed by a "\n", don't replace it and + // let it be ignored by the layout system + end += 2; result=aScanner.GetChar(theNextChar); } - else if(kCR==theNextChar) { - result=aScanner.GetChar(theNextChar); - result=aScanner.Peek(theNextChar); //then see what's next. - if(kLF==theNextChar) { - result=aScanner.GetChar(theNextChar); - } - mTextValue.AppendWithConversion("\n"); - mNewlineCount++; + else { + // If it standalone, replace the "\r" with a "\n" so that + // it will be considered by the layout system + aScanner.ReplaceCharacter(end, kLF); + end++; } - mTextValue.AppendWithConversion("\n"); mNewlineCount++; break; case kLF: - if((kLF==theNextChar) || (kCR==theNextChar)) { - result=aScanner.GetChar(theNextChar); - mTextValue.AppendWithConversion("\n"); - mNewlineCount++; - } - mTextValue.AppendWithConversion("\n"); - mNewlineCount++; - break; - default: - mTextValue.AppendWithConversion("\n"); + end++; mNewlineCount++; break; } //switch @@ -585,6 +571,9 @@ nsresult CTextToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) else done=PR_TRUE; } } + + aScanner.BindSubstring(mTextValue, origin, end); + return result; } @@ -599,16 +588,16 @@ nsresult CTextToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScanner& aScanner, nsString& aTerminalString,PRInt32 aMode,PRBool& aFlushTokens){ nsresult result=NS_OK; - PRInt32 theTermStrPos=0;; - nsString& theBuffer=aScanner.GetBuffer(); - PRInt32 theStartOffset=aScanner.GetOffset(); - PRInt32 theCurrOffset=theStartOffset; - PRInt32 theStartCommentPos=kNotFound; - PRInt32 theAltTermStrPos=kNotFound; + nsReadingIterator<PRUnichar> theStartOffset, theCurrOffset, theTermStrPos, theStartCommentPos, theAltTermStrPos, endPos; PRBool done=PR_FALSE; PRBool theLastIteration=PR_FALSE; PRInt32 termStrLen=aTerminalString.Length(); + aScanner.CurrentPosition(theStartOffset); + theCurrOffset = theStartOffset; + aScanner.EndReading(endPos); + theTermStrPos = theStartCommentPos = theAltTermStrPos = endPos; + // ALGORITHM: *** The performance is based on correctness of the document *** // 1. Look for a '<' character. This could be // a) Start of a comment (<!--), b) Start of the terminal string, or c) a start of a tag. @@ -630,74 +619,96 @@ nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScann // When is the disaster enabled? // a) when the buffer runs out ot data. // b) when the terminal string is not found. - PRBool disaster=PR_FALSE; - while(result==NS_OK && !done) { - theCurrOffset=theBuffer.FindChar(kLessThan,PR_TRUE,theCurrOffset); - if(-1<theCurrOffset) { - PRInt32 tempOffset=theCurrOffset; + PRBool disaster = PR_FALSE; + while((result == NS_OK) && !done) { + if (FindCharInReadable(PRUnichar(kLessThan), theCurrOffset, endPos)) { + nsReadingIterator<PRUnichar> tempOffset = theCurrOffset; while(1) { - theTermStrPos=kNotFound; - tempOffset=theBuffer.FindChar(kGreaterThan,PR_TRUE,tempOffset); - if(tempOffset>-1) { - //theTermStrPos=theBuffer.RFind(aTerminalString,PR_TRUE,tempOffset,termStrLen+2); - theTermStrPos=theBuffer.RFind(aTerminalString,PR_TRUE,tempOffset,tempOffset-(theCurrOffset-2)); //bug43513... - if(theTermStrPos>-1) break; - tempOffset++; + if (FindCharInReadable(PRUnichar(kGreaterThan), tempOffset, endPos)) { + + // Make a copy of the (presumed) end tag and + // do a case-insensitive comparision + nsAutoString str; + + nsReadingIterator<PRUnichar> start(tempOffset), end(tempOffset); + start.advance(-termStrLen); + + CopyUnicodeTo(start, end, str); + + if (str.EqualsIgnoreCase(aTerminalString)) { + theTermStrPos = tempOffset; + theTermStrPos.advance(-termStrLen); + break; + } + tempOffset.advance(1); + } + else { + break; } - else break; } - //theTermStrPos=theBuffer.Find(aTerminalString,PR_TRUE,theCurrOffset); - if(theTermStrPos>kNotFound) { - if((aMode!=eDTDMode_strict) && (aMode!=eDTDMode_transitional) && !theLastIteration) { - if(!aIgnoreComments) { - theCurrOffset=theBuffer.Find("<!--",PR_TRUE,theCurrOffset,5); - if(theStartCommentPos==kNotFound && theCurrOffset>kNotFound) { - theStartCommentPos=theCurrOffset; - } - if(theStartCommentPos>kNotFound) { - // Search for --> between <!-- and </TERMINALSTRING>. - theCurrOffset=theBuffer.RFind("-->",PR_TRUE,theTermStrPos,theTermStrPos-theStartCommentPos); - if(theCurrOffset==kNotFound) { - // If you're here it means that we have a bogus terminal string. - theAltTermStrPos=(theAltTermStrPos>-1)? theAltTermStrPos:theTermStrPos; // This could be helpful in case we hit the rock bottom. - theCurrOffset=theTermStrPos+termStrLen; // We did not find '-->' so keep searching for terminal string. - continue; - } - } + + if (theTermStrPos != endPos) { + if((aMode != eDTDMode_strict) && (aMode != eDTDMode_transitional) && + !theLastIteration && !aIgnoreComments) { + nsReadingIterator<PRUnichar> endComment(theCurrOffset); + endComment += 5; + if ((theStartCommentPos == endPos) && + FindInReadable(NS_LITERAL_STRING("<!--"), theCurrOffset, endComment)) { + theStartCommentPos = theCurrOffset; } - PRInt32 thePos=theBuffer.FindChar(kGreaterThan,PR_TRUE,theTermStrPos,20); - if(thePos>kNotFound && thePos>theTermStrPos+termStrLen) { - termStrLen +=(thePos-(theTermStrPos+termStrLen)); + if (theStartCommentPos != endPos) { + // Search for --> between <!-- and </TERMINALSTRING>. + theCurrOffset = theStartCommentPos; + nsReadingIterator<PRUnichar> terminal(theTermStrPos); + if (!RFindInReadable(NS_LITERAL_STRING("-->"), + theCurrOffset, terminal)) { + // If you're here it means that we have a bogus terminal string. + + // Even though it is bogus, the position of the terminal string + // could be helpful in case we hit the rock bottom. + if (theAltTermStrPos != endPos) { + theAltTermStrPos = theTermStrPos; + } + + // We did not find '-->' so keep searching for terminal string. + theCurrOffset = theTermStrPos; + theCurrOffset.advance(termStrLen); + continue; + } } } - + disaster=PR_FALSE; - theCurrOffset=theTermStrPos; - theBuffer.Mid(aTerminalString,theTermStrPos+2,termStrLen-2); - PRUnichar ch=theBuffer.CharAt(theTermStrPos+termStrLen); - theTermStrPos=(ch==kGreaterThan)? theTermStrPos+termStrLen:kNotFound; - if(theTermStrPos>kNotFound) { - theBuffer.Mid(mTextValue,theStartOffset,theCurrOffset-theStartOffset); - aScanner.Mark(theTermStrPos+1); - aFlushTokens=PR_TRUE; // We found </SCRIPT>...permit flushing -> Ref: Bug 22485 - } - done=PR_TRUE; + + aScanner.BindSubstring(mTextValue, theStartOffset, theTermStrPos); + + theTermStrPos.advance(termStrLen+1); + aScanner.SetPosition(theTermStrPos); + + // We found </SCRIPT>...permit flushing -> Ref: Bug 22485 + aFlushTokens=PR_TRUE; + done = PR_TRUE; + } + else { + disaster = PR_TRUE; } - else disaster=PR_TRUE; } - else disaster=PR_TRUE; + else { + disaster = PR_TRUE; + } + if(disaster) { if(!aScanner.IsIncremental()) { - if(theAltTermStrPos>kNotFound) { + if(theAltTermStrPos != endPos) { // If you're here it means..we hit the rock bottom and therefore switch to plan B. - theCurrOffset=theAltTermStrPos; - theLastIteration=PR_TRUE; + theCurrOffset = theAltTermStrPos; + theLastIteration = PR_TRUE; } else { - aTerminalString.Cut(0,2); // Do this to fix Bug. 35456 - done=PR_TRUE; + aTerminalString.Cut(0,2); + done = PR_TRUE; // Do this to fix Bug. 35456 } } else @@ -707,6 +718,26 @@ nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScann return result; } +void CTextToken::CopyTo(nsAWritableString& aStr) +{ + aStr.Assign(mTextValue); +} + +const nsAReadableString& CTextToken::GetStringValue(void) +{ + return mTextValue; +} + +void CTextToken::Bind(nsScanner* aScanner, nsReadingIterator<PRUnichar>& aStart, nsReadingIterator<PRUnichar>& aEnd) +{ + aScanner->BindSubstring(mTextValue, aStart, aEnd); +} + +void CTextToken::Bind(const nsAReadableString& aStr) +{ + mTextValue.Rebind(aStr); +} + /* * default constructor * @@ -725,8 +756,8 @@ CCDATASectionToken::CCDATASectionToken() : CHTMLToken(eHTMLTag_unknown) { * @param aName -- string to init token name with * @return */ -CCDATASectionToken::CCDATASectionToken(const nsString& aName) : CHTMLToken(aName) { - mTypeID=eHTMLTag_unknown; +CCDATASectionToken::CCDATASectionToken(const nsAReadableString& aName) : CHTMLToken(eHTMLTag_unknown) { + mTextValue.Assign(aName); } /* @@ -806,6 +837,11 @@ nsresult CCDATASectionToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt3 return result; } +const nsAReadableString& CCDATASectionToken::GetStringValue(void) +{ + return mTextValue; +} + /* * Default constructor @@ -825,8 +861,8 @@ CCommentToken::CCommentToken() : CHTMLToken(eHTMLTag_comment) { * @param * @return */ -CCommentToken::CCommentToken(const nsString& aName) : CHTMLToken(aName) { - mTypeID=eHTMLTag_comment; +CCommentToken::CCommentToken(const nsAReadableString& aName) : CHTMLToken(eHTMLTag_comment) { + mTextValue.Assign(aName); } /* @@ -918,11 +954,11 @@ nsresult ConsumeComment(PRUnichar aChar, nsScanner& aScanner,nsString& aString) per spec (But then, neither does IE or Nav). *********************************************************/ - PRInt32 theBestAltPos=kNotFound; - nsString& theBuffer=aScanner.GetBuffer(); - PRInt32 theStartOffset=aScanner.GetOffset(); - PRInt32 theCurrOffset=theStartOffset; + nsReadingIterator<PRUnichar> theStartOffset, theCurrOffset, theBestAltPos, endPos; + aScanner.EndReading(endPos); + theBestAltPos = endPos; + aScanner.CurrentPosition(theStartOffset); result=aScanner.GetChar(aChar); if(NS_OK==result) { if(kMinus==aChar) { @@ -930,22 +966,26 @@ nsresult ConsumeComment(PRUnichar aChar, nsScanner& aScanner,nsString& aString) if(NS_OK==result) { if(kMinus==aChar) { //in this case, we're reading a long-form comment <-- xxx --> - + + theCurrOffset = theStartOffset; + while((NS_OK==result)) { - theCurrOffset=theBuffer.FindChar(kGreaterThan,PR_TRUE,theCurrOffset); - if(kNotFound!=theCurrOffset) { + if (FindCharInReadable(PRUnichar(kGreaterThan), theCurrOffset, endPos)) { theCurrOffset++; - aChar=theBuffer[theCurrOffset-3]; + nsReadingIterator<PRUnichar> temp = theCurrOffset; + temp.advance(-3); + aChar=*temp; if(kMinus==aChar) { - aChar=theBuffer[theCurrOffset-2]; + temp++; + aChar=*temp; if(kMinus==aChar) { - theStartOffset=theStartOffset-2; // Include "<!" also.. - theBuffer.Mid(aString,theStartOffset,theCurrOffset-theStartOffset); - aScanner.Mark(theCurrOffset); + theStartOffset -= 2; // Include "<!" also.. + CopyUnicodeTo(theStartOffset, theCurrOffset, aString); + aScanner.SetPosition(theCurrOffset); return result; // We have found the dflt end comment delimiter ("-->") } } - if(kNotFound==theBestAltPos) { + if(theBestAltPos == endPos) { // If we did not find the dflt then assume that '>' is the end comment // until we find '-->'. Nav. Compatibility -- Ref: Bug# 24006 theBestAltPos=theCurrOffset; @@ -955,16 +995,16 @@ nsresult ConsumeComment(PRUnichar aChar, nsScanner& aScanner,nsString& aString) result=kEOF; } } //while - if((kNotFound==theCurrOffset) && (!aScanner.IsIncremental())) { + if((endPos==theCurrOffset) && (!aScanner.IsIncremental())) { //if you're here, then we're in a special state. //The problem at hand is that we've hit the end of the document without finding the normal endcomment delimiter "-->". //In this case, the first thing we try is to see if we found one of the alternate endcomment delimiter ">". //If so, rewind just pass than, and use everything up to that point as your comment. //If not, the document has no end comment and should be treated as one big comment. - if(kNotFound<theBestAltPos) { - theStartOffset=theStartOffset-2;// Include "<!" also.. - theBuffer.Mid(aString,theStartOffset,theBestAltPos-theStartOffset); - aScanner.Mark(theBestAltPos); + if(endPos != theBestAltPos) { + theStartOffset -= 2;// Include "<!" also.. + CopyUnicodeTo(theStartOffset, theBestAltPos, aString); + aScanner.SetPosition(theBestAltPos); result=NS_OK; } } @@ -1013,6 +1053,10 @@ nsresult CCommentToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMo return result; } +const nsAReadableString& CCommentToken::GetStringValue(void) +{ + return mTextValue; +} /* * @@ -1047,17 +1091,6 @@ CNewlineToken::CNewlineToken() : CHTMLToken(eHTMLTag_newline) { } -/* - * default constructor - * - * @update gess 3/25/98 - * @param aName -- string value to init token name with - * @return - */ -CNewlineToken::CNewlineToken(const nsString& aName) : CHTMLToken(aName) { - mTypeID=eHTMLTag_newline; -} - /* * * @@ -1080,19 +1113,29 @@ PRInt32 CNewlineToken::GetTokenType(void) { return eToken_newline; } + +static nsSlidingSubstring* gNewlineStr; +void CNewlineToken::AllocNewline() +{ + gNewlineStr = new nsSlidingSubstring(NS_LITERAL_STRING("\n")); +} + +void CNewlineToken::FreeNewline() +{ + if (gNewlineStr) { + delete gNewlineStr; + gNewlineStr = nsnull; + } +} + /** * This method retrieves the value of this internal string. * * @update gess 3/25/98 * @return nsString reference to internal string value */ -nsString& CNewlineToken::GetStringValueXXX(void) { - static nsString* theStr=0; - if(!theStr) { - theStr=new nsString; - theStr->AssignWithConversion("\n"); - } - return *theStr; +const nsAReadableString& CNewlineToken::GetStringValue(void) { + return *gNewlineStr; } /* @@ -1105,12 +1148,6 @@ nsString& CNewlineToken::GetStringValueXXX(void) { */ nsresult CNewlineToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) { -#if 1 - mTextValue.Assign(kNewLine); //This is what I THINK we should be doing. -#else - mTextValue=aChar; -#endif - /******************************************************************* Here's what the HTML spec says about newlines: @@ -1129,7 +1166,6 @@ nsresult CNewlineToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMo case kNewLine: if(kCR==theChar) { result=aScanner.GetChar(theChar); - mTextValue+=theChar; } break; case kCR: @@ -1164,8 +1200,8 @@ CAttributeToken::CAttributeToken() : CHTMLToken(eHTMLTag_unknown) { * @param aName -- string value to init token name with * @return */ -CAttributeToken::CAttributeToken(const nsString& aName) : CHTMLToken(aName), - mTextKey() { +CAttributeToken::CAttributeToken(const nsAReadableString& aName) : CHTMLToken(eHTMLTag_unknown) { + mTextValue.Assign(aName); mLastAttribute=PR_FALSE; mHasEqualWithoutValue=PR_FALSE; } @@ -1178,21 +1214,9 @@ CAttributeToken::CAttributeToken(const nsString& aName) : CHTMLToken(aName), * @param aName -- string value to init token name with * @return */ -CAttributeToken::CAttributeToken(const nsString& aKey, const nsString& aName) : CHTMLToken(aName) { - mTextKey = aKey; - mLastAttribute=PR_FALSE; - mHasEqualWithoutValue=PR_FALSE; -} - -/** - * - * @update gess8/4/98 - * @param - * @return - */ -void CAttributeToken::Reinitialize(PRInt32 aTag, const nsString& aString){ - CHTMLToken::Reinitialize(aTag,aString); - mTextKey.Truncate(); +CAttributeToken::CAttributeToken(const nsAReadableString& aKey, const nsAReadableString& aName) : CHTMLToken(eHTMLTag_unknown) { + mTextValue.Assign(aName); + mTextKey.Rebind(aKey); mLastAttribute=PR_FALSE; mHasEqualWithoutValue=PR_FALSE; } @@ -1229,14 +1253,28 @@ PRInt32 CAttributeToken::GetTokenType(void) { void CAttributeToken::SanitizeKey() { PRInt32 length=mTextKey.Length(); if(length > 0) { - PRUnichar theChar=mTextKey.Last(); - while(!nsCRT::IsAsciiAlpha(theChar) && !nsCRT::IsAsciiDigit(theChar)) { - mTextKey.Truncate(length-1); - length = mTextKey.Length(); - if(length <= 0) break; - theChar = mTextKey.Last(); + nsReadingIterator<PRUnichar> iter, begin, end; + mTextKey.BeginReading(begin); + mTextKey.EndReading(end); + iter = end; + + // Look for the first legal character starting from + // the end of the string + do { + --iter; + } while (!nsCRT::IsAsciiAlpha(*iter) && + !nsCRT::IsAsciiDigit(*iter) && + (iter != begin)); + + // If there were any illegal characters, just copy out the + // legal part + if (iter != --end) { + nsAutoString str; + CopyUnicodeTo(begin, iter, str); + mTextKey.Rebind(str); } } + return; } @@ -1249,11 +1287,17 @@ void CAttributeToken::SanitizeKey() { */ void CAttributeToken::DebugDumpToken(nsOutputStream& out) { char buffer[200]; - mTextKey.ToCString(buffer,sizeof(buffer)); - out << "[" << GetClassName() << "] " << buffer << "="; + nsCAutoString str; + CopyUCS2toASCII(mTextKey, str); + out << "[" << GetClassName() << "] " << str.GetBuffer() << "="; mTextValue.ToCString(buffer,sizeof(buffer)); out << buffer << ": " << mTypeID << nsEndl; } + +const nsAReadableString& CAttributeToken::GetStringValue(void) +{ + return mTextValue; +} /* * @@ -1275,10 +1319,10 @@ void CAttributeToken::GetSource(nsString& anOutputString){ * @return nada */ void CAttributeToken::AppendSource(nsString& anOutputString){ - anOutputString+=mTextKey; + anOutputString.Append(mTextKey); if(mTextValue.Length() || mHasEqualWithoutValue) anOutputString.AppendWithConversion("="); - anOutputString+=mTextValue; + anOutputString.Append(mTextValue); // anOutputString.AppendWithConversion(";"); } @@ -1293,7 +1337,8 @@ void CAttributeToken::AppendSource(nsString& anOutputString){ */ nsresult ConsumeQuotedString(PRUnichar aChar,nsString& aString,nsScanner& aScanner){ nsresult result=NS_OK; - PRInt32 theOffset=aScanner.GetOffset(); + nsReadingIterator<PRUnichar> theOffset; + aScanner.CurrentPosition(theOffset); switch(aChar) { case kQuote: @@ -1316,7 +1361,7 @@ nsresult ConsumeQuotedString(PRUnichar aChar,nsString& aString,nsScanner& aScann PRUnichar ch=aString.Last(); if(ch!=aChar) { if(!aScanner.IsIncremental() && result==kEOF) { - aScanner.Mark(theOffset); + aScanner.SetPosition(theOffset, PR_FALSE, PR_TRUE); aString.Assign(aChar); result=kBadStringLiteral; } @@ -1374,41 +1419,36 @@ nsresult CAttributeToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 a //I changed a bit of this method to use aRetainWhitespace so that we do the right //thing in viewsource. The ws/cr/lf sequences are now maintained, and viewsource looks good. - result=(aRetainWhitespace) ? aScanner.ReadWhitespace(mTextKey) : aScanner.SkipWhitespace(); + nsReadingIterator<PRUnichar> wsstart, wsend; + result=(aRetainWhitespace) ? aScanner.ReadWhitespace(wsstart, wsend) : aScanner.SkipWhitespace(); if(NS_OK==result) { result=aScanner.Peek(aChar); if(NS_OK==result) { - if(kQuote==aChar) { //if you're here, handle quoted key... - result=aScanner.GetChar(aChar); //skip the quote character... - if(NS_OK==result) { - mTextKey.Append(aChar); - result=ConsumeQuotedString(aChar,mTextKey,aScanner); - if(result==kBadStringLiteral) { - // Ref. Bug: 58455 - // If you're here it means that we have searched all the way thro' - // the document for a matching quote and haven't found it. Tell the - // caller that we are done searching and proceed with whatever we have. - result=NS_OK; - } - if(!aRetainWhitespace) - mTextKey.StripChars("\r\n"); //per the HTML spec, ignore linefeeds... - }//if - } - else if((kHashsign==aChar) || (nsCRT::IsAsciiDigit(aChar))){ - result=aScanner.ReadNumber(mTextKey); + nsReadingIterator<PRUnichar> start, end; + if((kHashsign==aChar) || (nsCRT::IsAsciiDigit(aChar))){ + result=aScanner.ReadNumber(start, end); } else { //If you're here, handle an unquoted key. - static nsString theTerminals = NS_ConvertToString("\b\t\n\r \"=>",8); - result=aScanner.ReadUntil(mTextKey,theTerminals,PR_FALSE); + static nsAutoString theTerminals = NS_ConvertToString("\b\t\n\r \"=>",8); + result=aScanner.ReadUntil(start,end,theTerminals,PR_FALSE); + } + if (!aRetainWhitespace) { + aScanner.BindSubstring(mTextKey, start, end); } //now it's time to Consume the (optional) value... if(NS_OK==result) { - result=(aRetainWhitespace) ? aScanner.ReadWhitespace(mTextKey) : aScanner.SkipWhitespace(); + if (aRetainWhitespace) { + aScanner.ReadWhitespace(start, wsend); + aScanner.BindSubstring(mTextKey, wsstart, wsend); + } + else { + aScanner.SkipWhitespace(); + } if(NS_OK==result) { result=aScanner.Peek(aChar); //Skip ahead until you find an equal sign or a '>'... @@ -1420,9 +1460,10 @@ nsresult CAttributeToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 a result=(aRetainWhitespace) ? aScanner.ReadWhitespace(mTextValue) : aScanner.SkipWhitespace(); if(NS_OK==result) { - result=aScanner.GetChar(aChar); //and grab the next char. + result=aScanner.Peek(aChar); //and grab the next char. if(NS_OK==result) { if((kQuote==aChar) || (kApostrophe==aChar)) { + aScanner.GetChar(aChar); mTextValue.Append(aChar); result=ConsumeQuotedString(aChar,mTextValue,aScanner); if(result==kBadStringLiteral) { @@ -1439,11 +1480,11 @@ nsresult CAttributeToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 a } else if(kGreaterThan==aChar){ mHasEqualWithoutValue=PR_TRUE; - result=aScanner.PutBack(aChar); } else if(kAmpersand==aChar) { // XXX - Discard script entity for now....except in // view-source + aScanner.GetChar(aChar); PRBool discard=!aRetainWhitespace; mTextValue.Append(aChar); result=aScanner.GetChar(aChar); @@ -1454,6 +1495,7 @@ nsresult CAttributeToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 a if(discard) mTextValue.Truncate(); } else { + aScanner.GetChar(aChar); mTextValue.Append(aChar); //it's an alphanum attribute... result=ConsumeAttributeValueText(aChar,mTextValue,aScanner); } @@ -1500,8 +1542,9 @@ nsresult CAttributeToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 a */ void CAttributeToken::DebugDumpSource(nsOutputStream& out) { static char buffer[1000]; - mTextKey.ToCString(buffer,sizeof(buffer)); - out << " " << buffer; + nsCAutoString str; + CopyUCS2toASCII(mTextKey, str); + out << " " << str.GetBuffer(); if(mTextValue.Length()){ mTextValue.ToCString(buffer,sizeof(buffer)); out << "=" << buffer; @@ -1510,6 +1553,18 @@ void CAttributeToken::DebugDumpSource(nsOutputStream& out) { out<<">"; } +void CAttributeToken::SetKey(const nsAReadableString& aKey) +{ + mTextKey.Rebind(aKey); +} + +void CAttributeToken::BindKey(nsScanner* aScanner, + nsReadingIterator<PRUnichar>& aStart, + nsReadingIterator<PRUnichar>& aEnd) +{ + aScanner->BindSubstring(mTextKey, aStart, aEnd); +} + /* * default constructor * @@ -1528,8 +1583,8 @@ CWhitespaceToken::CWhitespaceToken() : CHTMLToken(eHTMLTag_whitespace) { * @param aName -- string value to init token name with * @return */ -CWhitespaceToken::CWhitespaceToken(const nsString& aName) : CHTMLToken(aName) { - mTypeID=eHTMLTag_whitespace; +CWhitespaceToken::CWhitespaceToken(const nsAReadableString& aName) : CHTMLToken(eHTMLTag_whitespace) { + mTextValue.Assign(aName); } /* @@ -1572,6 +1627,11 @@ nsresult CWhitespaceToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 return result; } +const nsAReadableString& CWhitespaceToken::GetStringValue(void) +{ + return mTextValue; +} + /* * default constructor * @@ -1589,8 +1649,8 @@ CEntityToken::CEntityToken() : CHTMLToken(eHTMLTag_entity) { * @param aName -- string value to init token name with * @return */ -CEntityToken::CEntityToken(const nsString& aName) : CHTMLToken(aName) { - mTypeID=eHTMLTag_entity; +CEntityToken::CEntityToken(const nsAReadableString& aName) : CHTMLToken(eHTMLTag_entity) { + mTextValue.Assign(aName); #ifdef VERBOSE_DEBUG if(!VerifyEntityTable()) { cout<<"Entity table is invalid!" << endl; @@ -1796,6 +1856,11 @@ void CEntityToken::DebugDumpSource(nsOutputStream& out) { delete[] cp; } +const nsAReadableString& CEntityToken::GetStringValue(void) +{ + return mTextValue; +} + /* * * @@ -1839,7 +1904,8 @@ CScriptToken::CScriptToken() : CHTMLToken(eHTMLTag_script) { * @param aName -- string to init token name with * @return */ -CScriptToken::CScriptToken(const nsString& aString) : CHTMLToken(aString,eHTMLTag_script) { +CScriptToken::CScriptToken(const nsAReadableString& aString) : CHTMLToken(eHTMLTag_script) { + mTextValue.Assign(aString); } @@ -1865,6 +1931,11 @@ PRInt32 CScriptToken::GetTokenType(void) { return eToken_script; } +const nsAReadableString& CScriptToken::GetStringValue(void) +{ + return mTextValue; +} + /* * default constructor * @@ -1875,6 +1946,10 @@ PRInt32 CScriptToken::GetTokenType(void) { CStyleToken::CStyleToken() : CHTMLToken(eHTMLTag_style) { } +CStyleToken::CStyleToken(const nsAReadableString& aString) : CHTMLToken(eHTMLTag_style) { + mTextValue.Assign(aString); +} + /* * * @@ -1897,138 +1972,11 @@ PRInt32 CStyleToken::GetTokenType(void) { return eToken_style; } - -/* - * string based constructor - * - * @update gess 3/25/98 - * @param aName -- string value to init token name with - * @return - */ -CSkippedContentToken::CSkippedContentToken(const nsString& aName) : CAttributeToken(aName) { - mTextKey.AssignWithConversion("$skipped-content");/* XXX need a better answer! */ +const nsAReadableString& CStyleToken::GetStringValue(void) +{ + return mTextValue; } -/* - * - * - * @update gess 3/25/98 - * @param - * @return - */ -const char* CSkippedContentToken::GetClassName(void) { - return "skipped"; -} - -/* - * Retrieve the token type as an int. - * @update gess 3/25/98 - * @return - */ -PRInt32 CSkippedContentToken::GetTokenType(void) { - return eToken_skippedcontent; -} - -/* - * Consume content until you find an end sequence that matches - * this objects current mTextValue. Note that this is complicated - * by the fact that you can be parsing content that itself - * contains quoted content of the same type (like <SCRIPT>). - * That means we have to look for quote-pairs, and ignore the - * content inside them. - * - * @update gess 7/25/98 - * @param aScanner -- controller of underlying input source - * @return error result - */ -nsresult CSkippedContentToken::Consume(PRUnichar aChar,nsScanner& aScanner,PRInt32 aMode) { - PRBool done=PR_FALSE; - nsresult result=NS_OK; - nsString temp; - PRUnichar theChar; - - //We're going to try a new algorithm here. Rather than scan for the matching - //end tag like we used to do, we're now going to scan for whitespace and comments. - //If we find either, just eat them. If we find text or a tag, then go to the - //target endtag, or the start of another comment. - - while((!done) && (NS_OK==result)) { - result=aScanner.GetChar(aChar); - if((NS_OK==result) && (kLessThan==aChar)) { - //we're reading a tag or a comment... - result=aScanner.GetChar(theChar); - if((NS_OK==result) && (kExclamation==theChar)) { - //read a comment... - static CCommentToken theComment; - result=theComment.Consume(aChar,aScanner,aMode); - if(NS_OK==result) { - //result=aScanner.SkipWhitespace(); - temp.Append(theComment.GetStringValueXXX()); - } - } else { - //read a tag... - temp+=aChar; - temp+=theChar; - result=aScanner.ReadUntil(temp,kGreaterThan,PR_TRUE); - } - } - else if(('\b'==theChar) || ('\t'==theChar) || (' '==theChar)) { - static CWhitespaceToken theWS; - result=theWS.Consume(aChar,aScanner,aMode); - if(NS_OK==result) { - temp.Append(theWS.GetStringValueXXX()); - } - } - else { - temp+=aChar; - result=aScanner.ReadUntil(temp,kLessThan,PR_FALSE); - } - nsAutoString theRight; - temp.Right(theRight,mTextValue.Length()); - done=PRBool(0==theRight.CompareWithConversion(mTextValue,PR_TRUE)); - } - int len=temp.Length(); - temp.Truncate(len-mTextValue.Length()); - mTextKey=temp; - return result; -} - -/* - * Dump contents of this token to givne output stream - * - * @update gess 3/25/98 - * @param out -- ostream to output content - * @return - */ -void CSkippedContentToken::DebugDumpSource(nsOutputStream& out) { - static char buffer[1000]; - mTextKey.ToCString(buffer,sizeof(buffer)); - out << " " << buffer; - if(mLastAttribute) - out<<">"; -} - -/* - * - * - * @update gess 3/25/98 - * @param anOutputString will recieve the result - * @return nada - */ -void CSkippedContentToken::GetSource(nsString& anOutputString){ - anOutputString.AppendWithConversion("$skipped-content"); -} - -/* - * - * - * @update harishd 03/23/00 - * @param result appended to the output string. - * @return nada - */ -void CSkippedContentToken::AppendSource(nsString& anOutputString){ - anOutputString.AppendWithConversion("$skipped-content"); -} /** * @@ -2064,7 +2012,8 @@ CInstructionToken::CInstructionToken() : CHTMLToken(eHTMLTag_unknown) { * @param * @return */ -CInstructionToken::CInstructionToken(const nsString& aString) : CHTMLToken(aString) { +CInstructionToken::CInstructionToken(const nsAReadableString& aString) : CHTMLToken(eHTMLTag_unknown) { + mTextValue.Assign(aString); } /** @@ -2102,6 +2051,11 @@ PRInt32 CInstructionToken::GetTokenType(void){ return eToken_instruction; } +const nsAReadableString& CInstructionToken::GetStringValue(void) +{ + return mTextValue; +} + CErrorToken::CErrorToken(nsParserError *aError) : CHTMLToken(eHTMLTag_unknown) { @@ -2130,6 +2084,11 @@ const nsParserError * CErrorToken::GetError(void) return mError; } +const nsAReadableString& CErrorToken::GetStringValue(void) +{ + return mTextValue; +} + // Doctype decl token CDoctypeDeclToken::CDoctypeDeclToken(eHTMLTags aTag) : CHTMLToken(aTag) { @@ -2147,13 +2106,14 @@ nsresult CDoctypeDeclToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 nsresult result =NS_OK; - nsString& theBuffer=aScanner.GetBuffer(); - PRInt32 theCurrOffset=aScanner.GetOffset(); - PRInt32 thePos=(aScanner.GetBuffer()).FindChar(kLessThan,PR_TRUE,theCurrOffset); + nsReadingIterator<PRUnichar> theCurrOffset, endPos; + aScanner.CurrentPosition(theCurrOffset); + aScanner.EndReading(endPos); + FindCharInReadable(PRUnichar(kLessThan), theCurrOffset, endPos); mTextValue.AssignWithConversion("<!"); - if(thePos>-1) { + if(theCurrOffset != endPos) { result=aScanner.ReadUntil(mTextValue,'<',PR_FALSE); } else { @@ -2169,3 +2129,13 @@ const char* CDoctypeDeclToken::GetClassName(void) { PRInt32 CDoctypeDeclToken::GetTokenType(void) { return eToken_doctypeDecl; } + +const nsAReadableString& CDoctypeDeclToken::GetStringValue(void) +{ + return mTextValue; +} + +void CDoctypeDeclToken::SetStringValue(const nsAReadableString& aStr) +{ + mTextValue.Assign(aStr); +} diff --git a/mozilla/htmlparser/src/nsHTMLTokens.h b/mozilla/htmlparser/src/nsHTMLTokens.h index 228e0c9dcac..73dd88d9a07 100644 --- a/mozilla/htmlparser/src/nsHTMLTokens.h +++ b/mozilla/htmlparser/src/nsHTMLTokens.h @@ -47,6 +47,7 @@ #include "nsHTMLTags.h" #include "nsParserError.h" #include "nsString.h" +#include "nsSlidingString.h" class nsScanner; @@ -99,9 +100,6 @@ public: virtual ~CHTMLToken(); CHTMLToken(eHTMLTags aTag); - CHTMLToken(const nsString& aString,eHTMLTags aTag=eHTMLTag_unknown); - virtual void SetCStringValue(const char* name); - virtual nsString& GetStringValueXXX(void); virtual eContainerInfo GetContainerInfo(void) const {return eFormUnknown;} virtual void SetContainerInfo(eContainerInfo aInfo) { } @@ -118,8 +116,8 @@ protected: class CStartToken: public CHTMLToken { public: CStartToken(eHTMLTags aTag=eHTMLTag_unknown); - CStartToken(const nsString& aString); - CStartToken(const nsString& aName,eHTMLTags aTag); + CStartToken(const nsAReadableString& aString); + CStartToken(const nsAReadableString& aName,eHTMLTags aTag); virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,PRInt32 aMode); virtual PRInt32 GetTypeID(void); @@ -131,6 +129,7 @@ class CStartToken: public CHTMLToken { PRBool IsEmpty(void); void SetEmpty(PRBool aValue); virtual void DebugDumpSource(nsOutputStream& out); + virtual const nsAReadableString& GetStringValue(); virtual void GetSource(nsString& anOutputString); virtual void AppendSource(nsString& anOutputString); @@ -139,7 +138,6 @@ class CStartToken: public CHTMLToken { virtual void SetContainerInfo(eContainerInfo aContainerInfo) {mContainerInfo=aContainerInfo;} virtual PRBool IsWellFormed(void) const {return PRBool(eWellFormed==mContainerInfo);} - virtual void Reinitialize(PRInt32 aTag, const nsString& aString); /* * Get and set the ID attribute atom for this element. @@ -150,6 +148,7 @@ class CStartToken: public CHTMLToken { virtual nsresult GetIDAttributeAtom(nsIAtom** aResult); virtual nsresult SetIDAttributeAtom(nsIAtom* aID); + nsString mTextValue; nsString mTrailingContent; PRInt32 mOrigin; protected: @@ -171,14 +170,19 @@ class CStartToken: public CHTMLToken { class CEndToken: public CHTMLToken { public: CEndToken(eHTMLTags aTag); - CEndToken(const nsString& aString); + CEndToken(const nsAReadableString& aString); + CEndToken(const nsAReadableString& aName,eHTMLTags aTag); virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,PRInt32 aMode); virtual PRInt32 GetTypeID(void); virtual const char* GetClassName(void); virtual PRInt32 GetTokenType(void); virtual void DebugDumpSource(nsOutputStream& out); + virtual const nsAReadableString& GetStringValue(); virtual void GetSource(nsString& anOutputString); virtual void AppendSource(nsString& anOutputString); + + protected: + nsString mTextValue; }; @@ -193,11 +197,15 @@ class CEndToken: public CHTMLToken { class CCommentToken: public CHTMLToken { public: CCommentToken(); - CCommentToken(const nsString& aString); + CCommentToken(const nsAReadableString& aString); virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,PRInt32 aMode); virtual const char* GetClassName(void); virtual PRInt32 GetTokenType(void); + virtual const nsAReadableString& GetStringValue(void); char mLeadingChar; + + protected: + nsString mTextValue; }; @@ -211,7 +219,7 @@ class CCommentToken: public CHTMLToken { class CEntityToken : public CHTMLToken { public: CEntityToken(); - CEntityToken(const nsString& aString); + CEntityToken(const nsAReadableString& aString); virtual const char* GetClassName(void); virtual PRInt32 GetTokenType(void); PRInt32 TranslateToUnicodeStr(nsString& aString); @@ -219,8 +227,12 @@ class CEntityToken : public CHTMLToken { static PRInt32 ConsumeEntity(PRUnichar aChar,nsString& aString,nsScanner& aScanner); static PRInt32 TranslateToUnicodeStr(PRInt32 aValue,nsString& aString); virtual void DebugDumpSource(nsOutputStream& out); + virtual const nsAReadableString& GetStringValue(void); virtual void GetSource(nsString& anOutputString); virtual void AppendSource(nsString& anOutputString); + + protected: + nsString mTextValue; }; @@ -234,10 +246,14 @@ class CEntityToken : public CHTMLToken { class CWhitespaceToken: public CHTMLToken { public: CWhitespaceToken(); - CWhitespaceToken(const nsString& aString); + CWhitespaceToken(const nsAReadableString& aString); virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,PRInt32 aMode); virtual const char* GetClassName(void); virtual PRInt32 GetTokenType(void); + virtual const nsAReadableString& GetStringValue(void); + + protected: + nsString mTextValue; }; /** @@ -250,12 +266,20 @@ class CWhitespaceToken: public CHTMLToken { class CTextToken: public CHTMLToken { public: CTextToken(); - CTextToken(const nsString& aString); + CTextToken(const nsAReadableString& aString); virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,PRInt32 aMode); nsresult ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScanner& aScanner, nsString& aTerminalString,PRInt32 aMode,PRBool& aFlushTokens); virtual const char* GetClassName(void); virtual PRInt32 GetTokenType(void); + virtual PRInt32 GetTextLength(void); + virtual void CopyTo(nsAWritableString& aStr); + virtual const nsAReadableString& GetStringValue(void); + virtual void Bind(nsScanner* aScanner, nsReadingIterator<PRUnichar>& aStart, nsReadingIterator<PRUnichar>& aEnd); + virtual void Bind(const nsAReadableString& aStr); + + protected: + nsSlidingSubstring mTextValue; }; @@ -269,10 +293,14 @@ class CTextToken: public CHTMLToken { class CCDATASectionToken : public CHTMLToken { public: CCDATASectionToken(); - CCDATASectionToken(const nsString& aString); + CCDATASectionToken(const nsAReadableString& aString); virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,PRInt32 aMode); virtual const char* GetClassName(void); virtual PRInt32 GetTokenType(void); + virtual const nsAReadableString& GetStringValue(void); + + protected: + nsString mTextValue; }; @@ -288,23 +316,28 @@ public: class CAttributeToken: public CHTMLToken { public: CAttributeToken(); - CAttributeToken(const nsString& aString); - CAttributeToken(const nsString& aKey, const nsString& aString); - ~CAttributeToken() { mTextKey.SetCapacity(0);} + CAttributeToken(const nsAReadableString& aString); + CAttributeToken(const nsAReadableString& aKey, const nsAReadableString& aString); + ~CAttributeToken() {} virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,PRInt32 aMode); virtual const char* GetClassName(void); virtual PRInt32 GetTokenType(void); - virtual nsString& GetKey(void) {return mTextKey;} + virtual const nsAReadableString& GetKey(void) {return mTextKey;} + virtual void SetKey(const nsAReadableString& aKey); + virtual void BindKey(nsScanner* aScanner, nsReadingIterator<PRUnichar>& aStart, nsReadingIterator<PRUnichar>& aEnd); + virtual const nsString& GetValue(void) {return mTextValue;} virtual void SanitizeKey(); virtual void DebugDumpToken(nsOutputStream& out); + virtual const nsAReadableString& GetStringValue(void); virtual void GetSource(nsString& anOutputString); virtual void AppendSource(nsString& anOutputString); virtual void DebugDumpSource(nsOutputStream& out); PRBool mLastAttribute; - virtual void Reinitialize(PRInt32 aTag, const nsString& aString); PRBool mHasEqualWithoutValue; - nsString mTextKey; + protected: + nsAutoString mTextValue; + nsSlidingSubstring mTextKey; }; @@ -317,11 +350,13 @@ class CAttributeToken: public CHTMLToken { class CNewlineToken: public CHTMLToken { public: CNewlineToken(); - CNewlineToken(const nsString& aString); virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,PRInt32 aMode); virtual const char* GetClassName(void); virtual PRInt32 GetTokenType(void); - virtual nsString& GetStringValueXXX(void); + virtual const nsAReadableString& GetStringValue(void); + + static void AllocNewline(); + static void FreeNewline(); }; @@ -337,10 +372,13 @@ class CNewlineToken: public CHTMLToken { class CScriptToken: public CHTMLToken { public: CScriptToken(); - CScriptToken(const nsString& aString); + CScriptToken(const nsAReadableString& aString); virtual const char* GetClassName(void); virtual PRInt32 GetTokenType(void); + virtual const nsAReadableString& GetStringValue(void); + protected: + nsString mTextValue; }; @@ -355,29 +393,13 @@ class CScriptToken: public CHTMLToken { class CStyleToken: public CHTMLToken { public: CStyleToken(); - CStyleToken(const nsString& aString); + CStyleToken(const nsAReadableString& aString); virtual const char* GetClassName(void); virtual PRInt32 GetTokenType(void); - protected: -}; + virtual const nsAReadableString& GetStringValue(void); - -/** - * This is a placeholder token, which is being deprecated. - * Don't bother paying attention to this. - * - * @update gess 3/25/98 - */ -class CSkippedContentToken: public CAttributeToken { - public: - CSkippedContentToken(const nsString& aString); - virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,PRInt32 aMode); - virtual const char* GetClassName(void); - virtual PRInt32 GetTokenType(void); - virtual void DebugDumpSource(nsOutputStream& out); - virtual void GetSource(nsString& anOutputString); - virtual void AppendSource(nsString& anOutputString); protected: + nsString mTextValue; }; @@ -391,10 +413,14 @@ class CSkippedContentToken: public CAttributeToken { class CInstructionToken: public CHTMLToken { public: CInstructionToken(); - CInstructionToken(const nsString& aString); + CInstructionToken(const nsAReadableString& aString); virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,PRInt32 aMode); virtual const char* GetClassName(void); virtual PRInt32 GetTokenType(void); + virtual const nsAReadableString& GetStringValue(void); + + protected: + nsString mTextValue; }; class CErrorToken : public CHTMLToken { @@ -411,7 +437,9 @@ public: // of nsParserError is returned which needs to be destroyed by the consumer? const nsParserError* GetError(void); + virtual const nsAReadableString& GetStringValue(void); protected: + nsString mTextValue; nsParserError* mError; }; @@ -427,6 +455,11 @@ public: virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,PRInt32 aMode); virtual const char* GetClassName(void); virtual PRInt32 GetTokenType(void); + virtual const nsAReadableString& GetStringValue(void); + virtual void SetStringValue(const nsAReadableString& aStr); + + protected: + nsString mTextValue; }; #endif diff --git a/mozilla/htmlparser/src/nsIElementObserver.h b/mozilla/htmlparser/src/nsIElementObserver.h index b047970f60c..d308a05e416 100644 --- a/mozilla/htmlparser/src/nsIElementObserver.h +++ b/mozilla/htmlparser/src/nsIElementObserver.h @@ -32,7 +32,7 @@ #include "nsISupports.h" #include "prtypes.h" -#include "nsHTMLTokens.h" +#include "nsHTMLTags.h" #include "nsDeque.h" diff --git a/mozilla/htmlparser/src/nsIParserFilter.h b/mozilla/htmlparser/src/nsIParserFilter.h index 80ee6f82a01..c9704c88197 100644 --- a/mozilla/htmlparser/src/nsIParserFilter.h +++ b/mozilla/htmlparser/src/nsIParserFilter.h @@ -47,7 +47,7 @@ class nsIParserFilter : public nsISupports { NS_DEFINE_STATIC_IID_ACCESSOR(NS_IPARSERFILTER_IID) - NS_IMETHOD RawBuffer(char * buffer, PRUint32 * buffer_length) = 0; + NS_IMETHOD RawBuffer(const char * buffer, PRUint32 * buffer_length) = 0; NS_IMETHOD WillAddToken(CToken & token) = 0; diff --git a/mozilla/htmlparser/src/nsIParserNode.h b/mozilla/htmlparser/src/nsIParserNode.h index d129adb5095..8fe06fe980b 100644 --- a/mozilla/htmlparser/src/nsIParserNode.h +++ b/mozilla/htmlparser/src/nsIParserNode.h @@ -78,7 +78,7 @@ class nsIParserNode : public nsISupports { * @update gess5/11/98 * @return string containing node text */ - virtual const nsString& GetText() const =0; //get plain text if available + virtual const nsAReadableString& GetText() const =0; //get plain text if available /** * Retrieve skipped context from node @@ -114,7 +114,7 @@ class nsIParserNode : public nsISupports { * @param anIndex is the index of the key you want * @return string containing key. */ - virtual const nsString& GetKeyAt(PRUint32 anIndex) const =0; + virtual const nsAReadableString& GetKeyAt(PRUint32 anIndex) const =0; /** * Retrieve the value (of key/value pair) at given index diff --git a/mozilla/htmlparser/src/nsLoggingSink.cpp b/mozilla/htmlparser/src/nsLoggingSink.cpp index 26800df6941..4d2f58f65ab 100644 --- a/mozilla/htmlparser/src/nsLoggingSink.cpp +++ b/mozilla/htmlparser/src/nsLoggingSink.cpp @@ -92,10 +92,10 @@ nsLoggingSink::nsLoggingSink() nsLoggingSink::~nsLoggingSink() { - if (0 != mOutput) { - mOutput->flush(); - mOutput = 0; - } + //if (0 != mOutput) { + //mOutput->flush(); + // mOutput = 0; + //} } NS_IMPL_ADDREF(nsLoggingSink) @@ -269,11 +269,14 @@ nsLoggingSink::AddComment(const nsIParserNode& aNode){ NS_IMETHODIMP nsLoggingSink::SetTitle(const nsString& aValue) { - nsAutoString tmp; - QuoteText(aValue, tmp); + char* tmp; + GetNewCString(aValue, &tmp); WriteTabs(*mOutput,++mLevel); - (*mOutput) << "<title value=\"" << tmp << "\"/>" << endl; - --mLevel; + if(tmp) { + (*mOutput) << "<title value=\"" << tmp << "\"/>" << endl; + nsMemory::Free(tmp); + } + --mLevel; return NS_OK; } @@ -364,8 +367,8 @@ nsLoggingSink::OpenNode(const char* aKind, const nsIParserNode& aNode) (*mOutput) << "\"" << tag << "\""; } else { - const nsString& text = aNode.GetText(); - (*mOutput) << "\"" << text << " \""; + const nsAReadableString& text = aNode.GetText(); + (*mOutput) << "\"" << NS_ConvertUCS2toUTF8(text) << " \""; } if (WillWriteAttributes(aNode)) { @@ -392,31 +395,43 @@ nsLoggingSink::CloseNode(const char* aKind) nsresult nsLoggingSink::WriteAttributes(const nsIParserNode& aNode) { - nsAutoString tmp, tmp2; + WriteTabs(*mOutput,mLevel); + nsAutoString tmp; PRInt32 ac = aNode.GetAttributeCount(); for (PRInt32 i = 0; i < ac; i++) { - const nsString& k = aNode.GetKeyAt(i); + char* key=nsnull; + char* value=nsnull; + const nsAutoString k(aNode.GetKeyAt(i)); const nsString& v = aNode.GetValueAt(i); - (*mOutput) << " <attr key=\"" << k << "\" value=\""; + GetNewCString(k, &key); + if(key) { + (*mOutput) << " <attr key=\"" << key << "\" value=\""; + nsMemory::Free(key); + } tmp.Truncate(); tmp.Append(v); - PRUnichar first = tmp.First(); - if ((first == '"') || (first == '\'')) { - if (tmp.Last() == first) { - tmp.Cut(0, 1); - PRInt32 pos = tmp.Length() - 1; - if (pos >= 0) { - tmp.Cut(pos, 1); + if(tmp.Length() > 0) { + PRUnichar first = tmp.First(); + if ((first == '"') || (first == '\'')) { + if (tmp.Last() == first) { + tmp.Cut(0, 1); + PRInt32 pos = tmp.Length() - 1; + if (pos >= 0) { + tmp.Cut(pos, 1); + } + } else { + // Mismatched quotes - leave them in } - } else { - // Mismatched quotes - leave them in + } + GetNewCString(tmp, &value); + + if(value) { + (*mOutput) << value << "\"/>" << endl; + nsMemory::Free(value); } } - QuoteText(tmp, tmp2); - - (*mOutput) << tmp2 << "\"/>" << endl; } if (0 != strchr(gSkippedContentTags, aNode.GetNodeType())) { @@ -473,11 +488,15 @@ nsLoggingSink::LeafNode(const nsIParserNode& aNode) else { PRInt32 pos; nsAutoString tmp; + char* str; switch (nodeType) { case eHTMLTag_whitespace: case eHTMLTag_text: - QuoteText(aNode.GetText(), tmp); - (*mOutput) << "<text value=\"" << tmp << "\"/>" << endl; + GetNewCString(aNode.GetText(), &str); + if(str) { + (*mOutput) << "<text value=\"" << str << "\"/>" << endl; + nsMemory::Free(str); + } break; case eHTMLTag_newline: @@ -502,10 +521,10 @@ nsLoggingSink::LeafNode(const nsIParserNode& aNode) } nsresult -nsLoggingSink::QuoteText(const nsString& aValue, nsString& aResult) +nsLoggingSink::QuoteText(const nsAReadableString& aValue, nsString& aResult) { aResult.Truncate(); - const PRUnichar* cp = aValue.GetUnicode(); + const PRUnichar* cp = nsPromiseFlatString(aValue); const PRUnichar* end = cp + aValue.Length(); while (cp < end) { PRUnichar ch = *cp++; @@ -527,6 +546,29 @@ nsLoggingSink::QuoteText(const nsString& aValue, nsString& aResult) return NS_OK; } +/** + * Use this method to convert nsString to char*. + * REMEMBER: Match this call with nsMemory::Free(aResult); + * + * @update 04/04/99 harishd + * @param aValue - The string value + * @param aResult - String coverted to char*. + */ +nsresult +nsLoggingSink::GetNewCString(const nsAReadableString& aValue, char** aResult) +{ + nsresult result=NS_OK; + nsAutoString temp; + result=QuoteText(aValue,temp); + if(NS_SUCCEEDED(result)) { + if(temp.Length()>0) { + *aResult=temp.ToNewCString(); + } + } + return result; +} + + NS_IMETHODIMP nsLoggingSink::DoFragment(PRBool aFlag) { diff --git a/mozilla/htmlparser/src/nsLoggingSink.h b/mozilla/htmlparser/src/nsLoggingSink.h index 84bdb74bd56..e4224db3d69 100644 --- a/mozilla/htmlparser/src/nsLoggingSink.h +++ b/mozilla/htmlparser/src/nsLoggingSink.h @@ -75,7 +75,8 @@ public: nsresult CloseNode(const char* aKind); nsresult LeafNode(const nsIParserNode& aNode); nsresult WriteAttributes(const nsIParserNode& aNode); - nsresult QuoteText(const nsString& aValue, nsString& aResult); + nsresult QuoteText(const nsAReadableString& aValue, nsString& aResult); + nsresult GetNewCString(const nsAReadableString& aValue, char** aResult); PRBool WillWriteAttributes(const nsIParserNode& aNode); protected: diff --git a/mozilla/htmlparser/src/nsParser.cpp b/mozilla/htmlparser/src/nsParser.cpp index 7cb349ed20d..b546197e202 100644 --- a/mozilla/htmlparser/src/nsParser.cpp +++ b/mozilla/htmlparser/src/nsParser.cpp @@ -42,7 +42,6 @@ #include "nsIChannel.h" #include "nsIProgressEventSink.h" #include "nsIInputStream.h" -#include "CRtfDTD.h" #include "CNavDTD.h" #include "COtherDTD.h" #include "prenv.h" @@ -59,7 +58,6 @@ static NS_DEFINE_CID(kWellFormedDTDCID, NS_WELLFORMEDDTD_CID); static NS_DEFINE_CID(kNavDTDCID, NS_CNAVDTD_CID); static NS_DEFINE_CID(kCOtherDTDCID, NS_COTHER_DTD_CID); static NS_DEFINE_CID(kViewSourceDTDCID, NS_VIEWSOURCE_DTD_CID); -static NS_DEFINE_CID(kRtfDTDCID, NS_CRTF_DTD_CID); static const char* kNullURL = "Error: Null URL given"; static const char* kOnStartNotCalled = "Error: OnStartRequest() must be called before OnDataAvailable()"; @@ -117,7 +115,7 @@ public: mDTDDeque.Push(theDTD); mHasViewSourceDTD=PR_FALSE; - mHasRTFDTD=mHasXMLDTD=PR_FALSE; + mHasXMLDTD=PR_FALSE; } ~CSharedParserObjects() { @@ -141,7 +139,6 @@ public: nsDeque mDTDDeque; PRBool mHasViewSourceDTD; //this allows us to defer construction of this object. PRBool mHasXMLDTD; //also defer XML dtd construction - PRBool mHasRTFDTD; //also defer RTF dtd construction nsIDTD *mOtherDTD; //it's ok to leak this; the deque contains a copy too. }; @@ -677,11 +674,6 @@ void DetermineParseMode(nsString& aBuffer,nsDTDMode& aParseMode,eParserDocType& aParseMode=eDTDMode_quirks; return; } - else if(aMimeType.EqualsWithConversion(kRTFTextContentType)) { - aDocType=ePlainText; - aParseMode=eDTDMode_quirks; - return; - } else if(aMimeType.EqualsWithConversion(kTextCSSContentType)) { aDocType=ePlainText; aParseMode=eDTDMode_quirks; @@ -1024,10 +1016,6 @@ void DetermineParseMode2(nsString& aBuffer,nsDTDMode& aParseMode,eParserDocType& aDocType=ePlainText; aParseMode=eDTDMode_quirks; } - else if(aMimeType.EqualsWithConversion(kRTFTextContentType)) { - aDocType=ePlainText; - aParseMode=eDTDMode_quirks; - } if(theModeStr) { if(0==nsCRT::strcasecmp(theModeStr,"strict")) @@ -1094,11 +1082,6 @@ PRBool FindSuitableDTD( CParserContext& aParserContext,nsString& aBuffer) { gSharedObjects.mDTDDeque.Push(theDTD); gSharedObjects.mHasViewSourceDTD=PR_TRUE; } - else if(!gSharedObjects.mHasRTFDTD) { - NS_NewRTF_DTD(&theDTD); //do this so all non-html files can be viewed... - gSharedObjects.mDTDDeque.Push(theDTD); - gSharedObjects.mHasRTFDTD=PR_TRUE; - } } } @@ -1220,9 +1203,6 @@ NS_IMETHODIMP nsParser::CreateCompatibleDTD(nsIDTD** aDTD, aMimeType->EqualsWithConversion(kRDFTextContentType)) { theDTDClassID=&kWellFormedDTDCID; } - else if(aMimeType->EqualsWithConversion(kXIFTextContentType)) { - theDTDClassID=&kRtfDTDCID; - } else { theDTDClassID=&kNavDTDCID; } @@ -1406,7 +1386,10 @@ nsresult nsParser::WillBuildModel(nsString& aFilename){ mMajorIteration=-1; mMinorIteration=-1; - nsString& theBuffer=mParserContext->mScanner->GetBuffer(); + nsAutoString theBuffer; + // XXXVidur Make a copy and only check in the first 1k + mParserContext->mScanner->Peek(theBuffer, 1024); + DetermineParseMode(theBuffer,mParserContext->mDTDMode,mParserContext->mDocType,mParserContext->mMimeType); if(PR_TRUE==FindSuitableDTD(*mParserContext,theBuffer)) { @@ -2240,6 +2223,61 @@ static PRBool detectByteOrderMark(const unsigned char* aBytes, PRInt32 aLen, nsS return oCharset.Length() > 0; } +typedef struct { + PRBool mNeedCheckFirst4Bytes; + nsParser* mParser; + nsIParserFilter* mParserFilter; + nsScanner* mScanner; +} ParserWriteStruct; + +/* + * This function is invoked as a result of a call to a stream's + * ReadSegments() method. It is called for each contiguous buffer + * of data in the underlying stream or pipe. Using ReadSegments + * allows us to avoid copying data to read out of the stream. + */ +static NS_METHOD +ParserWriteFunc(nsIInputStream* in, + void* closure, + const char* fromRawSegment, + PRUint32 toOffset, + PRUint32 count, + PRUint32 *writeCount) +{ + nsresult result; + ParserWriteStruct* pws = NS_STATIC_CAST(ParserWriteStruct*, closure); + const char* buf = fromRawSegment; + PRUint32 theNumRead = count; + + if (!pws) { + return NS_ERROR_FAILURE; + } + + if(pws->mNeedCheckFirst4Bytes && (count >= 4)) { + nsCharsetSource guessSource; + nsAutoString guess; + + pws->mNeedCheckFirst4Bytes = PR_FALSE; + if(detectByteOrderMark((const unsigned char*)buf, + theNumRead, guess, guessSource)) + { +#ifdef DEBUG_XMLENCODING + printf("xmlencoding detect- %s\n", guess.ToNewCString()); +#endif + pws->mParser->SetDocumentCharset(guess, guessSource); + } + } + + if(pws->mParserFilter) + pws->mParserFilter->RawBuffer(buf, &theNumRead); + + result = pws->mScanner->Append(buf, theNumRead); + if (NS_SUCCEEDED(result)) { + *writeCount = count; + } + + return result; +} /** * @@ -2273,90 +2311,27 @@ NS_PRECONDITION(((eOnStart==mParserContext->mStreamListenerState)||(eOnDataAvail if(eInvalidDetect==theContext->mAutoDetectStatus) { if(theContext->mScanner) { - theContext->mScanner->GetBuffer().Truncate(); + nsReadingIterator<PRUnichar> iter; + theContext->mScanner->EndReading(iter); + theContext->mScanner->SetPosition(iter, PR_TRUE); } } - PRInt32 newLength=(aLength>theContext->mTransferBufferSize) ? aLength : -theContext->mTransferBufferSize; - if(!theContext->mTransferBuffer) { - theContext->mTransferBufferSize=newLength; - theContext->mTransferBuffer=new char[newLength+20]; - } - else if(aLength>theContext->mTransferBufferSize){ - delete [] theContext->mTransferBuffer; - theContext->mTransferBufferSize=newLength; - theContext->mTransferBuffer=new char[newLength+20]; - } - - if(theContext->mTransferBuffer) { - - //We need to add code to defensively deal with the case where the transfer buffer is null. - - PRUint32 theTotalRead=0; - PRUint32 theNumRead=1; //init to a non-zero value - int theStartPos=0; - - PRBool needCheckFirst4Bytes = + PRUint32 totalRead; + ParserWriteStruct pws; + pws.mNeedCheckFirst4Bytes = ((0 == sourceOffset) && (mCharsetSource<kCharsetFromAutoDetection)); - while ((theNumRead>0) && (aLength>theTotalRead) && (NS_OK==result)) { - result = pIStream->Read(theContext->mTransferBuffer, aLength, &theNumRead); - if(NS_SUCCEEDED(result) && (theNumRead>0)) { - if(needCheckFirst4Bytes && (theNumRead >= 4)) { - nsCharsetSource guessSource; - nsAutoString guess; - - needCheckFirst4Bytes = PR_FALSE; - if(detectByteOrderMark((const unsigned char*)theContext->mTransferBuffer, - theNumRead, guess, guessSource)) - { - #ifdef DEBUG_XMLENCODING - printf("xmlencoding detect- %s\n", guess.ToNewCString()); - #endif - this->SetDocumentCharset(guess, guessSource); - } - } - theTotalRead+=theNumRead; - if(mParserFilter) - mParserFilter->RawBuffer(theContext->mTransferBuffer, &theNumRead); + pws.mParser = this; + pws.mParserFilter = mParserFilter; + pws.mScanner = theContext->mScanner; - #ifdef rickgdebug - unsigned int index=0; - for(index=0;index<theNumRead;index++) { - if(0==theContext->mTransferBuffer[index]){ - printf("\nNull found at buffer[%i] provided by netlib...\n",index); - break; - } - } - #endif + result = pIStream->ReadSegments(ParserWriteFunc, (void*)&pws, aLength, &totalRead); + if (NS_FAILED(result)) { + return result; + } -#if 1 - static int dump=0; - if(dump) { - theContext->mTransferBuffer[theNumRead]=0; - printf("\n\n-----------------------------------------------------%s\n",theContext->mTransferBuffer); - } -#endif - - - theContext->mScanner->Append(theContext->mTransferBuffer,theNumRead); - - - #ifdef rickgdebug - theContext->mTransferBuffer[theNumRead]=0; - theContext->mTransferBuffer[theNumRead+1]=0; - theContext->mTransferBuffer[theNumRead+2]=0; - cout << theContext->mTransferBuffer; - #endif - - } //if - theStartPos+=theNumRead; - }//while - - result=ResumeParse(); - } //if - - } //if + result=ResumeParse(); + } return result; } diff --git a/mozilla/htmlparser/src/nsParserModule.cpp b/mozilla/htmlparser/src/nsParserModule.cpp index 0437a40572c..9a2939a40f1 100644 --- a/mozilla/htmlparser/src/nsParserModule.cpp +++ b/mozilla/htmlparser/src/nsParserModule.cpp @@ -32,9 +32,7 @@ #include "nsWellFormedDTD.h" #include "CNavDTD.h" #include "COtherDTD.h" -#include "nsXIFDTD.h" #include "COtherDTD.h" -#include "CRtfDTD.h" #include "nsViewSourceHTML.h" #include "nsHTMLContentSinkStream.h" #include "nsHTMLToTXTSinkStream.h" @@ -142,11 +140,9 @@ static NS_DEFINE_CID(kParserNodeCID, NS_PARSER_NODE_IID); static NS_DEFINE_CID(kLoggingSinkCID, NS_LOGGING_SINK_CID); static NS_DEFINE_CID(kWellFormedDTDCID, NS_WELLFORMEDDTD_CID); static NS_DEFINE_CID(kNavDTDCID, NS_CNAVDTD_CID); -static NS_DEFINE_CID(kXIFDTDCID, NS_XIF_DTD_CID); static NS_DEFINE_CID(kCOtherDTDCID, NS_COTHER_DTD_CID); static NS_DEFINE_CID(kCTransitionalDTDCID, NS_CTRANSITIONAL_DTD_CID); static NS_DEFINE_CID(kViewSourceDTDCID, NS_VIEWSOURCE_DTD_CID); -static NS_DEFINE_CID(kRtfDTDCID, NS_CRTF_DTD_CID); static NS_DEFINE_CID(kHTMLContentSinkStreamCID, NS_HTMLCONTENTSINKSTREAM_CID); static NS_DEFINE_CID(kHTMLToTXTSinkStreamCID, NS_HTMLTOTXTSINKSTREAM_CID); static NS_DEFINE_CID(kParserServiceCID, NS_PARSERSERVICE_CID); @@ -162,11 +158,9 @@ static Components gComponents[] = { { "Logging sink", &kLoggingSinkCID }, { "Well formed DTD", &kWellFormedDTDCID }, { "Navigator HTML DTD", &kNavDTDCID }, - { "XIF DTD", &kXIFDTDCID }, { "OTHER DTD", &kCOtherDTDCID }, { "Transitional DTD", &kCTransitionalDTDCID }, { "ViewSource DTD", &kViewSourceDTDCID }, - { "Rtf DTD", &kRtfDTDCID }, { "HTML Content Sink Stream", &kHTMLContentSinkStreamCID }, { "HTML To Text Sink Stream", &kHTMLToTXTSinkStreamCID }, { "ParserService", &kParserServiceCID }, @@ -179,11 +173,9 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsCParserNode) NS_GENERIC_FACTORY_CONSTRUCTOR(nsLoggingSink) NS_GENERIC_FACTORY_CONSTRUCTOR(CWellFormedDTD) NS_GENERIC_FACTORY_CONSTRUCTOR(CNavDTD) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsXIFDTD) NS_GENERIC_FACTORY_CONSTRUCTOR(COtherDTD) NS_GENERIC_FACTORY_CONSTRUCTOR(CTransitionalDTD) NS_GENERIC_FACTORY_CONSTRUCTOR(CViewSourceHTML) -NS_GENERIC_FACTORY_CONSTRUCTOR(CRtfDTD) NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLContentSinkStream) NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLToTXTSinkStream) NS_GENERIC_FACTORY_CONSTRUCTOR(nsParserService) @@ -210,11 +202,9 @@ protected: nsCOMPtr<nsIGenericFactory> mLoggingSinkFactory; nsCOMPtr<nsIGenericFactory> mWellFormedDTDFactory; nsCOMPtr<nsIGenericFactory> mNavHTMLDTDFactory; - nsCOMPtr<nsIGenericFactory> mXIFDTDFactory; nsCOMPtr<nsIGenericFactory> mOtherHTMLDTDFactory; nsCOMPtr<nsIGenericFactory> mTransitionalHTMLDTDFactory; nsCOMPtr<nsIGenericFactory> mViewSourceHTMLDTDFactory; - nsCOMPtr<nsIGenericFactory> mRtfHTMLDTDFactory; nsCOMPtr<nsIGenericFactory> mHTMLContentSinkStreamFactory; nsCOMPtr<nsIGenericFactory> mHTMLToTXTSinkStreamFactory; nsCOMPtr<nsIGenericFactory> mParserServiceFactory; @@ -242,6 +232,8 @@ nsParserModule::Initialize() nsHTMLTags::AddRefTable(); nsHTMLEntities::AddRefTable(); mInitialized = PR_TRUE; + InitializeElementTable(); + CNewlineToken::AllocNewline(); } return NS_OK; } @@ -255,8 +247,8 @@ nsParserModule::Shutdown() nsDTDContext::ReleaseGlobalObjects(); nsParser::FreeSharedObjects(); mInitialized = PR_FALSE; - COtherDTD::ReleaseTable(); - CNavDTD::ReleaseTable(); + DeleteElementTable(); + CNewlineToken::FreeNewline(); } } @@ -313,13 +305,6 @@ nsParserModule::GetClassObject(nsIComponentManager *aCompMgr, } fact = mNavHTMLDTDFactory; } - else if (aClass.Equals(kXIFDTDCID)) { - if (!mXIFDTDFactory) { - rv = NS_NewGenericFactory(getter_AddRefs(mXIFDTDFactory), - &nsXIFDTDConstructor); - } - fact = mXIFDTDFactory; - } else if (aClass.Equals(kCOtherDTDCID)) { if (!mOtherHTMLDTDFactory) { rv = NS_NewGenericFactory(getter_AddRefs(mOtherHTMLDTDFactory), @@ -341,13 +326,6 @@ nsParserModule::GetClassObject(nsIComponentManager *aCompMgr, } fact = mViewSourceHTMLDTDFactory; } - else if (aClass.Equals(kRtfDTDCID)) { - if (!mRtfHTMLDTDFactory) { - rv = NS_NewGenericFactory(getter_AddRefs(mRtfHTMLDTDFactory), - &CRtfDTDConstructor); - } - fact = mRtfHTMLDTDFactory; - } else if (aClass.Equals(kHTMLContentSinkStreamCID)) { if (!mHTMLContentSinkStreamFactory) { rv = NS_NewGenericFactory(getter_AddRefs(mHTMLContentSinkStreamFactory), diff --git a/mozilla/htmlparser/src/nsParserNode.cpp b/mozilla/htmlparser/src/nsParserNode.cpp index 777ba4b42f2..75838d0e3db 100644 --- a/mozilla/htmlparser/src/nsParserNode.cpp +++ b/mozilla/htmlparser/src/nsParserNode.cpp @@ -186,8 +186,8 @@ const nsString& nsCParserNode::GetName() const { * @param * @return string ref of text from internal token */ -const nsString& nsCParserNode::GetText() const { - return (mToken) ? mToken->GetStringValueXXX() : GetEmptyString(); +const nsAReadableString& nsCParserNode::GetText() const { + return (mToken) ? mToken->GetStringValue() : GetEmptyString(); } /** @@ -272,7 +272,7 @@ PRInt32 nsCParserNode::GetAttributeCount(PRBool askToken) const{ * @param anIndex-- offset of attribute to retrieve * @return string rep of given attribute text key */ -const nsString& nsCParserNode::GetKeyAt(PRUint32 anIndex) const { +const nsAReadableString& nsCParserNode::GetKeyAt(PRUint32 anIndex) const { PRInt32 theCount = (mAttributes) ? mAttributes->GetSize() : 0; if((PRInt32)anIndex<theCount) { CAttributeToken* tkn=(CAttributeToken*)mAttributes->ObjectAt(anIndex); @@ -296,7 +296,7 @@ const nsString& nsCParserNode::GetValueAt(PRUint32 anIndex) const { if(PRInt32(anIndex)<theCount) { CAttributeToken* tkn=(CAttributeToken*)mAttributes->ObjectAt(anIndex); - return tkn->GetStringValueXXX(); + return tkn->GetValue(); } return GetEmptyString(); } @@ -373,6 +373,7 @@ nsresult nsCParserNode::ReleaseAll() { //fixed a bug that patrick found, where the attributes deque existed //but was empty. In that case, the attributes deque itself was leaked. //THANKS PATRICK! + // Umm...why is this a useful comment in the source? if(mTokenAllocator) { RecycleTokens(mTokenAllocator,*mAttributes); diff --git a/mozilla/htmlparser/src/nsParserNode.h b/mozilla/htmlparser/src/nsParserNode.h index e9266b9765f..540da833188 100644 --- a/mozilla/htmlparser/src/nsParserNode.h +++ b/mozilla/htmlparser/src/nsParserNode.h @@ -85,7 +85,7 @@ class nsCParserNode : public nsIParserNode { * @update gess5/11/98 * @return string containing node text */ - virtual const nsString& GetText() const; + virtual const nsAReadableString& GetText() const; /** * Retrieve skipped context from node @@ -133,7 +133,7 @@ class nsCParserNode : public nsIParserNode { * @param anIndex is the index of the key you want * @return string containing key. */ - virtual const nsString& GetKeyAt(PRUint32 anIndex) const; + virtual const nsAReadableString& GetKeyAt(PRUint32 anIndex) const; /** * Retrieve the value (of key/value pair) at given index @@ -202,7 +202,7 @@ class nsCParserNode : public nsIParserNode { * @return void */ virtual nsresult ReleaseAll(); - + PRInt32 mLineNumber; CToken* mToken; nsDeque* mAttributes; diff --git a/mozilla/htmlparser/src/nsScanner.cpp b/mozilla/htmlparser/src/nsScanner.cpp index 8ffce4ff81b..0fcd1c29eb6 100644 --- a/mozilla/htmlparser/src/nsScanner.cpp +++ b/mozilla/htmlparser/src/nsScanner.cpp @@ -29,6 +29,34 @@ #include "nsICharsetConverterManager.h" #include "nsICharsetAlias.h" #include "nsFileSpec.h" +#include "nsReadableUtils.h" + +nsScannerString::nsScannerString(PRUnichar* aStorageStart, + PRUnichar* aDataEnd, + PRUnichar* aStorageEnd) : nsSlidingString(aStorageStart, aDataEnd, aStorageEnd) +{ +} + +void +nsScannerString::InsertBuffer(PRUnichar* aStorageStart, + PRUnichar* aDataEnd, + PRUnichar* aStorageEnd) +{ + // XXX This is where insertion of a buffer at the head + // of the buffer list will take place pending checkins + // from scc. +} + +void +nsScannerString::ReplaceCharacter(nsReadingIterator<PRUnichar>& aPosition, + PRUnichar aChar) +{ + // XXX Casting a const to non-const. Unless the base class + // provides support for writing iterators, this is the best + // that can be done. + PRUnichar* pos = (PRUnichar*)aPosition.get(); + *pos = aChar; +} static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID); @@ -52,16 +80,19 @@ MOZ_DECL_CTOR_COUNTER(nsScanner); * @param aMode represents the parser mode (nav, other) * @return */ -nsScanner::nsScanner(nsString& anHTMLString, const nsString& aCharset, nsCharsetSource aSource) : - mBuffer(anHTMLString) +nsScanner::nsScanner(nsString& anHTMLString, const nsString& aCharset, nsCharsetSource aSource) { MOZ_COUNT_CTOR(nsScanner); - mTotalRead=mBuffer.Length(); + PRUnichar* buffer = anHTMLString.ToNewUnicode(); + mTotalRead = anHTMLString.Length(); + mSlidingBuffer = nsnull; + mCountRemaining = 0; + AppendToBuffer(buffer, buffer+mTotalRead, buffer+mTotalRead); + mSlidingBuffer->BeginReading(mCurrentPosition); + mMarkPosition = mCurrentPosition; mIncremental=PR_FALSE; mOwnsStream=PR_FALSE; - mOffset=0; - mMarkPos=0; mInputStream=0; mUnicodeDecoder = 0; mCharsetSource = kCharsetUninitialized; @@ -83,9 +114,9 @@ nsScanner::nsScanner(nsString& aFilename,PRBool aCreateStream, const nsString& a { MOZ_COUNT_CTOR(nsScanner); + mSlidingBuffer = nsnull; mIncremental=PR_TRUE; - mOffset=0; - mMarkPos=0; + mCountRemaining = 0; mTotalRead=0; mOwnsStream=aCreateStream; mInputStream=0; @@ -112,9 +143,9 @@ nsScanner::nsScanner(nsString& aFilename,nsInputStream& aStream,const nsString& { MOZ_COUNT_CTOR(nsScanner); + mSlidingBuffer = nsnull; mIncremental=PR_FALSE; - mOffset=0; - mMarkPos=0; + mCountRemaining = 0; mTotalRead=0; mOwnsStream=PR_FALSE; mInputStream=&aStream; @@ -179,7 +210,11 @@ nsresult nsScanner::SetDocumentCharset(const nsString& aCharset , nsCharsetSourc * @return */ nsScanner::~nsScanner() { - + + if (mSlidingBuffer) { + delete mSlidingBuffer; + } + MOZ_COUNT_DTOR(nsScanner); if(mInputStream) { @@ -201,9 +236,9 @@ nsScanner::~nsScanner() { * @param * @return */ -PRUint32 nsScanner::RewindToMark(void){ - mOffset=mMarkPos; - return mOffset; +void nsScanner::RewindToMark(void){ + mCountRemaining += (Distance(mMarkPosition, mCurrentPosition)); + mCurrentPosition = mMarkPosition; } @@ -216,16 +251,11 @@ PRUint32 nsScanner::RewindToMark(void){ * @param * @return */ -PRUint32 nsScanner::Mark(PRInt32 anIndex){ - if(kNotFound==anIndex) { - if((mOffset>0) && (mOffset>eBufferSizeThreshold)) { - mBuffer.Cut(0,mOffset); //delete chars up to mark position - mOffset=0; - } - mMarkPos=mOffset; +void nsScanner::Mark() { + if (mSlidingBuffer) { + mMarkPosition = mCurrentPosition; + mSlidingBuffer->DiscardPrefix(mMarkPosition); } - else mOffset=(PRUint32)anIndex; - return 0; } @@ -237,9 +267,9 @@ PRUint32 nsScanner::Mark(PRInt32 anIndex){ * @return error code */ PRBool nsScanner::Insert(const nsAReadableString& aBuffer) { - - mBuffer.Insert(aBuffer,mOffset); - mTotalRead+=aBuffer.Length(); + // XXX This is where insertion of a buffer at the head + // of the buffer list will take place pending checkins + // from scc. return PR_TRUE; } @@ -251,16 +281,12 @@ PRBool nsScanner::Insert(const nsAReadableString& aBuffer) { * @return error code */ PRBool nsScanner::Append(const nsAReadableString& aBuffer) { + + PRUnichar* buffer = ToNewUnicode(aBuffer); + PRUint32 bufLen = aBuffer.Length(); + mTotalRead += bufLen; - PRUint32 theLen=mBuffer.Length(); - - mBuffer.Append(aBuffer); - mTotalRead+=aBuffer.Length(); - if(theLen<mBuffer.Length()) { - - //Now yank any nulls that were embedded in this given buffer - mBuffer.StripChar(0,theLen); - } + AppendToBuffer(buffer, buffer+bufLen, buffer+bufLen); return PR_TRUE; } @@ -273,31 +299,35 @@ PRBool nsScanner::Append(const nsAReadableString& aBuffer) { * @return */ PRBool nsScanner::Append(const char* aBuffer, PRUint32 aLen){ - - PRUint32 theLen=mBuffer.Length(); - + PRUnichar* unichars; if(mUnicodeDecoder) { - PRInt32 unicharBufLen = 0; - mUnicodeDecoder->GetMaxLength(aBuffer, aLen, &unicharBufLen); - mUnicodeXferBuf.SetCapacity(unicharBufLen+32); - mUnicodeXferBuf.Truncate(); - PRUnichar *unichars = (PRUnichar*)mUnicodeXferBuf.GetUnicode(); - + nsresult res; do { + PRInt32 unicharBufLen = 0; + mUnicodeDecoder->GetMaxLength(aBuffer, aLen, &unicharBufLen); + unichars = (PRUnichar*)nsMemory::Alloc((unicharBufLen+1) * sizeof(PRUnichar)); + if (!unichars) { + return PR_FALSE; + } + PRInt32 srcLength = aLen; PRInt32 unicharLength = unicharBufLen; res = mUnicodeDecoder->Convert(aBuffer, &srcLength, unichars, &unicharLength); - unichars[unicharLength]=0; //add this since the unicode converters can't be trusted to do so. - mBuffer.Append(unichars, unicharLength); + // if we failed, we consume one byte, replace it with U+FFFD + // and try the conversion again. + if(NS_FAILED(res)) { + unichars[unicharLength++] = (PRUnichar)0xFFFD; + } + + AppendToBuffer(unichars, unichars+unicharLength, + unichars+unicharBufLen); mTotalRead += unicharLength; - // if we failed, we consume one byte by replace it with U+FFFD - // and try conversion again. + + // Continuation of failure case if(NS_FAILED(res)) { mUnicodeDecoder->Reset(); - mBuffer.Append( (PRUnichar)0xFFFD); - mTotalRead++; if(((PRUint32) (srcLength + 1)) > aLen) srcLength = aLen; else @@ -306,52 +336,18 @@ PRBool nsScanner::Append(const char* aBuffer, PRUint32 aLen){ aLen -= srcLength; } } while (NS_FAILED(res) && (aLen > 0)); - // we continue convert the bytes data into Unicode - // if we have conversion error and we have more data. - - // delete[] unichars; } else { - mBuffer.AppendWithConversion(aBuffer,aLen); + nsLiteralCString str(aBuffer, aLen); + unichars = ToNewUnicode(str); + AppendToBuffer(unichars, unichars+aLen, unichars+aLen); mTotalRead+=aLen; - - } - - if(theLen<mBuffer.Length()) { - //Now yank any nulls that were embedded in this given buffer - mBuffer.StripChar(0,theLen); } return PR_TRUE; } -/** - * Append PRUNichar* data to the internal buffer of the scanner - * - * @update gess4/3/98 - * @return error code (it's always true) - */ -PRBool nsScanner::Append(const PRUnichar* aBuffer, PRUint32 aLen){ - - if(-1==(PRInt32)aLen) - aLen=nsCRT::strlen(aBuffer); - - CBufDescriptor theDesc(aBuffer,PR_TRUE, aLen+1,aLen); - nsAutoString theBuffer(theDesc); - - PRUint32 theLen=mBuffer.Length(); - mBuffer.Append(theBuffer); - mTotalRead+=aLen; - - if(theLen<mBuffer.Length()) { - //Now yank any nulls that were embedded in this given buffer - mBuffer.StripChar(0,theLen); - } - - return PR_TRUE; -} - /** * Grab data from underlying stream. * @@ -378,21 +374,24 @@ nsresult nsScanner::FillBuffer(void) { } else { PRInt32 numread=0; - char buf[kBufsize+1]; + char* buf = new char[kBufsize+1]; buf[kBufsize]=0; if(mInputStream) { numread = mInputStream->read(buf, kBufsize); if (0 == numread) { + delete [] buf; return kEOF; } } - mOffset=mBuffer.Length(); + if((0<numread) && (0==result)) { - mBuffer.AppendWithConversion((const char*)buf,numread); - mBuffer.StripChar(0); //yank the nulls that come in from the net. + nsLiteralCString str(buf, numread); + PRUnichar* unichars = ToNewUnicode(str); + AppendToBuffer(unichars, unichars+numread, unichars+kBufsize+1); } - mTotalRead+=mBuffer.Length(); + delete [] buf; + mTotalRead+=numread; } return result; @@ -407,13 +406,17 @@ nsresult nsScanner::FillBuffer(void) { */ nsresult nsScanner::Eof() { nsresult theError=NS_OK; + + if (!mSlidingBuffer) { + return kEOF; + } - if(mOffset>=(PRUint32)mBuffer.Length()) { + if (mCurrentPosition == mEndPosition) { theError=FillBuffer(); } - + if(NS_OK==theError) { - if (0==(PRUint32)mBuffer.Length()) { + if (0==(PRUint32)mSlidingBuffer->Length()) { return kEOF; } } @@ -431,11 +434,18 @@ nsresult nsScanner::Eof() { nsresult nsScanner::GetChar(PRUnichar& aChar) { nsresult result=NS_OK; aChar=0; - if(mOffset>=(PRUint32)mBuffer.Length()) + + if (!mSlidingBuffer) { + return kEOF; + } + + if (mCurrentPosition == mEndPosition) { result=Eof(); + } if(NS_OK == result){ - aChar=GetCharAt(mBuffer,mOffset++); + aChar=*mCurrentPosition++; + mCountRemaining--; } return result; } @@ -449,31 +459,61 @@ nsresult nsScanner::GetChar(PRUnichar& aChar) { * @param * @return */ -nsresult nsScanner::Peek(PRUnichar& aChar) { +nsresult nsScanner::Peek(PRUnichar& aChar, PRUint32 aOffset) { nsresult result=NS_OK; aChar=0; - if(mOffset>=(PRUint32)mBuffer.Length()) + + if (!mSlidingBuffer) { + return kEOF; + } + + if (mCurrentPosition == mEndPosition) { result=Eof(); + } if(NS_OK == result){ - aChar=GetCharAt(mBuffer,mOffset); + if (aOffset) { + if (mCountRemaining < aOffset) { + result = Eof(); + } + else { + nsReadingIterator<PRUnichar> pos = mCurrentPosition; + pos.advance(aOffset); + aChar=*pos; + } + } + else { + aChar=*mCurrentPosition; + } } return result; } +nsresult nsScanner::Peek(nsAWritableString& aStr, PRInt32 aNumChars) +{ + if (!mSlidingBuffer) { + return kEOF; + } + + if (mCurrentPosition == mEndPosition) { + return Eof(); + } + + nsReadingIterator<PRUnichar> start, end; + + start = mCurrentPosition; + + if (mCountRemaining < PRUint32(aNumChars)) { + end = mEndPosition; + } + else { + end = start; + end.advance(aNumChars); + } + + CopyUnicodeTo(start, end, aStr); -/** - * Push the given char back onto the scanner - * - * @update gess 3/25/98 - * @param - * @return error code - */ -nsresult nsScanner::PutBack(PRUnichar aChar) { - if(mOffset>0) - mOffset--; - else mBuffer.Insert(aChar,0); return NS_OK; } @@ -487,41 +527,44 @@ nsresult nsScanner::PutBack(PRUnichar aChar) { */ nsresult nsScanner::SkipWhitespace(void) { + if (!mSlidingBuffer) { + return kEOF; + } + PRUnichar theChar=0; nsresult result=Peek(theChar); - const PRUnichar* theBuf=mBuffer.GetUnicode(); - PRInt32 theOrigin=mOffset; + nsReadingIterator<PRUnichar> current, end; PRBool found=PR_FALSE; mNewlinesSkipped = 0; + current = mCurrentPosition; + end = mEndPosition; - while(NS_OK==result) { - - theChar=theBuf[mOffset++]; - if(theChar) { - switch(theChar) { - case '\n': mNewlinesSkipped++; - case ' ' : - case '\r': - case '\b': - case '\t': - found=PR_TRUE; - break; - default: - found=PR_FALSE; - break; - } - if(!found) { - mOffset-=1; + while(current != end) { + theChar=*current; + switch(theChar) { + case '\n': mNewlinesSkipped++; + case ' ' : + case '\r': + case '\b': + case '\t': + found=PR_TRUE; + break; + default: + found=PR_FALSE; break; - } } - else if ((PRUint32)mBuffer.Length()<=mOffset) { - mOffset-=1; - result=Peek(theChar); - theBuf=mBuffer.GetUnicode(); - theOrigin=mOffset; + if(!found) { + break; } + else { + current++; + } + } + + SetPosition(current); + if (current == end) { + return Eof(); } //DoErrTest(aString); @@ -539,16 +582,20 @@ nsresult nsScanner::SkipWhitespace(void) { */ nsresult nsScanner::SkipOver(PRUnichar aSkipChar){ + if (!mSlidingBuffer) { + return kEOF; + } + PRUnichar ch=0; nsresult result=NS_OK; while(NS_OK==result) { - result=GetChar(ch); + result=Peek(ch); if(NS_OK == result) { if(ch!=aSkipChar) { - PutBack(ch); break; } + GetChar(ch); } else break; } //while @@ -565,17 +612,21 @@ nsresult nsScanner::SkipOver(PRUnichar aSkipChar){ */ nsresult nsScanner::SkipOver(nsString& aSkipSet){ + if (!mSlidingBuffer) { + return kEOF; + } + PRUnichar theChar=0; nsresult result=NS_OK; while(NS_OK==result) { - result=GetChar(theChar); + result=Peek(theChar); if(NS_OK == result) { PRInt32 pos=aSkipSet.FindChar(theChar); if(kNotFound==pos) { - PutBack(theChar); break; } + GetChar(theChar); } else break; } //while @@ -593,17 +644,21 @@ nsresult nsScanner::SkipOver(nsString& aSkipSet){ * @return error code */ nsresult nsScanner::SkipTo(nsString& aValidSet){ + if (!mSlidingBuffer) { + return kEOF; + } + PRUnichar ch=0; nsresult result=NS_OK; while(NS_OK==result) { - result=GetChar(ch); + result=Peek(ch); if(NS_OK == result) { PRInt32 pos=aValidSet.FindChar(ch); if(kNotFound!=pos) { - PutBack(ch); break; } + GetChar(ch); } else break; } //while @@ -649,17 +704,23 @@ nsresult nsScanner::SkipPast(nsString& aValidSet){ * @param aIgnore - If set ignores ':','-','_' * @return error code */ -nsresult nsScanner::GetIdentifier(nsSubsumeStr& aString,PRBool allowPunct) { +nsresult nsScanner::GetIdentifier(nsString& aString,PRBool allowPunct) { + + if (!mSlidingBuffer) { + return kEOF; + } PRUnichar theChar=0; nsresult result=Peek(theChar); - const PRUnichar* theBuf=mBuffer.GetUnicode(); - PRInt32 theOrigin=mOffset; + nsReadingIterator<PRUnichar> current, end; PRBool found=PR_FALSE; + + current = mCurrentPosition; + end = mEndPosition; - while(NS_OK==result) { + while(current != end) { - theChar=theBuf[mOffset++]; + theChar=*current; if(theChar) { found=PR_FALSE; switch(theChar) { @@ -679,14 +740,22 @@ nsresult nsScanner::GetIdentifier(nsSubsumeStr& aString,PRBool allowPunct) { } if(!found) { - mOffset-=1; - PRUnichar* thePtr=(PRUnichar*)&theBuf[theOrigin-1]; - aString.Subsume(thePtr,PR_FALSE,mOffset-theOrigin+1); + // If we the current character isn't a valid character for + // the identifier, we're done. Copy the results into + // the string passed in. + CopyUnicodeTo(mCurrentPosition, current, aString); break; } + + current++; } } + SetPosition(current); + if (current == end) { + result = Eof(); + } + //DoErrTest(aString); return result; @@ -702,15 +771,22 @@ nsresult nsScanner::GetIdentifier(nsSubsumeStr& aString,PRBool allowPunct) { */ nsresult nsScanner::ReadIdentifier(nsString& aString,PRBool allowPunct) { + if (!mSlidingBuffer) { + return kEOF; + } + PRUnichar theChar=0; nsresult result=Peek(theChar); - const PRUnichar* theBuf=mBuffer.GetUnicode(); - PRInt32 theOrigin=mOffset; + nsReadingIterator<PRUnichar> origin, current, end; PRBool found=PR_FALSE; - while(NS_OK==result) { + origin = mCurrentPosition; + current = mCurrentPosition; + end = mEndPosition; + + while(current != end) { - theChar=theBuf[mOffset++]; + theChar=*current; if(theChar) { found=PR_FALSE; switch(theChar) { @@ -730,19 +806,79 @@ nsresult nsScanner::ReadIdentifier(nsString& aString,PRBool allowPunct) { } if(!found) { - mOffset-=1; - aString.Append(&theBuf[theOrigin],mOffset-theOrigin); + AppendUnicodeTo(mCurrentPosition, current, aString); break; } + + current++; } - else if ((PRUint32)mBuffer.Length()<=mOffset) { - mOffset -= 1; - aString.Append(&theBuf[theOrigin],mOffset-theOrigin); - result=Peek(theChar); - theBuf=mBuffer.GetUnicode(); - theOrigin=mOffset; + } + + SetPosition(current); + if (current == end) { + AppendUnicodeTo(origin, current, aString); + return Eof(); + } + + //DoErrTest(aString); + + return result; +} + +nsresult nsScanner::ReadIdentifier(nsReadingIterator<PRUnichar>& aStart, + nsReadingIterator<PRUnichar>& aEnd, + PRBool allowPunct) { + + if (!mSlidingBuffer) { + return kEOF; + } + + PRUnichar theChar=0; + nsresult result=Peek(theChar); + nsReadingIterator<PRUnichar> origin, current, end; + PRBool found=PR_FALSE; + + origin = mCurrentPosition; + current = mCurrentPosition; + end = mEndPosition; + + while(current != end) { + + theChar=*current; + if(theChar) { + found=PR_FALSE; + switch(theChar) { + case ':': + case '_': + case '-': + found=allowPunct; + break; + default: + if(('a'<=theChar) && (theChar<='z')) + found=PR_TRUE; + else if(('A'<=theChar) && (theChar<='Z')) + found=PR_TRUE; + else if(('0'<=theChar) && (theChar<='9')) + found=PR_TRUE; + break; + } + + if(!found) { + aStart = mCurrentPosition; + aEnd = current; + break; + } + + current++; } } + + SetPosition(current); + if (current == end) { + aStart = origin; + aEnd = current; + return Eof(); + } //DoErrTest(aString); @@ -759,15 +895,22 @@ nsresult nsScanner::ReadIdentifier(nsString& aString,PRBool allowPunct) { */ nsresult nsScanner::ReadNumber(nsString& aString) { + if (!mSlidingBuffer) { + return kEOF; + } + PRUnichar theChar=0; nsresult result=Peek(theChar); - const PRUnichar* theBuf=mBuffer.GetUnicode(); - PRInt32 theOrigin=mOffset; + nsReadingIterator<PRUnichar> origin, current, end; PRBool found=PR_FALSE; - while(NS_OK==result) { + origin = mCurrentPosition; + current = origin; + end = mEndPosition; + + while(current != end) { - theChar=theBuf[mOffset++]; + theChar=*current; if(theChar) { found=PR_FALSE; if(('a'<=theChar) && (theChar<='f')) @@ -778,21 +921,74 @@ nsresult nsScanner::ReadNumber(nsString& aString) { found=PR_TRUE; else if('#'==theChar) found=PR_TRUE; + if(!found) { - mOffset-=1; - aString.Append(&theBuf[theOrigin],mOffset-theOrigin); + AppendUnicodeTo(origin, current, aString); break; } + + current++; } - else if ((PRUint32)mBuffer.Length()<=mOffset) { - mOffset -= 1; - aString.Append(&theBuf[theOrigin],mOffset-theOrigin); - result=Peek(theChar); - theBuf=mBuffer.GetUnicode(); - theOrigin=mOffset; + } + + SetPosition(current); + if (current == end) { + AppendUnicodeTo(origin, current, aString); + return Eof(); + } + + //DoErrTest(aString); + + return result; +} + +nsresult nsScanner::ReadNumber(nsReadingIterator<PRUnichar>& aStart, + nsReadingIterator<PRUnichar>& aEnd) { + + if (!mSlidingBuffer) { + return kEOF; + } + + PRUnichar theChar=0; + nsresult result=Peek(theChar); + nsReadingIterator<PRUnichar> origin, current, end; + PRBool found=PR_FALSE; + + origin = mCurrentPosition; + current = origin; + end = mEndPosition; + + while(current != end) { + + theChar=*current; + if(theChar) { + found=PR_FALSE; + if(('a'<=theChar) && (theChar<='f')) + found=PR_TRUE; + else if(('A'<=theChar) && (theChar<='F')) + found=PR_TRUE; + else if(('0'<=theChar) && (theChar<='9')) + found=PR_TRUE; + else if('#'==theChar) + found=PR_TRUE; + + if(!found) { + aStart = origin; + aEnd = current; + break; + } + + current++; } } + SetPosition(current); + if (current == end) { + aStart = origin; + aEnd = current; + return Eof(); + } + //DoErrTest(aString); return result; @@ -808,15 +1004,22 @@ nsresult nsScanner::ReadNumber(nsString& aString) { */ nsresult nsScanner::ReadWhitespace(nsString& aString) { + if (!mSlidingBuffer) { + return kEOF; + } + PRUnichar theChar=0; nsresult result=Peek(theChar); - const PRUnichar* theBuf=mBuffer.GetUnicode(); - PRInt32 theOrigin=mOffset; + nsReadingIterator<PRUnichar> origin, current, end; PRBool found=PR_FALSE; - while(NS_OK==result) { + origin = mCurrentPosition; + current = origin; + end = mEndPosition; + + while(current != end) { - theChar=theBuf[mOffset++]; + theChar=*current; if(theChar) { switch(theChar) { case ' ': @@ -831,18 +1034,18 @@ nsresult nsScanner::ReadWhitespace(nsString& aString) { break; } if(!found) { - mOffset-=1; - aString.Append(&theBuf[theOrigin],mOffset-theOrigin); + AppendUnicodeTo(origin, current, aString); break; } + + current ++; } - else if ((PRUint32)mBuffer.Length()<=mOffset) { - mOffset -= 1; - aString.Append(&theBuf[theOrigin],mOffset-theOrigin); - result=Peek(theChar); - theBuf=mBuffer.GetUnicode(); - theOrigin=mOffset; - } + } + + SetPosition(current); + if (current == end) { + AppendUnicodeTo(origin, current, aString); + return Eof(); } //DoErrTest(aString); @@ -850,6 +1053,59 @@ nsresult nsScanner::ReadWhitespace(nsString& aString) { return result; } +nsresult nsScanner::ReadWhitespace(nsReadingIterator<PRUnichar>& aStart, + nsReadingIterator<PRUnichar>& aEnd) { + + if (!mSlidingBuffer) { + return kEOF; + } + + PRUnichar theChar=0; + nsresult result=Peek(theChar); + nsReadingIterator<PRUnichar> origin, current, end; + PRBool found=PR_FALSE; + + origin = mCurrentPosition; + current = origin; + end = mEndPosition; + + while(current != end) { + + theChar=*current; + if(theChar) { + switch(theChar) { + case ' ': + case '\b': + case '\t': + case kLF: + case kCR: + found=PR_TRUE; + break; + default: + found=PR_FALSE; + break; + } + if(!found) { + aStart = origin; + aEnd = current; + break; + } + + current ++; + } + } + + SetPosition(current); + if (current == end) { + aStart = origin; + aEnd = current; + return Eof(); + } + + //DoErrTest(aString); + + return result; +} /** * Consume chars as long as they are <i>in</i> the @@ -865,30 +1121,38 @@ nsresult nsScanner::ReadWhile(nsString& aString, nsString& aValidSet, PRBool addTerminal){ + if (!mSlidingBuffer) { + return kEOF; + } + PRUnichar theChar=0; nsresult result=Peek(theChar); - const PRUnichar* theBuf=mBuffer.GetUnicode(); - PRInt32 theOrigin=mOffset; + nsReadingIterator<PRUnichar> origin, current, end; - while(NS_OK==result) { + origin = mCurrentPosition; + current = origin; + end = mEndPosition; + + while(current != end) { - theChar=theBuf[mOffset++]; + theChar=*current; if(theChar) { PRInt32 pos=aValidSet.FindChar(theChar); if(kNotFound==pos) { - if(!addTerminal) - mOffset-=1; - aString.Append(&theBuf[theOrigin],mOffset-theOrigin); + if(addTerminal) + current++; + AppendUnicodeTo(origin, current, aString); break; } + + current++; } - else if ((PRUint32)mBuffer.Length()<=mOffset) { - mOffset -= 1; - aString.Append(&theBuf[theOrigin],mOffset-theOrigin); - result=Peek(theChar); - theBuf=mBuffer.GetUnicode(); - theOrigin=mOffset; - } + } + + SetPosition(current); + if (current == end) { + AppendUnicodeTo(origin, current, aString); + return Eof(); } //DoErrTest(aString); @@ -911,31 +1175,37 @@ nsresult nsScanner::ReadUntil(nsString& aString, nsString& aTerminalSet, PRBool addTerminal){ + if (!mSlidingBuffer) { + return kEOF; + } PRUnichar theChar=0; nsresult result=Peek(theChar); - const PRUnichar* theBuf=mBuffer.GetUnicode(); - PRInt32 theOrigin=mOffset; + nsReadingIterator<PRUnichar> origin, current, end; - while(NS_OK==result) { + origin = mCurrentPosition; + current = origin; + end = mEndPosition; + + while(current != end) { - theChar=theBuf[mOffset++]; + theChar=*current; if(theChar) { PRInt32 pos=aTerminalSet.FindChar(theChar); if(kNotFound!=pos) { - if(!addTerminal) - mOffset-=1; - aString.Append(&theBuf[theOrigin],mOffset-theOrigin); + if(addTerminal) + current++; + AppendUnicodeTo(origin, current, aString); break; - } - } - else if ((PRUint32)mBuffer.Length()<=mOffset) { - mOffset -= 1; - aString.Append(&theBuf[theOrigin],mOffset-theOrigin); - result=Peek(theChar); - theBuf=mBuffer.GetUnicode(); - theOrigin=mOffset; + } } + current++; + } + + SetPosition(current); + if (current == end) { + AppendUnicodeTo(origin, current, aString); + return Eof(); } //DoErrTest(aString); @@ -958,38 +1228,87 @@ nsresult nsScanner::ReadUntil(nsString& aString, nsCString& aTerminalSet, PRBool addTerminal){ + if (!mSlidingBuffer) { + return kEOF; + } + PRUnichar theChar=0; nsresult result=Peek(theChar); - const PRUnichar* theBuf=mBuffer.GetUnicode(); - PRInt32 theOrigin=mOffset; + nsReadingIterator<PRUnichar> origin, current, end; - while(NS_OK==result) { + origin = mCurrentPosition; + current = origin; + end = mEndPosition; + + while(current != end) { - theChar=theBuf[mOffset++]; + theChar=*current; if(theChar) { PRInt32 pos=aTerminalSet.FindChar(theChar); if(kNotFound!=pos) { - if(!addTerminal) - mOffset-=1; - aString.Append(&theBuf[theOrigin],mOffset-theOrigin); + if(addTerminal) + current++; + AppendUnicodeTo(origin, current, aString); break; } } - else if ((PRUint32)mBuffer.Length()<=mOffset) { - mOffset -= 1; - aString.Append(&theBuf[theOrigin],mOffset-theOrigin); - result=Peek(theChar); - theBuf=mBuffer.GetUnicode(); - theOrigin=mOffset; - } + current++; } + SetPosition(current); + if (current == end) { + AppendUnicodeTo(origin, current, aString); + return Eof(); + } //DoErrTest(aString); return result; } +nsresult nsScanner::ReadUntil(nsReadingIterator<PRUnichar>& aStart, + nsReadingIterator<PRUnichar>& aEnd, + nsString& aTerminalSet, + PRBool addTerminal){ + + if (!mSlidingBuffer) { + return kEOF; + } + + PRUnichar theChar=0; + nsresult result=Peek(theChar); + nsReadingIterator<PRUnichar> origin, current, end; + + origin = mCurrentPosition; + current = origin; + end = mEndPosition; + + while(current != end) { + + theChar=*current; + if(theChar) { + PRInt32 pos=aTerminalSet.FindChar(theChar); + if(kNotFound!=pos) { + if(addTerminal) + current++; + aStart = origin; + aEnd = current; + break; + } + } + current++; + } + + SetPosition(current); + if (current == end) { + aStart = origin; + aEnd = current; + return Eof(); + } + + return result; +} + /** * Consume characters until you encounter one contained in given * input set. @@ -1004,6 +1323,10 @@ nsresult nsScanner::ReadUntil(nsString& aString, const char* aTerminalSet, PRBool addTerminal) { + if (!mSlidingBuffer) { + return kEOF; + } + nsresult result=NS_OK; if(aTerminalSet) { PRInt32 len=nsCRT::strlen(aTerminalSet); @@ -1028,32 +1351,36 @@ nsresult nsScanner::ReadUntil(nsString& aString, nsresult nsScanner::ReadUntil(nsString& aString, PRUnichar aTerminalChar, PRBool addTerminal){ + if (!mSlidingBuffer) { + return kEOF; + } + PRUnichar theChar=0; - nsresult result=NS_OK; + nsresult result=Peek(theChar); + nsReadingIterator<PRUnichar> origin, current, end; - const PRUnichar* theBuf=mBuffer.GetUnicode(); - PRInt32 theOrigin=mOffset; - result=Peek(theChar); - PRUint32 theLen=mBuffer.Length(); + origin = mCurrentPosition; + current = origin; + end = mEndPosition; - while(NS_OK==result) { + while(current != end) { - theChar=theBuf[mOffset++]; + theChar=*current; if(theChar) { if(aTerminalChar==theChar) { - if(!addTerminal) - mOffset-=1; - aString.Append(&theBuf[theOrigin],mOffset-theOrigin); + if(addTerminal) + current++; + AppendUnicodeTo(origin, current, aString); break; } } - else if ((PRUint32)mBuffer.Length()<=mOffset) { - mOffset -= 1; - aString.Append(&theBuf[theOrigin],theLen-theOrigin); - mOffset=theLen; - result=Peek(theChar); - theLen=mBuffer.Length(); - } + current++; + } + + SetPosition(current); + if (current == end) { + AppendUnicodeTo(origin, current, aString); + return Eof(); } //DoErrTest(aString); @@ -1061,19 +1388,69 @@ nsresult nsScanner::ReadUntil(nsString& aString, } +void nsScanner::BindSubstring(nsSlidingSubstring& aSubstring, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd) +{ + aSubstring.Rebind(*mSlidingBuffer, aStart, aEnd); +} -/** - * - * @update gess 3/25/98 - * @param - * @return - */ -nsString& nsScanner::GetBuffer(void) { - return mBuffer; +void nsScanner::CurrentPosition(nsReadingIterator<PRUnichar>& aPosition) +{ + aPosition = mCurrentPosition; +} + +void nsScanner::EndReading(nsReadingIterator<PRUnichar>& aPosition) +{ + aPosition = mEndPosition; +} + +void nsScanner::SetPosition(nsReadingIterator<PRUnichar>& aPosition, PRBool aTerminate, PRBool aReverse) +{ + if (mSlidingBuffer) { + if (aReverse) { + mCountRemaining += (Distance(aPosition, mCurrentPosition)); + } + else { + mCountRemaining -= (Distance(mCurrentPosition, aPosition)); + } + mCurrentPosition = aPosition; + if (aTerminate && (mCurrentPosition == mEndPosition)) { + mMarkPosition = mCurrentPosition; + mSlidingBuffer->DiscardPrefix(mCurrentPosition); + } + } +} + +void nsScanner::ReplaceCharacter(nsReadingIterator<PRUnichar>& aPosition, + PRUnichar aChar) +{ + if (mSlidingBuffer) { + mSlidingBuffer->ReplaceCharacter(aPosition, aChar); + } +} + +void nsScanner::AppendToBuffer(PRUnichar* aStorageStart, + PRUnichar* aDataEnd, + PRUnichar* aStorageEnd) +{ + if (!mSlidingBuffer) { + mSlidingBuffer = new nsScannerString(aStorageStart, aDataEnd, aStorageEnd); + mSlidingBuffer->BeginReading(mCurrentPosition); + mMarkPosition = mCurrentPosition; + mSlidingBuffer->EndReading(mEndPosition); + mCountRemaining = (aDataEnd - aStorageStart); + } + else { + mSlidingBuffer->AppendBuffer(aStorageStart, aDataEnd, aStorageEnd); + if (mCurrentPosition == mEndPosition) { + mSlidingBuffer->BeginReading(mCurrentPosition); + } + mSlidingBuffer->EndReading(mEndPosition); + mCountRemaining += (aDataEnd - aStorageStart); + } } /** - * Call this to copy bytes out of the scanner that have not yet been consumed + * call this to copy bytes out of the scanner that have not yet been consumed * by the tokenization process. * * @update gess 5/12/98 @@ -1081,10 +1458,11 @@ nsString& nsScanner::GetBuffer(void) { * @return nada */ void nsScanner::CopyUnusedData(nsString& aCopyBuffer) { - PRInt32 theLen=mBuffer.Length(); - if(0<theLen) { - mBuffer.Right(aCopyBuffer,theLen-mMarkPos); - } + nsReadingIterator<PRUnichar> start, end; + start = mCurrentPosition; + end = mEndPosition; + + CopyUnicodeTo(start, end, aCopyBuffer); } /** diff --git a/mozilla/htmlparser/src/nsScanner.h b/mozilla/htmlparser/src/nsScanner.h index cb75d5b40df..e904af37b25 100644 --- a/mozilla/htmlparser/src/nsScanner.h +++ b/mozilla/htmlparser/src/nsScanner.h @@ -41,7 +41,19 @@ #include "prtypes.h" #include "nsIUnicodeDecoder.h" #include "nsFileStream.h" +#include "nsSlidingString.h" +class nsScannerString : public nsSlidingString { + public: + nsScannerString(PRUnichar* aStorageStart, + PRUnichar* aDataEnd, + PRUnichar* aStorageEnd); + virtual void InsertBuffer(PRUnichar* aStorageStart, + PRUnichar* aDataEnd, + PRUnichar* aStorageEnd); + virtual void ReplaceCharacter(nsReadingIterator<PRUnichar>& aPosition, + PRUnichar aChar); +}; class nsScanner { public: @@ -102,16 +114,9 @@ class nsScanner { * @param ch is the char to accept new value * @return error code reflecting read status */ - nsresult Peek(PRUnichar& ch); + nsresult Peek(PRUnichar& ch, PRUint32 aOffset=0); - /** - * Push the given char back onto the scanner - * - * @update gess 3/25/98 - * @param character to be pushed - * @return error code - */ - nsresult PutBack(PRUnichar ch); + nsresult Peek(nsAWritableString& aStr, PRInt32 aNumChars); /** * Skip over chars as long as they're in aSkipSet @@ -175,10 +180,17 @@ class nsScanner { * @param addTerminal tells us whether to append terminal to aString * @return error code */ - nsresult GetIdentifier(nsSubsumeStr& aString,PRBool allowPunct=PR_FALSE); + nsresult GetIdentifier(nsString& aString,PRBool allowPunct=PR_FALSE); nsresult ReadIdentifier(nsString& aString,PRBool allowPunct=PR_FALSE); + nsresult ReadIdentifier(nsReadingIterator<PRUnichar>& aStart, + nsReadingIterator<PRUnichar>& aEnd, + PRBool allowPunct=PR_FALSE); nsresult ReadNumber(nsString& aString); + nsresult ReadNumber(nsReadingIterator<PRUnichar>& aStart, + nsReadingIterator<PRUnichar>& aEnd); nsresult ReadWhitespace(nsString& aString); + nsresult ReadWhitespace(nsReadingIterator<PRUnichar>& aStart, + nsReadingIterator<PRUnichar>& aEnd); /** * Consume characters until you find the terminal char @@ -204,6 +216,8 @@ class nsScanner { nsresult ReadUntil(nsString& aString,nsString& aTermSet,PRBool addTerminal); nsresult ReadUntil(nsString& aString,nsCString& aTermSet,PRBool addTerminal); nsresult ReadUntil(nsString& aString,const char* aTermSet,PRBool addTerminal); + nsresult ReadUntil(nsReadingIterator<PRUnichar>& aStart, nsReadingIterator<PRUnichar>& aEnd, nsString& aTerminalSet,PRBool addTerminal); + /** * Consume characters while they're members of anInputSet @@ -225,7 +239,7 @@ class nsScanner { * @param * @return */ - PRUint32 Mark(PRInt32 anIndex=-1); + void Mark(void); /** * Resets current offset position of input stream to marked position. @@ -237,7 +251,7 @@ class nsScanner { * @param * @return */ - PRUint32 RewindToMark(void); + void RewindToMark(void); /** @@ -267,17 +281,6 @@ class nsScanner { */ PRBool Append(const char* aBuffer, PRUint32 aLen); - PRBool Append(const PRUnichar* aBuffer, PRUint32 aLen); - - /** - * - * - * @update gess 5/12/98 - * @param - * @return - */ - nsString& GetBuffer(void); - /** * Call this to copy bytes out of the scanner that have not yet been consumed * by the tokenization process. @@ -310,6 +313,15 @@ class nsScanner { */ nsresult SetDocumentCharset(const nsString& aCharset, nsCharsetSource aSource); + void BindSubstring(nsSlidingSubstring& aSubstring, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd); + void CurrentPosition(nsReadingIterator<PRUnichar>& aPosition); + void EndReading(nsReadingIterator<PRUnichar>& aPosition); + void SetPosition(nsReadingIterator<PRUnichar>& aPosition, + PRBool aTruncate = PR_FALSE, + PRBool aReverse = PR_FALSE); + void ReplaceCharacter(nsReadingIterator<PRUnichar>& aPosition, + PRUnichar aChar); + /** * Internal method used to cause the internal buffer to * be filled with data. @@ -319,7 +331,6 @@ class nsScanner { PRBool IsIncremental(void) {return mIncremental;} void SetIncremental(PRBool anIncrValue) {mIncremental=anIncrValue;} - PRUint32 GetOffset(void) {return mOffset;} PRInt32 GetNewlinesSkipped(void) { return mNewlinesSkipped; } protected: @@ -335,18 +346,24 @@ class nsScanner { */ nsresult FillBuffer(void); + void AppendToBuffer(PRUnichar* aStorageStart, + PRUnichar* aDataEnd, + PRUnichar* aStorageEnd); + nsInputStream* mInputStream; - nsString mBuffer; + nsScannerString* mSlidingBuffer; + nsReadingIterator<PRUnichar> mCurrentPosition; // The position we will next read from in the scanner buffer + nsReadingIterator<PRUnichar> mMarkPosition; // The position last marked (we may rewind to here) + nsReadingIterator<PRUnichar> mEndPosition; // The current end of the scanner buffer nsString mFilename; - PRUint32 mOffset; - PRUint32 mMarkPos; + PRUint32 mCountRemaining; // The number of bytes still to be read + // from the scanner buffer PRUint32 mTotalRead; PRBool mOwnsStream; PRBool mIncremental; nsCharsetSource mCharsetSource; nsString mCharset; nsIUnicodeDecoder *mUnicodeDecoder; - nsString mUnicodeXferBuf; PRInt32 mNewlinesSkipped; }; diff --git a/mozilla/htmlparser/src/nsToken.cpp b/mozilla/htmlparser/src/nsToken.cpp index afa33922a92..94573df308a 100644 --- a/mozilla/htmlparser/src/nsToken.cpp +++ b/mozilla/htmlparser/src/nsToken.cpp @@ -43,7 +43,7 @@ int CToken::GetTokenCount(){return TokenCount-DelTokenCount;} * * @update gess 7/21/98 */ -CToken::CToken(PRInt32 aTag) : mTextValue() { +CToken::CToken(PRInt32 aTag) { // Tokens are allocated through the arena ( not heap allocated..yay ). // We, therefore, don't need this macro anymore.. #ifdef MATCH_CTOR_DTOR @@ -65,65 +65,6 @@ CToken::CToken(PRInt32 aTag) : mTextValue() { #endif } -/** - * Constructor with string for tagname assignment - * - * @update gess 3/25/98 - * @param nsString--name of token - */ -CToken::CToken(const nsString& aName) : mTextValue(aName) { - // Tokens are allocated through the arena ( not heap allocated..yay ). - // We, therefore, don't need this macro anymore.. -#ifdef MATCH_CTOR_DTOR - MOZ_COUNT_CTOR(CToken); -#endif - - mTypeID=0; - mAttrCount=0; - mNewlineCount=0; - mOrigin=eSource; - // Note that the use count starts with 1 instead of 0. This - // is because of the assumption that any token created is in - // use and therefore does not require an explicit addref, or - // rather IF_HOLD. This, also, will make sure that tokens created - // on the stack do not accidently hit the arena recycler. - mUseCount=1; - -#ifdef NS_DEBUG - TokenCount++; -#endif -} - -/** - * constructor from char* - * - * @update gess 3/25/98 - * @param aName--char* containing name of token - */ -CToken::CToken(const char* aName) { - // Tokens are allocated through the arena ( not heap allocated..yay ). - // We, therefore, don't need this macro anymore.. -#ifdef MATCH_CTOR_DTOR - MOZ_COUNT_CTOR(CToken); -#endif - - mTypeID=0; - mAttrCount=0; - mNewlineCount=0; - mOrigin=eSource; - mTextValue.AssignWithConversion(aName); - // Note that the use count starts with 1 instead of 0. This - // is because of the assumption that any token created is in - // use and therefore does not require an explicit addref, or - // rather IF_HOLD. This, also, will make sure that tokens created - // on the stack do not accidently hit the arena recycler. - mUseCount=1; - -#ifdef NS_DEBUG - TokenCount++; -#endif -} - /** * Decstructor * @@ -139,31 +80,6 @@ CToken::~CToken() { mUseCount=0; } - -/** - * This method gets called when a token is about to be reused - * for some other purpose. The token should initialize itself - * to some reasonable default values. - * @update gess7/25/98 - * @param aTag - * @param aString - */ -void CToken::Reinitialize(PRInt32 aTag, const nsString& aString){ - if(0==aString.Length()) - mTextValue.Truncate(0); - else mTextValue=aString; - mAttrCount=0; - mAttrCount=0; - mNewlineCount=0; - mTypeID=aTag; - mOrigin=eSource; - // Note that the use count starts with 1 instead of 0. This - // is because of the assumption that any token created is in - // use and therefore does not require an explicit addref, or - // rather IF_HOLD. This, also, will make sure that tokens created - // on the stack do not accidently hit the arena recycler. - mUseCount=1; -} /** * Virtual method used to tell this toke to consume his @@ -190,9 +106,9 @@ nsresult CToken::Consume(PRUnichar aChar,nsScanner& aScanner,PRInt32 aMode) { void CToken::DebugDumpToken(nsOutputStream& anOutputStream) { anOutputStream << "[" << GetClassName() << "] "; PRUint32 i=0; - PRUint32 theLen=mTextValue.Length(); + PRUint32 theLen=GetStringValue().Length(); for(i=0;i<theLen;i++){ - anOutputStream << char(mTextValue.CharAt(i)); + anOutputStream << (const char*)NS_ConvertUCS2toUTF8(GetStringValue()); } anOutputStream << " TypeID: " << mTypeID << " AttrCount: " << mAttrCount << nsEndl; } @@ -205,36 +121,9 @@ void CToken::DebugDumpToken(nsOutputStream& anOutputStream) { * @param ostream -- output stream to accept output data */ void CToken::DebugDumpSource(nsOutputStream& anOutputStream) { - char buf[256]; - mTextValue.ToCString(buf,sizeof(buf)); - anOutputStream << buf; + anOutputStream << (const char*)NS_ConvertUCS2toUTF8(GetStringValue()); } -/** - * Setter method that changes the string value of this token - * @update gess5/11/98 - * @param name is a char* value containing new string value - */ -void CToken::SetCStringValue(const char* name){ - mTextValue.AssignWithConversion(name); -} - -/** - * Setter method for the string value of this token - */ -void CToken::SetStringValue(nsString& aStr) { - mTextValue = aStr; -} - -/** - * This method retrieves the value of this internal string. - * - * @update gess 3/25/98 - * @return nsString reference to internal string value - */ -nsString& CToken::GetStringValueXXX(void) { - return mTextValue; -} /** * Get string of full contents, suitable for debug dump. @@ -243,7 +132,7 @@ nsString& CToken::GetStringValueXXX(void) { * @return reference to string containing string value */ void CToken::GetSource(nsString& anOutputString){ - anOutputString=mTextValue; + anOutputString.Assign(GetStringValue()); } /** @@ -251,19 +140,7 @@ void CToken::GetSource(nsString& anOutputString){ * @return reference to string containing string value */ void CToken::AppendSource(nsString& anOutputString){ - anOutputString+=mTextValue; -} - -/** - * This method retrieves the value of this internal string - * as a cstring. - * - * @update gess 3/25/98 - * @return char* rep of internal string value - */ -char* CToken::GetCStringValue(char* aBuffer, PRInt32 aMaxLen) { - strcpy(aBuffer,"string"); - return aBuffer; + anOutputString.Append(GetStringValue()); } /** diff --git a/mozilla/htmlparser/src/nsToken.h b/mozilla/htmlparser/src/nsToken.h index 80684f25a58..8fe686c4334 100644 --- a/mozilla/htmlparser/src/nsToken.h +++ b/mozilla/htmlparser/src/nsToken.h @@ -114,42 +114,18 @@ class CToken { */ CToken(PRInt32 aTag=0); - /** - * Constructor with string assignment for tag - * @update gess5/11/98 - * @param aName is the given name of the token - */ - CToken(const nsString& aName); - - /** - * constructor from char* - * @update gess5/11/98 - * @param aName is the given name of the token - */ - CToken(const char* aName); - /** * destructor * @update gess5/11/98 */ virtual ~CToken(); - /** - * This method gets called when a token is about to be reused - * for some other purpose. The token should reinit itself to - * some reasonable default values. - * @update gess7/25/98 - * @param aTag - * @param aString - */ - virtual void Reinitialize(PRInt32 aTag, const nsString& aString); - /** * Retrieve string value of the token * @update gess5/11/98 * @return reference to string containing string value */ - virtual nsString& GetStringValueXXX(void); + virtual const nsAReadableString& GetStringValue(void) = 0; /** * Get string of full contents, suitable for debug dump. @@ -164,25 +140,6 @@ class CToken { */ virtual void AppendSource(nsString& anOutputString); - /** - * Setter method that changes the string value of this token - * @update gess5/11/98 - * @param name is a char* value containing new string value - */ - virtual void SetCStringValue(const char* name); - - /** - * Setter method for the string value of this token - */ - virtual void SetStringValue(nsString& aStr); - - /** - * Retrieve string value of the token as a c-string - * @update gess5/11/98 - * @return reference to string containing string value - */ - virtual char* GetCStringValue(char* aBuffer, PRInt32 aMaxLen); - /** * Sets the ordinal value of this token (not currently used) * @update gess5/11/98 @@ -276,7 +233,6 @@ protected: PRInt32 mTypeID; PRInt16 mAttrCount; - nsString mTextValue; PRInt32 mUseCount; }; diff --git a/mozilla/htmlparser/src/nsViewSourceHTML.cpp b/mozilla/htmlparser/src/nsViewSourceHTML.cpp index ab13dfade48..e2d4cdaed49 100644 --- a/mozilla/htmlparser/src/nsViewSourceHTML.cpp +++ b/mozilla/htmlparser/src/nsViewSourceHTML.cpp @@ -74,6 +74,7 @@ static NS_DEFINE_CID(kPrefCID, NS_PREF_CID); #endif // VIEW_SOURCE_COLORING #include "COtherDTD.h" +#include "nsElementTable.h" #include "prenv.h" //this is here for debug reasons... #include "prtypes.h" //this is here for debug reasons... @@ -169,15 +170,15 @@ public: mIndirectString=0; } - void SetIndirectString(const nsString& aString) { + void SetIndirectString(const nsAReadableString& aString) { mIndirectString=&aString; } - virtual nsString& GetStringValueXXX(void){ - return (nsString&)*mIndirectString; + virtual const nsAReadableString& GetStringValue(void){ + return (nsAReadableString&)*mIndirectString; } - const nsString* mIndirectString; + const nsAReadableString* mIndirectString; }; @@ -196,7 +197,7 @@ public: mITextToken(), mITextNode(&mITextToken), mTextToken(), - mErrorToken("error"), + mErrorToken(NS_ConvertASCIItoUCS2("error")), mTextNode(&mTextToken){ } @@ -215,7 +216,7 @@ public: CIndirectTextToken mITextToken; nsCParserNode mITextNode; CTextToken mTextToken; - CToken mErrorToken; + CTextToken mErrorToken; nsCParserNode mTextNode; }; @@ -235,6 +236,7 @@ enum { VIEW_SOURCE_POPUP = 11 }; +#ifdef VIEW_SOURCE_COLORING static char* kElementStyles[] = { "color: purple; font-weight:bold;", "color: purple; font-weight:bold;", @@ -249,6 +251,7 @@ static char* kElementStyles[] = { "display:block; background-color:#FFFFCC; width:90%; border:solid; border-width:1pt; font-family: Sans-serif;", "font-weight: normal;" }; +#endif static char* kBeforeText[] = { "<", @@ -327,6 +330,7 @@ CViewSourceHTML::CViewSourceHTML() : mTags(), mErrors() { mDocType=eHTML3Text; mValidator=0; mHasOpenRoot=PR_FALSE; + mInCDATAContainer = PR_FALSE; //set this to 1 if you want to see errors in your HTML markup. char* theEnvString = PR_GetEnv("MOZ_VALIDATE_HTML"); @@ -445,19 +449,17 @@ nsresult CViewSourceHTML::WillBuildModel( const CParserContext& aParserContext, nsAutoString tag; tag.AssignWithConversion("HTML"); - CStartToken htmlToken(eHTMLTag_html); - htmlToken.SetStringValue(tag); + CStartToken htmlToken(tag, eHTMLTag_html); nsCParserNode htmlNode(&htmlToken,0); mSink->OpenHTML(htmlNode); tag.AssignWithConversion("BODY"); - CStartToken bodyToken(eHTMLTag_body); - bodyToken.SetStringValue(tag); + CStartToken bodyToken(tag, eHTMLTag_body); nsCParserNode bodyNode(&bodyToken,0); mSink->OpenBody(bodyNode); #else static const char* theHeader="<?xml version=\"1.0\"?>"; - CToken ssToken(theHeader); + CCommentToken ssToken(theHeader); nsCParserNode ssNode(&ssToken); result= mSink->AddCharacterData(ssNode); #endif // VIEW_SOURCE_HTML @@ -500,11 +502,10 @@ NS_IMETHODIMP CViewSourceHTML::BuildModel(nsIParser* aParser,nsITokenizer* aToke #ifdef VIEW_SOURCE_HTML nsAutoString tag; tag.AssignWithConversion("PRE"); - CStartToken theToken(eHTMLTag_pre); - theToken.SetStringValue(tag); + CStartToken theToken(tag, eHTMLTag_pre); #else //now let's automatically open the root container... - CToken theToken("viewsource"); + CStartToken theToken("viewsource"); #endif // VIEW_SOURCE_HTML nsCParserNode theNode(&theToken,0); @@ -513,12 +514,10 @@ NS_IMETHODIMP CViewSourceHTML::BuildModel(nsIParser* aParser,nsITokenizer* aToke if(theAllocator) { #ifdef VIEW_SOURCE_HTML theAttr=(CAttributeToken*)theAllocator->CreateTokenOfType(eToken_attribute,eHTMLTag_unknown,NS_ConvertToString(kPreStyle)); - nsString& theKey=theAttr->GetKey(); - theKey=NS_ConvertToString("style"); + theAttr->SetKey(NS_LITERAL_STRING("style")); #else theAttr=(CAttributeToken*)theAllocator->CreateTokenOfType(eToken_attribute,eHTMLTag_unknown,NS_ConvertToString("http://www.mozilla.org/viewsource")); - nsString& theKey=theAttr->GetKey(); - theKey=NS_ConvertToString("xmlns"); + theAttr->SetKey(NS_LITERAL_STRING("xmlns")); #endif // VIEW_SOURCE_HTML } if(theAttr) @@ -604,23 +603,15 @@ NS_IMETHODIMP CViewSourceHTML::DidBuildModel(nsresult anErrorCode,PRBool aNotify if(ePlainText!=mDocType) { #ifdef VIEW_SOURCE_HTML - nsAutoString tag; - - tag.AssignWithConversion("PRE"); CEndToken theToken(eHTMLTag_pre); - theToken.SetStringValue(tag); nsCParserNode preNode(&theToken,0); mSink->CloseContainer(preNode); - tag.AssignWithConversion("BODY"); CEndToken bodyToken(eHTMLTag_body); - bodyToken.SetStringValue(tag); nsCParserNode bodyNode(&bodyToken,0); mSink->CloseBody(bodyNode); - tag.AssignWithConversion("HTML"); CEndToken htmlToken(eHTMLTag_html); - htmlToken.SetStringValue(tag); nsCParserNode htmlNode(&htmlToken,0); mSink->CloseHTML(htmlNode); #else @@ -628,7 +619,7 @@ NS_IMETHODIMP CViewSourceHTML::DidBuildModel(nsresult anErrorCode,PRBool aNotify GenerateSummary(); - CToken theToken("viewsource"); + CEndToken theToken("viewsource"); nsCParserNode theNode(&theToken,0); mSink->CloseContainer(theNode); #endif // VIEW_SOURCE_HTML @@ -821,120 +812,6 @@ PRBool CViewSourceHTML::IsContainer(PRInt32 aTag) const{ return result; } - -/** - * This method gets called when a tag needs to be sent out - * - * @update gess 3/25/98 - * @param - * @return result status - */ -nsresult WriteText(const nsString& aTextString,nsIContentSink& aSink,PRBool aPreserveSpace,PRBool aPlainText,CSharedVSContext& aContext) { - nsresult result=NS_OK; - - nsString& temp=aContext.mTextToken.GetStringValueXXX(); - temp.Truncate(); - - PRInt32 theEnd=aTextString.Length(); - PRInt32 theTextOffset=0; - PRInt32 theOffset=-1; //aTextString.FindCharInSet("\t\n\r ",theStartOffset); - PRInt32 theSpaces=0; - PRUnichar theChar=0; - PRUnichar theNextChar=0; - - while(++theOffset<theEnd){ - //theNextChar=aTextString[theOffset-1]; - theChar=aTextString[theOffset]; - switch(theChar){ - case kSpace: - theNextChar=(theOffset+1 != theEnd) ? aTextString[theOffset+1] : '\0'; - if((!aPlainText) && aPreserveSpace) { //&& ((kSpace==theNextChar) || (0==theNextChar))) - if(theTextOffset<theOffset) { - if(kSpace==theNextChar) { - aTextString.Mid(temp,theTextOffset,theOffset-theTextOffset); - theTextOffset=theOffset--; - } - } - else{ - while((theOffset<theEnd) && (kSpace==aTextString[theOffset])){ - theOffset++; - theSpaces++; - } - theTextOffset=theOffset--; - } - } - break; - - case kTab: - if((!aPlainText) && aPreserveSpace){ - if(theTextOffset<theOffset) { - aTextString.Mid(temp,theTextOffset,theOffset-theTextOffset); - } - theSpaces+=8; - theOffset++; - theTextOffset=theOffset; - } - break; - - case kCR: - case kLF: - if(theTextOffset<theOffset) { - aTextString.Mid(temp,theTextOffset,theOffset-theTextOffset); - theTextOffset=theOffset--; //back up one on purpose... - } - else { - theNextChar=(theOffset+1 != theEnd) ? aTextString.CharAt(theOffset+1) : '\0'; - if((kCR==theChar) && (kLF==theNextChar)) { - theOffset++; - } - - CStartToken theToken(eHTMLTag_br); - aContext.mStartNode.Init(&theToken,0); - result=aSink.AddLeaf(aContext.mStartNode); - theTextOffset=theOffset+1; - } - break; - - default: - break; - } //switch - if(0<temp.Length()){ - result=aSink.AddLeaf(aContext.mTextNode); - temp.Truncate(); - } - if(0<theSpaces){ - - CEntityToken theToken( NS_ConvertToString("nbsp") ); - aContext.mStartNode.Init(&theToken,0); - int theIndex; - for(theIndex=0;theIndex<theSpaces;theIndex++) - result=aSink.AddLeaf(aContext.mStartNode); - theSpaces=0; - } - } - - if(theTextOffset<theEnd){ - temp.Truncate(); - aTextString.Mid(temp,theTextOffset,theEnd-theTextOffset); - result=aSink.AddLeaf(aContext.mTextNode); //just dump the whole string... - } - - return result; -} - -/** - * This method gets called when a tag needs to be sent out - * - * @update gess 3/25/98 - * @param - * @return result status - */ -nsresult CViewSourceHTML::WriteText(const nsString& aTextString,nsIContentSink& aSink,PRBool aPreserveSpace,PRBool aPlainText) { - CSharedVSContext& theContext=CSharedVSContext::GetSharedContext(); - return ::WriteText(aTextString,aSink,aPreserveSpace,aPlainText,theContext); -} - - /** * This method gets called when a tag needs to write it's attributes * @@ -959,16 +836,13 @@ nsresult CViewSourceHTML::WriteAttributes(PRInt32 attrCount) { theContext.mTokenNode.AddAttribute(theToken); //and add it to the node. CAttributeToken* theAttrToken=(CAttributeToken*)theToken; - nsString& theKey=theAttrToken->GetKey(); - theKey.StripChar(kCR); + const nsAReadableString& theKey=theAttrToken->GetKey(); - CToken theKeyToken(theKey); - result=WriteTag(mKey,&theKeyToken,0,PR_FALSE); - nsString& theValue=theToken->GetStringValueXXX(); - theValue.StripChar(kCR); + result=WriteTag(mKey,theKey,0,PR_FALSE); + const nsString& theValue=theAttrToken->GetValue(); if((0<theValue.Length()) || (theAttrToken->mHasEqualWithoutValue)){ - result=WriteTag(mValue,theToken,0,PR_FALSE); + result=WriteTag(mValue,theValue,0,PR_FALSE); } } } @@ -987,9 +861,9 @@ nsresult CViewSourceHTML::WriteAttributes(PRInt32 attrCount) { * @return result status */ #ifdef VIEW_SOURCE_HTML -nsresult CViewSourceHTML::WriteTag(PRInt32 aTagType,nsString & aText,PRInt32 attrCount,PRBool aNewlineRequired) { +nsresult CViewSourceHTML::WriteTag(PRInt32 aTagType,const nsAReadableString & aText,PRInt32 attrCount,PRBool aNewlineRequired) { #else -nsresult CViewSourceHTML::WriteTag(nsString &theXMLTagName,nsString & aText,PRInt32 attrCount,PRBool aNewlineRequired) { +nsresult CViewSourceHTML::WriteTag(nsString &theXMLTagName,nsAReadableString & aText,PRInt32 attrCount,PRBool aNewlineRequired) { #endif // VIEW_SOURCE_HTML static nsString theString; @@ -1014,14 +888,10 @@ nsresult CViewSourceHTML::WriteTag(nsString &theXMLTagName,nsString & aText,PRIn #ifdef VIEW_SOURCE_COLORING nsAutoString tag (NS_LITERAL_STRING("SPAN")); - CStartToken theTagToken(eHTMLTag_span); - if (syntaxHilight) - { - theTagToken.SetStringValue(tag); - } + CStartToken theTagToken(tag, eHTMLTag_span); #endif // VIEW_SOURCE_COLORING -#else // VIEW_SOURCE_HTML *UNDEFINED* - CToken theTagToken(theXMLTagName); +#else + CStartToken theTagToken(theXMLTagName); #endif // VIEW_SOURCE_HTML #ifdef VIEW_SOURCE_COLORING @@ -1032,8 +902,7 @@ nsresult CViewSourceHTML::WriteTag(nsString &theXMLTagName,nsString & aText,PRIn nsTokenAllocator* theAllocator=mTokenizer->GetTokenAllocator(); if(theAllocator) { CAttributeToken* theAttr=(CAttributeToken*)theAllocator->CreateTokenOfType(eToken_attribute,eHTMLTag_unknown,NS_ConvertToString(kElementStyles[aTagType])); - nsString& theKey=theAttr->GetKey(); - theKey=NS_ConvertToString("style"); + theAttr->SetKey(NS_LITERAL_STRING("style")); theContext.mStartNode.AddAttribute(theAttr); } #endif // VIEW_SOURCE_HTML @@ -1071,7 +940,6 @@ nsresult CViewSourceHTML::WriteTag(nsString &theXMLTagName,nsString & aText,PRIn { theContext.mStartNode.ReleaseAll(); CEndToken theEndToken(eHTMLTag_span); - theEndToken.SetStringValue(tag); theContext.mEndNode.Init(&theEndToken,mLineNumber); mSink->CloseContainer(theContext.mEndNode); //emit </starttag>... } @@ -1097,31 +965,6 @@ nsresult CViewSourceHTML::WriteTag(nsString &theXMLTagName,nsString & aText,PRIn return result; } -/** - * This method gets called when a tag needs to be sent out - * - * @update gess 6June2000 -- factored to use WriteTag(txt,txt...); - * @param - * @return result status - */ -#ifdef VIEW_SOURCE_HTML -nsresult CViewSourceHTML::WriteTag(PRInt32 aTagType,CToken* aToken,PRInt32 attrCount,PRBool aNewlineRequired) { -#else -nsresult CViewSourceHTML::WriteTag(nsString &theXMLTagName,CToken* aToken,PRInt32 attrCount,PRBool aNewlineRequired) { -#endif // VIEW_SOURCE_HTML - - nsString& theStr=aToken->GetStringValueXXX(); - theStr.StripChar(kCR); - -#ifdef VIEW_SOURCE_HTML - nsresult result=WriteTag(aTagType,theStr,attrCount,aNewlineRequired); -#else - nsresult result=WriteTag(theXMLTagName,theStr,attrCount,aNewlineRequired); -#endif // VIEW_SOURCE_HTML - - return result; -} - /** * This method gets called when a tag needs to be sent out but is known to be misplaced (error) * @@ -1130,9 +973,9 @@ nsresult CViewSourceHTML::WriteTag(nsString &theXMLTagName,CToken* aToken,PRInt3 * @return result status */ #ifdef VIEW_SOURCE_HTML -nsresult CViewSourceHTML::WriteTagWithError(PRInt32 aTagType,CToken* aToken,PRInt32 attrCount,PRBool aNewlineRequired) { +nsresult CViewSourceHTML::WriteTagWithError(PRInt32 aTagType,const nsAReadableString& aStr,PRInt32 attrCount,PRBool aNewlineRequired) { #else -nsresult CViewSourceHTML::WriteTagWithError(nsString &theXMLTagName,CToken* aToken,PRInt32 attrCount,PRBool aNewlineRequired) { +nsresult CViewSourceHTML::WriteTagWithError(nsString &theXMLTagName,const nsAReadableString& aStr,PRInt32 attrCount,PRBool aNewlineRequired) { #endif // VIEW_SOURCE_HTML STOP_TIMER(); @@ -1150,9 +993,9 @@ nsresult CViewSourceHTML::WriteTagWithError(nsString &theXMLTagName,CToken* aTok #ifdef VIEW_SOURCE_HTML //now write the tag from the source file... - result=WriteTag(aTagType,aToken,attrCount,aNewlineRequired); + result=WriteTag(aTagType,aStr,attrCount,aNewlineRequired); #else - result=WriteTag(theXMLTagName,aToken,attrCount,aNewlineRequired); + result=WriteTag(theXMLTagName,aStr,attrCount,aNewlineRequired); #endif // VIEW_SOURCE_HTML if(ePlainText!=mDocType) { @@ -1222,6 +1065,11 @@ NS_IMETHODIMP CViewSourceHTML::HandleToken(CToken* aToken,nsIParser* aParser) { { mTagCount++; + if (gHTMLElements[theChild].CanContainType(kCDATA)) { + mInCDATAContainer = PR_TRUE; + } + + const nsAReadableString& startValue = aToken->GetStringValue(); if(mShowErrors) { PRBool theChildIsValid=PR_TRUE; if(mValidator) { @@ -1231,15 +1079,15 @@ NS_IMETHODIMP CViewSourceHTML::HandleToken(CToken* aToken,nsIParser* aParser) { mTags.Append(PRUnichar(theChild)); } } - + if(theChildIsValid) - result=WriteTag(mStartTag,aToken,aToken->GetAttributeCount(),PR_TRUE); + result=WriteTag(mStartTag,startValue,aToken->GetAttributeCount(),PR_TRUE); else { AddContainmentError(theChild,theParent,mLineNumber); - result=WriteTagWithError(mStartTag,aToken,aToken->GetAttributeCount(),PR_TRUE); + result=WriteTagWithError(mStartTag,startValue,aToken->GetAttributeCount(),PR_TRUE); } } - else result=WriteTag(mStartTag,aToken,aToken->GetAttributeCount(),PR_TRUE); + else result=WriteTag(mStartTag,startValue,aToken->GetAttributeCount(),PR_TRUE); if((ePlainText!=mDocType) && mParser && (NS_OK==result)) { CObserverService* theService=mParser->GetObserverService(); @@ -1255,53 +1103,82 @@ NS_IMETHODIMP CViewSourceHTML::HandleToken(CToken* aToken,nsIParser* aParser) { break; case eToken_end: - if(theParent==theChild) { - mTags.Truncate(mTags.Length()-1); + { + if (gHTMLElements[theChild].CanContainType(kCDATA)) { + mInCDATAContainer = PR_FALSE; + } + + if(theParent==theChild) { + mTags.Truncate(mTags.Length()-1); + } + const nsAReadableString& endValue = aToken->GetStringValue(); + result=WriteTag(mEndTag,endValue,0,PR_TRUE); } - result=WriteTag(mEndTag,aToken,0,PR_TRUE); break; case eToken_cdatasection: { - nsString& theStr=aToken->GetStringValueXXX(); - theStr.InsertWithConversion("<!",0); - theStr.AppendWithConversion("]]>"); - result=WriteTag(mCDATATag,aToken,0,PR_TRUE); + nsAutoString theStr; + theStr.Assign(NS_LITERAL_STRING("<!")); + theStr.Append(aToken->GetStringValue()); + theStr.Append(NS_LITERAL_STRING("]]>")); + result=WriteTag(mCDATATag,theStr,0,PR_TRUE); } break; case eToken_comment: - result=WriteTag(mCommentTag,aToken,0,PR_TRUE); + { + const nsAReadableString& commentValue = aToken->GetStringValue(); + result=WriteTag(mCommentTag,commentValue,0,PR_TRUE); + } break; case eToken_doctypeDecl: { - result=WriteTag(mDocTypeTag,aToken,0,PR_TRUE); + const nsAReadableString& doctypeValue = aToken->GetStringValue(); + result=WriteTag(mDocTypeTag,doctypeValue,0,PR_TRUE); } break; case eToken_newline: - mLineNumber++; //now fall through... + { + const nsAReadableString& newlineValue = aToken->GetStringValue(); + mLineNumber++; + result=WriteTag(mText,newlineValue,0,PR_FALSE); + } + break; + case eToken_whitespace: - result=WriteTag(mText,aToken,0,PR_FALSE); + { + const nsAReadableString& wsValue = aToken->GetStringValue(); + result=WriteTag(mText,wsValue,0,PR_FALSE); + } break; case eToken_text: - - if(mShowErrors) { - if((0==mValidator) || mValidator->CanContain(theParent,eHTMLTag_text)) - result=WriteTag(mText,aToken,aToken->GetAttributeCount(),PR_TRUE); - else { - AddContainmentError(eHTMLTag_text,theParent,mLineNumber); - result=WriteTagWithError(mText,aToken,aToken->GetAttributeCount(),PR_FALSE); + { + if(mShowErrors) { + const nsAReadableString& str = aToken->GetStringValue(); + if((0==mValidator) || + mValidator->CanContain(theParent,eHTMLTag_text)) + result=WriteTag(mText,str,aToken->GetAttributeCount(),PR_TRUE); + else { + AddContainmentError(eHTMLTag_text,theParent,mLineNumber); + result=WriteTagWithError(mText,str,aToken->GetAttributeCount(),PR_FALSE); + } + } + else if (mInCDATAContainer) { + // Fix bug 40809 + nsAutoString theStr; + aToken->GetSource(theStr); + theStr.ReplaceSubstring(NS_ConvertASCIItoUCS2("\r\n"), NS_ConvertASCIItoUCS2("\n")); + theStr.ReplaceChar(kCR,kLF); + result=WriteTag(mText,theStr,aToken->GetAttributeCount(),PR_TRUE); + } + else { + const nsAReadableString& str = aToken->GetStringValue(); + result=WriteTag(mText,str,aToken->GetAttributeCount(),PR_TRUE); } - } - else { - // Fix bug 40809 - nsString& theStr=aToken->GetStringValueXXX(); - theStr.ReplaceSubstring(NS_ConvertASCIItoUCS2("\r\n"), NS_ConvertASCIItoUCS2("\n")); - theStr.ReplaceChar(kCR,kLF); - result=WriteTag(mText,theStr,aToken->GetAttributeCount(),PR_TRUE); } break; @@ -1309,20 +1186,19 @@ NS_IMETHODIMP CViewSourceHTML::HandleToken(CToken* aToken,nsIParser* aParser) { case eToken_entity: { nsAutoString theStr; - nsString& theEntity=aToken->GetStringValueXXX(); - if(!theEntity.EqualsWithConversion("XI",IGNORE_CASE)) { - PRUnichar theChar=theEntity.CharAt(0); + theStr.Assign(aToken->GetStringValue()); + if(!theStr.EqualsWithConversion("XI",IGNORE_CASE)) { + PRUnichar theChar=theStr.CharAt(0); if((nsCRT::IsAsciiDigit(theChar)) || ('X'==theChar) || ('x'==theChar)){ - theStr.AppendWithConversion("#"); + theStr.InsertWithConversion("#", 0); } - theStr.Append(theEntity); } result=WriteTag(mEntityTag,theStr,0,PR_FALSE); } break; case eToken_instruction: - result=WriteTag(mPITag,aToken,0,PR_TRUE); + result=WriteTag(mPITag,aToken->GetStringValue(),0,PR_TRUE); default: result=NS_OK; diff --git a/mozilla/htmlparser/src/nsViewSourceHTML.h b/mozilla/htmlparser/src/nsViewSourceHTML.h index 55dfb612775..9eb3421ba57 100644 --- a/mozilla/htmlparser/src/nsViewSourceHTML.h +++ b/mozilla/htmlparser/src/nsViewSourceHTML.h @@ -237,18 +237,13 @@ class CViewSourceHTML: public nsIDTD { virtual PRBool IsContainer(PRInt32 aTag) const; - static nsresult WriteText(const nsString& aTextString,nsIContentSink& aSink,PRBool aPreserveText,PRBool aPlainText); - - private: #ifdef VIEW_SOURCE_HTML - nsresult WriteTag(PRInt32 tagType,CToken* aTag,PRInt32 attrCount,PRBool aNewlineRequired); - nsresult WriteTag(PRInt32 tagType,nsString &aText,PRInt32 attrCount,PRBool aNewlineRequired); - nsresult WriteTagWithError(PRInt32 tagType,CToken* aToken,PRInt32 attrCount,PRBool aNewlineRequired); + nsresult WriteTag(PRInt32 tagType,const nsAReadableString &aText,PRInt32 attrCount,PRBool aNewlineRequired); + nsresult WriteTagWithError(PRInt32 tagType,const nsAReadableString& aToken,PRInt32 attrCount,PRBool aNewlineRequired); #else - nsresult WriteTag(nsString &anXMLName,CToken* aTag,PRInt32 attrCount,PRBool aNewlineRequired); - nsresult WriteTag(nsString &anXMLName,nsString &aText,PRInt32 attrCount,PRBool aNewlineRequired); - nsresult WriteTagWithError(nsString &theXMLTagName,CToken* aToken,PRInt32 attrCount,PRBool aNewlineRequired); + nsresult WriteTag(nsString &anXMLName,const nsAReadableString &aText,PRInt32 attrCount,PRBool aNewlineRequired); + nsresult WriteTagWithError(nsString &theXMLTagName,const nsAReadableString& aStr,PRInt32 attrCount,PRBool aNewlineRequired); #endif void AddContainmentError(eHTMLTags aChild,eHTMLTags aParent,PRInt32 aLineNumber); @@ -305,6 +300,7 @@ protected: nsString mErrors; PRBool mShowErrors; PRBool mHasOpenRoot; + PRBool mInCDATAContainer; }; extern NS_HTMLPARS nsresult NS_NewViewSourceHTML(nsIDTD** aInstancePtrResult); diff --git a/mozilla/htmlparser/src/nsWellFormedDTD.cpp b/mozilla/htmlparser/src/nsWellFormedDTD.cpp index bd0f9e6cbea..666c905f666 100644 --- a/mozilla/htmlparser/src/nsWellFormedDTD.cpp +++ b/mozilla/htmlparser/src/nsWellFormedDTD.cpp @@ -52,6 +52,7 @@ #include <ctype.h> // toupper() #include "nsString.h" +#include "nsReadableUtils.h" static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); static NS_DEFINE_IID(kIDTDIID, NS_IDTD_IID); @@ -249,7 +250,6 @@ NS_IMETHODIMP CWellFormedDTD::BuildModel(nsIParser* aParser,nsITokenizer* aToken if(aTokenizer) { nsHTMLTokenizer* oldTokenizer=mTokenizer; mTokenizer=(nsHTMLTokenizer*)aTokenizer; - nsTokenAllocator* theAllocator=aTokenizer->GetTokenAllocator(); while(NS_SUCCEEDED(result)){ if(mDTDState!=NS_ERROR_HTMLPARSER_STOPPARSING) { @@ -573,7 +573,9 @@ nsresult CWellFormedDTD::HandleCommentToken(CToken* aToken) { nsresult result=NS_OK; - mLineNumber += (aToken->GetStringValueXXX()).CountChar(kNewLine); + CCommentToken* theToken = (CCommentToken*)aToken; + mLineNumber += CountCharInReadable(theToken->GetStringValue(), + PRUnichar(kNewLine)); nsCParserNode theNode((CHTMLToken*)aToken,mLineNumber,mTokenizer->GetTokenAllocator()); result=(mSink)? mSink->AddComment(theNode):NS_OK; @@ -689,8 +691,6 @@ nsresult CWellFormedDTD::HandleErrorToken(CToken* aToken) { nsresult result=NS_OK; if(mTokenizer) { - nsTokenAllocator* theAllocator=mTokenizer->GetTokenAllocator(); - // Cycle through the remaining tokens in the token stream and handle them // These tokens were added so that content objects for the error message // are generated by the content sink diff --git a/mozilla/htmlparser/src/nsXIFDTD.cpp b/mozilla/htmlparser/src/nsXIFDTD.cpp index eb839a303af..539c81f95d8 100644 --- a/mozilla/htmlparser/src/nsXIFDTD.cpp +++ b/mozilla/htmlparser/src/nsXIFDTD.cpp @@ -164,17 +164,19 @@ public: * @return valid id, or user_defined. */ static -eXIFTags DetermineXIFTagType(const nsString& aString) +eXIFTags DetermineXIFTagType(const nsAReadableString& aString) { PRInt32 result=-1; PRInt32 cnt=sizeof(gXIFTagTable)/sizeof(nsXIFTagEntry); PRInt32 low=0; PRInt32 high=cnt-1; PRInt32 middle=kNotFound; - + nsCAutoString tag; + tag.AssignWithConversion(aString); + while(low<=high){ middle=(PRInt32)(low+high)/2; - result=aString.CompareWithConversion(gXIFTagTable[middle].mName, PR_TRUE); + result=tag.CompareWithConversion((const char*)gXIFTagTable[middle].mName); if (result==0) return gXIFTagTable[middle].fTagID; if (result<0) @@ -460,7 +462,7 @@ nsresult nsXIFDTD::WillHandleToken(CToken* aToken,PRInt32& aType) { eXIFTags theNewType = eXIFTag_userdefined; if((eToken_start==aType) || (eToken_end==aType)) { - nsString& name = aToken->GetStringValueXXX(); + const nsAReadableString& name = aToken->GetStringValue(); theNewType=DetermineXIFTagType(name); if (theNewType != eXIFTag_userdefined) { aToken->SetTypeID(theNewType); @@ -714,7 +716,8 @@ nsresult nsXIFDTD::HandleContainer(nsIParserNode& aNode) { theTagID=nsHTMLTags::LookupTag(theTagName); - theNode->mToken->Reinitialize(theTagID,theTagName); + CToken* theToken = mTokenAllocator->CreateTokenOfType(eToken_start,theTagID, theTagName); + theNode->SetToken(theToken); theNode->Init(theNode->mToken,0,mTokenAllocator); } mXIFContext->Push(&aNode); @@ -810,8 +813,9 @@ nsresult nsXIFDTD::HandleCommentToken(CToken* aToken, nsIParserNode& aNode) { nsAutoString fragment; PRBool done=PR_FALSE; PRBool inContent=PR_FALSE; - nsString& comment=aToken->GetStringValueXXX(); - comment.AssignWithConversion("<!--"); // overwrite comment with "<!--" + CCommentToken* theToken = (CCommentToken*)aToken; + nsAutoString comment; + comment.AssignWithConversion("<!--"); while (!done && NS_SUCCEEDED(result)) { token=mTokenizer->PopToken(); @@ -819,7 +823,7 @@ nsresult nsXIFDTD::HandleCommentToken(CToken* aToken, nsIParserNode& aNode) { if(!token) return result; type=(eHTMLTokenTypes)token->GetTokenType(); - fragment.Assign(token->GetStringValueXXX()); + fragment.Assign(token->GetStringValue()); if(fragment.EqualsWithConversion("content")) { if(type==eToken_start) inContent=PR_TRUE; @@ -827,6 +831,7 @@ nsresult nsXIFDTD::HandleCommentToken(CToken* aToken, nsIParserNode& aNode) { } else if(fragment.EqualsWithConversion("comment")) { comment.AppendWithConversion("-->"); + theToken->SetStringValue(comment); result=(mSink)? mSink->AddComment(aNode):NS_OK; done=PR_TRUE; } @@ -862,8 +867,7 @@ nsresult nsXIFDTD::HandleAttributeToken(CToken* aToken,nsIParserNode& aNode) { if(hasValue) { CToken* attribute = mTokenAllocator->CreateTokenOfType(eToken_attribute,eHTMLTag_unknown,theValue); - nsString& key=((CAttributeToken*)attribute)->GetKey(); - key=theKey; // set the new key on the attribute.. + ((CAttributeToken*)attribute)->SetKey(theKey); // set the new key on the attribute.. thePeekNode->AddAttribute(attribute); } } @@ -985,7 +989,7 @@ PRBool nsXIFDTD::GetAttribute(const nsIParserNode& aNode, const nsString& aKey, PRInt32 count = aNode.GetAttributeCount(); for (i = 0; i < count; i++) { - const nsString& key = aNode.GetKeyAt(i); + const nsAReadableString& key = aNode.GetKeyAt(i); if (key.Equals(aKey)) { const nsString& value = aNode.GetValueAt(i); @@ -1014,7 +1018,7 @@ PRBool nsXIFDTD::GetAttributePair(nsIParserNode& aNode, nsString& aKey, nsString for (i = 0; i < count; i++) { - const nsString& k = aNode.GetKeyAt(i); + const nsAReadableString& k = aNode.GetKeyAt(i); const nsString& v = aNode.GetValueAt(i); nsAutoString key; key.Assign(k); @@ -1094,8 +1098,8 @@ nsresult nsXIFDTD::AddLeaf(const nsIParserNode& aNode) break; case eXIFTag_text: if(theToken) { - nsString& temp =theToken->GetStringValueXXX(); - if (temp.EqualsWithConversion("<xml version=\"1.0\"?>")) handled=PR_TRUE; + const nsAReadableString& temp =theToken->GetStringValue(); + if (temp.Equals(NS_LITERAL_STRING("<xml version=\"1.0\"?>"))) handled=PR_TRUE; } break; default: @@ -1332,18 +1336,19 @@ nsresult nsXIFDTD::ProcessEntityTag(const nsIParserNode& aNode) // That's totally worng. if (GetAttribute(aNode,NS_ConvertToString("value"),value)) { value.AppendWithConversion(';'); - CToken* entity=((nsCParserNode&)aNode).mToken; + CToken* entity = mTokenAllocator->CreateTokenOfType(eToken_entity, eHTMLTag_entity, value); if(entity) { - entity->Reinitialize(eHTMLTag_entity,value); nsCParserNode* thePeekNode=(nsCParserNode*)mXIFContext->PeekNode(); if(thePeekNode) { eHTMLTags theTag=(eHTMLTags)thePeekNode->mToken->GetTypeID(); if(theTag==eHTMLTag_script || theTag==eHTMLTag_style) { nsAutoString scratch; ((CEntityToken*)entity)->TranslateToUnicodeStr(scratch); // Ex. > would become '<' - entity->Reinitialize(eHTMLTag_text,scratch); // Covert type to text and set the translated value. + IF_FREE(entity); + entity = mTokenAllocator->CreateTokenOfType(eToken_text, eHTMLTag_text, scratch); } } + // XXX Casting from an interface down to a class? For shame! ((nsCParserNode&)aNode).Init(entity,mLineNumber,mTokenAllocator); } result=mSink->AddLeaf(aNode); @@ -1364,10 +1369,10 @@ nsresult nsXIFDTD::BeginCSSStyleSheet(const nsIParserNode& aNode) PRInt32 error; nsAutoString value; - CToken* theToken=((nsCParserNode&)aNode).mToken; - + CToken* theToken=mTokenAllocator->CreateTokenOfType(eToken_start, eHTMLTag_style, NS_ConvertASCIItoUCS2("style")); + if(theToken) { - theToken->Reinitialize(eHTMLTag_style,NS_ConvertASCIItoUCS2("style")); + ((nsCParserNode&)aNode).SetToken(theToken); mXIFContext->Push(&aNode); } diff --git a/mozilla/htmlparser/src/nsXMLTokenizer.cpp b/mozilla/htmlparser/src/nsXMLTokenizer.cpp index 49a151e320c..c314c6d270b 100644 --- a/mozilla/htmlparser/src/nsXMLTokenizer.cpp +++ b/mozilla/htmlparser/src/nsXMLTokenizer.cpp @@ -160,26 +160,19 @@ nsTokenAllocator* nsXMLTokenizer::GetTokenAllocator(void) { static nsresult ConsumeConditional(nsScanner& aScanner,const nsString& aMatchString,PRBool& aMatch) { nsresult result=NS_OK; - PRUnichar matchChar; + nsAutoString str; + PRUint32 len = aMatchString.Length(); - PRInt32 i, count = aMatchString.Length(); - for (i=0; i < count; i++) { - result = aScanner.GetChar(matchChar); - if ((NS_OK != result) || (aMatchString.CharAt(i) != matchChar)) { - break; - } + result = aScanner.Peek(str, len); + if ((NS_OK == result) && str.Equals(aMatchString)) { + aMatch = PR_TRUE; + nsReadingIterator<PRUnichar> curPos; + aScanner.CurrentPosition(curPos); + curPos.advance(len); + aScanner.SetPosition(curPos); } - - if (NS_OK == result) { - if (i != count) { - for (; i >= 0; i--) { - aScanner.PutBack(aMatchString.CharAt(i)); - } - aMatch = PR_FALSE; - } - else { - aMatch = PR_TRUE; - } + else { + aMatch = PR_FALSE; } return result; diff --git a/mozilla/htmlparser/tests/logparse/makefile.win b/mozilla/htmlparser/tests/logparse/makefile.win index 020ba2b7c8a..35c79551e38 100644 --- a/mozilla/htmlparser/tests/logparse/makefile.win +++ b/mozilla/htmlparser/tests/logparse/makefile.win @@ -1,4 +1,4 @@ -!#!nmake +#!nmake # # The contents of this file are subject to the Netscape Public # License Version 1.1 (the "License"); you may not use this file @@ -23,10 +23,10 @@ DEPTH=..\..\.. MAKE_OBJ_TYPE = EXE -PROGRAM = .\$(OBJDIR)\logparse.exe +PROGRAM = .\$(OBJDIR)\TestParser.exe OBJS = \ - .\$(OBJDIR)\logparse.obj \ + .\$(OBJDIR)\TestParser.obj \ $(NULL) LINCS= \ @@ -52,4 +52,4 @@ install:: $(PROGRAM) $(MAKE_INSTALL) $(PROGRAM) $(DIST)\bin clobber:: - rm -f $(DIST)\bin\logparse.exe + rm -f $(DIST)\bin\TestParser.exe diff --git a/mozilla/htmlparser/tests/outsinks/Convert.cpp b/mozilla/htmlparser/tests/outsinks/Convert.cpp index 869e371f913..288a9e968e9 100644 --- a/mozilla/htmlparser/tests/outsinks/Convert.cpp +++ b/mozilla/htmlparser/tests/outsinks/Convert.cpp @@ -88,7 +88,9 @@ Compare(nsString& str, nsString& aFileName) return 0; else { - char* cstr = str.ToNewUTF8String(); + nsAutoString left; + str.Left(left, different); + char* cstr = left.ToNewUTF8String(); printf("Comparison failed at char %d:\n-----\n%s\n-----\n", different, cstr); Recycle(cstr); diff --git a/mozilla/parser/htmlparser/robot/nsRobotSink.cpp b/mozilla/parser/htmlparser/robot/nsRobotSink.cpp index 0ebf4280ef1..1b0d6ebd512 100644 --- a/mozilla/parser/htmlparser/robot/nsRobotSink.cpp +++ b/mozilla/parser/htmlparser/robot/nsRobotSink.cpp @@ -226,9 +226,8 @@ NS_IMETHODIMP RobotSink::OpenContainer(const nsIParserNode& aNode) PRInt32 ac = aNode.GetAttributeCount(); for (PRInt32 i = 0; i < ac; i++) { // Get upper-cased key - const nsString& key = aNode.GetKeyAt(i); - k.Truncate(); - k.Append(key); + const nsAReadableString& key = aNode.GetKeyAt(i); + k.Assign(key); k.ToLowerCase(); if (k.EqualsWithConversion("href")) { // Get value and remove mandatory quotes diff --git a/mozilla/parser/htmlparser/src/CNavDTD.cpp b/mozilla/parser/htmlparser/src/CNavDTD.cpp index 101fce2d5a6..eb034927890 100644 --- a/mozilla/parser/htmlparser/src/CNavDTD.cpp +++ b/mozilla/parser/htmlparser/src/CNavDTD.cpp @@ -52,6 +52,7 @@ #include "nsLinebreakConverter.h" #include "nsIFormProcessor.h" #include "nsVoidArray.h" +#include "nsReadableUtils.h" #include "prmem.h" @@ -164,10 +165,6 @@ CNavDTD::CNavDTD() : nsIDTD(), mHeadContext=new nsDTDContext(); mBodyContext=new nsDTDContext(); - if(!gHTMLElements) { - InitializeElementTable(); - } - mNodeRecycler=0; #ifdef RICKG_DEBUG @@ -178,13 +175,6 @@ CNavDTD::CNavDTD() : nsIDTD(), #endif } -void CNavDTD::ReleaseTable(void) { - if(gHTMLElements) { - delete [] gHTMLElements; //fixed bug 49564 - gHTMLElements=0; - } -} - /** * This method recycles the nodes on a nodestack. * NOTE: Unlike recycleNode(), we force the usecount @@ -347,7 +337,7 @@ eAutoDetectResult CNavDTD::CanParse(CParserContext& aParserContext,nsString& aBu if(BufferContainsHTML(aBuffer,theBufHasXML)){ result = eValidDetect ; if(0==aParserContext.mMimeType.Length()) { - aParserContext.SetMimeType(NS_ConvertToString(kHTMLTextContentType)); + aParserContext.SetMimeType(NS_ConvertASCIItoUCS2(kHTMLTextContentType, sizeof(kHTMLTextContentType))); if(!theBufHasXML) { switch(aParserContext.mDTDMode) { case eDTDMode_strict: @@ -455,13 +445,13 @@ nsresult CNavDTD::BuildModel(nsIParser* aParser,nsITokenizer* aTokenizer,nsIToke CStartToken* theToken=nsnull; if(ePlainText==mDocType) { //we do this little trick for text files, in both normal and viewsource mode... - theToken=(CStartToken*)mTokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_pre); + theToken=NS_STATIC_CAST(CStartToken*,mTokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_pre)); if(theToken) { mTokenizer->PushTokenFront(theToken); } } //if the content model is empty, then begin by opening <html>... - theToken=(CStartToken*)mTokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_html,NS_ConvertToString("html")); + theToken=NS_STATIC_CAST(CStartToken*,mTokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_html,NS_ConvertToString("html"))); if(theToken) { mTokenizer->PushTokenFront(theToken); //this token should get pushed on the context stack. } @@ -514,7 +504,7 @@ nsresult CNavDTD::DidBuildModel(nsresult anErrorCode,PRBool aNotifySink,nsIParse mSkipTarget=eHTMLTag_unknown; //clear this in case we were searching earlier. - CStartToken *theToken=(CStartToken*)mTokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_body,NS_ConvertToString("body")); + CStartToken *theToken=NS_STATIC_CAST(CStartToken*,mTokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_body,NS_ConvertToString("body"))); mTokenizer->PushTokenFront(theToken); //this token should get pushed on the context stack, don't recycle it result=BuildModel(aParser,mTokenizer,0,aSink); } @@ -524,7 +514,7 @@ nsresult CNavDTD::DidBuildModel(nsresult anErrorCode,PRBool aNotifySink,nsIParse if((NS_OK==anErrorCode) && (mBodyContext->GetCount()>0)) { if(mSkipTarget) { CHTMLToken* theEndToken=nsnull; - theEndToken=(CHTMLToken*)mTokenAllocator->CreateTokenOfType(eToken_end,mSkipTarget); + theEndToken=NS_STATIC_CAST(CHTMLToken*,mTokenAllocator->CreateTokenOfType(eToken_end,mSkipTarget)); if(theEndToken) { result=HandleToken(theEndToken,mParser); } @@ -629,7 +619,7 @@ nsresult CNavDTD::HandleToken(CToken* aToken,nsIParser* aParser){ nsresult result=NS_OK; if(aToken) { - CHTMLToken* theToken= (CHTMLToken*)(aToken); + CHTMLToken* theToken= NS_STATIC_CAST(CHTMLToken*, aToken); eHTMLTokenTypes theType=eHTMLTokenTypes(theToken->GetTokenType()); eHTMLTags theTag=(eHTMLTags)theToken->GetTypeID(); PRBool execSkipContent=PR_FALSE; @@ -723,7 +713,7 @@ nsresult CNavDTD::HandleToken(CToken* aToken,nsIParser* aParser){ //However, in quirks mode, a few tags request, ambiguosly, for a BODY. - Bugs 18928, 24204.- mMisplacedContent.Push(aToken); if(mDTDMode==eDTDMode_quirks && (gHTMLElements[theTag].HasSpecialProperty(kRequiresBody))) { - CToken* theBodyToken=(CToken*)mTokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_body,NS_ConvertToString("body")); + CToken* theBodyToken=NS_STATIC_CAST(CToken*,mTokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_body,NS_ConvertToString("body"))); result=HandleToken(theBodyToken,aParser); } return result; @@ -856,9 +846,10 @@ nsresult CNavDTD::DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag){ MOZ_TIMER_DEBUGLOG(("Stop: Parse Time: CNavDTD::DidHandleStartTag(), this=%p\n", this)); const nsString& theString=aNode.GetSkippedContent(); if(0<theString.Length()) { - CTextToken *theToken=(CTextToken*)mTokenAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text,theString); + CTextToken *theToken=NS_STATIC_CAST(CTextToken*,mTokenAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text,theString)); nsCParserNode theNode(theToken,0); - result=mSink->AddLeaf(theNode); //when the node get's destructed, so does the new token + result=mSink->AddLeaf(theNode); + IF_FREE(theToken); } MOZ_TIMER_DEBUGLOG(("Start: Parse Time: CNavDTD::DidHandleStartTag(), this=%p\n", this)); START_TIMER() @@ -892,7 +883,7 @@ nsresult CNavDTD::DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag){ if(theCount) { PRInt32 theIndex=0; for(theIndex=0;theIndex<theCount;theIndex++){ - const nsString& theKey=aNode.GetKeyAt(theIndex); + nsAutoString theKey(aNode.GetKeyAt(theIndex)); if(theKey.EqualsWithConversion("ENTITY",PR_TRUE)) { const nsString& theName=aNode.GetValueAt(theIndex); theNamePtr=&theName; @@ -1234,9 +1225,9 @@ nsresult CNavDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsCParserNode //(during editing) to display a special icon for unknown tags. if(eHTMLTag_userdefined==aTag) { - CAttributeToken* theToken= (CAttributeToken*)mTokenAllocator->CreateTokenOfType(eToken_attribute,aTag); + CAttributeToken* theToken= NS_STATIC_CAST(CAttributeToken*,mTokenAllocator->CreateTokenOfType(eToken_attribute,aTag)); if(theToken) { - theToken->mTextKey.AssignWithConversion("_moz-userdefined"); + theToken->SetKey(NS_LITERAL_STRING("_moz-userdefined")); aNode.AddAttribute(theToken); } } @@ -1266,7 +1257,7 @@ nsresult CNavDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsCParserNode CObserverService* theService=mParser->GetObserverService(); if(theService) { const nsISupportsParserBundle* bundle=mParser->GetParserBundle(); - result=theService->Notify(aTag,aNode,(void*)bundle, NS_ConvertToString(kHTMLTextContentType), mParser); + result=theService->Notify(aTag,aNode,(void*)bundle, mMimeType, mParser); } } @@ -1283,11 +1274,11 @@ nsresult CNavDTD::WillHandleStartTag(CToken* aToken,eHTMLTags aTag,nsCParserNode PRInt32 theCount=aNode.GetAttributeCount(); if(1<theCount){ - const nsString& theKey=aNode.GetKeyAt(0); + nsAutoString theKey(aNode.GetKeyAt(0)); if(theKey.Equals("NAME",IGNORE_CASE)) { const nsString& theValue1=aNode.GetValueAt(0); if(theValue1.Equals("\"CRC\"",IGNORE_CASE)) { - const nsString& theKey2=aNode.GetKeyAt(1); + nsAutoString theKey2(aNode.GetKeyAt(1)); if(theKey2.Equals("CONTENT",IGNORE_CASE)) { const nsString& theValue2=aNode.GetValueAt(1); PRInt32 err=0; @@ -1484,8 +1475,7 @@ nsresult CNavDTD::HandleKeyGen(nsIParserNode* aNode) { // Placing the attribute token on the tokenizer to get picked up by the SELECT. theToken=mTokenAllocator->CreateTokenOfType(eToken_attribute,eHTMLTag_unknown,theAttribute); - nsString& theKey=((CAttributeToken*)theToken)->GetKey(); - theKey.AssignWithConversion("_moz-type"); + ((CAttributeToken*)theToken)->SetKey(NS_LITERAL_STRING("_moz-type")); mTokenizer->PushTokenFront(theToken); // Pop out NAME and CHALLENGE attributes ( from the keygen NODE ) @@ -1837,7 +1827,7 @@ nsresult CNavDTD::HandleEndToken(CToken* aToken) { //to use </BR>, even though that isn't a legitimate tag. if(eDTDMode_quirks==mDTDMode) { // Use recycler and pass the token thro' HandleToken() to fix bugs like 32782. - CHTMLToken* theToken = (CHTMLToken*)mTokenAllocator->CreateTokenOfType(eToken_start,theChildTag); + CHTMLToken* theToken = NS_STATIC_CAST(CHTMLToken*,mTokenAllocator->CreateTokenOfType(eToken_start,theChildTag)); result=HandleToken(theToken,mParser); } } @@ -1888,7 +1878,7 @@ nsresult CNavDTD::HandleEndToken(CToken* aToken) { if(!CanOmit(theParentTag,theChildTag,theParentContains)) { IF_HOLD(aToken); mTokenizer->PushTokenFront(aToken); //put this end token back... - CHTMLToken* theToken = (CHTMLToken*)mTokenAllocator->CreateTokenOfType(eToken_start,theChildTag); + CHTMLToken* theToken = NS_STATIC_CAST(CHTMLToken*,mTokenAllocator->CreateTokenOfType(eToken_start,theChildTag)); mTokenizer->PushTokenFront(theToken); //put this new token onto stack... } } @@ -2025,7 +2015,7 @@ nsresult CNavDTD::HandleEntityToken(CToken* aToken) { nsresult result=NS_OK; - nsString& theStr=aToken->GetStringValueXXX(); + nsAutoString theStr(aToken->GetStringValue()); PRUnichar theChar=theStr.CharAt(0); if((kHashsign!=theChar) && (-1==nsHTMLEntities::EntityToUnicode(theStr))){ @@ -2033,16 +2023,15 @@ nsresult CNavDTD::HandleEntityToken(CToken* aToken) { CNamedEntity *theEntity=mBodyContext->GetEntity(theStr); CToken *theToken=0; if(theEntity) { - theToken=(CTextToken*)mTokenAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text,theEntity->mValue); + theToken=NS_STATIC_CAST(CTextToken*,mTokenAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text,theEntity->mValue)); } else { //if you're here we have a bogus entity. //convert it into a text token. - theToken=(CTextToken*)mTokenAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text,NS_ConvertToString("&")); - if(theToken) { - nsString &theTokenStr=theToken->GetStringValueXXX(); - theTokenStr.Append(theStr); //should append the entity name; fix bug 51161. - } + nsAutoString entityName; + entityName.AssignWithConversion("&"); + entityName.Append(theStr); //should append the entity name; fix bug 51161. + theToken = mTokenAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text,entityName); } return HandleToken(theToken,mParser); //theToken should get recycled automagically... } @@ -2084,8 +2073,9 @@ nsresult CNavDTD::HandleCommentToken(CToken* aToken) { nsresult result=NS_OK; - nsString& theComment=aToken->GetStringValueXXX(); - mLineNumber += (theComment).CountChar(kNewLine); + CCommentToken* theToken = NS_STATIC_CAST(CCommentToken*,aToken); + const nsAReadableString& theComment = theToken->GetStringValue(); + mLineNumber += CountCharInReadable(theComment, PRUnichar(kNewLine)); nsCParserNode* theNode=mNodeRecycler->CreateNode(); if(theNode) { @@ -2203,8 +2193,9 @@ nsresult CNavDTD::HandleDocTypeDeclToken(CToken* aToken){ WriteTokenToLog(aToken); #endif - nsString& docTypeStr=aToken->GetStringValueXXX(); - mLineNumber += (docTypeStr).CountChar(kNewLine); + CDoctypeDeclToken* theToken = NS_STATIC_CAST(CDoctypeDeclToken*,aToken); + nsAutoString docTypeStr(theToken->GetStringValue()); + mLineNumber += docTypeStr.CountChar(kNewLine); PRInt32 len=docTypeStr.Length(); PRInt32 pos=docTypeStr.RFindChar(kGreaterThan); @@ -2212,6 +2203,7 @@ nsresult CNavDTD::HandleDocTypeDeclToken(CToken* aToken){ docTypeStr.Cut(pos,len-pos);// First remove '>' from the end. } docTypeStr.Cut(0,2); // Now remove "<!" from the begining + theToken->SetStringValue(docTypeStr); nsCParserNode* theNode=mNodeRecycler->CreateNode(); if(theNode) { @@ -2265,7 +2257,7 @@ nsresult CNavDTD::CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt32 eHTMLTags theSkipTarget=gHTMLElements[aTag].mSkipTarget; for(attr=0;attr<aCount;attr++){ if((eHTMLTag_unknown!=theSkipTarget) && mSkippedContent.GetSize()) - theToken=(CToken*)mSkippedContent.PopFront(); + theToken=NS_STATIC_CAST(CToken*,mSkippedContent.PopFront()); else theToken=mTokenizer->PopToken(); if(theToken) { eHTMLTokenTypes theType=eHTMLTokenTypes(theToken->GetTokenType()); diff --git a/mozilla/parser/htmlparser/src/CNavDTD.h b/mozilla/parser/htmlparser/src/CNavDTD.h index 0e8a8d069ca..e9cfd65f7c6 100644 --- a/mozilla/parser/htmlparser/src/CNavDTD.h +++ b/mozilla/parser/htmlparser/src/CNavDTD.h @@ -481,7 +481,6 @@ CLASS_EXPORT_HTMLPARS CNavDTD : public nsIDTD { nsresult DoFragment(PRBool aFlag); - static void ReleaseTable(void); protected: diff --git a/mozilla/parser/htmlparser/src/COtherDTD.cpp b/mozilla/parser/htmlparser/src/COtherDTD.cpp index 8a5bd5cf7ef..9b2f7bcd696 100644 --- a/mozilla/parser/htmlparser/src/COtherDTD.cpp +++ b/mozilla/parser/htmlparser/src/COtherDTD.cpp @@ -174,13 +174,6 @@ COtherDTD::COtherDTD() : nsIDTD(), mSharedNodes(0) { #endif } -void COtherDTD::ReleaseTable(void) { - if(gElementTable) { - delete gElementTable; - gElementTable=0; - } -} - /** * This method creates a new parser node. It tries to get one from * the recycle list before allocating a new one. @@ -647,7 +640,7 @@ nsresult COtherDTD::DidHandleStartTag(nsCParserNode& aNode,eHTMLTags aChildTag){ if(theCount) { PRInt32 theIndex=0; for(theIndex=0;theIndex<theCount;theIndex++){ - const nsString& theKey=aNode.GetKeyAt(theIndex); + nsAutoString theKey(aNode.GetKeyAt(theIndex)); if(theKey.EqualsWithConversion("ENTITY",PR_TRUE)) { const nsString& theName=aNode.GetValueAt(theIndex); theNamePtr=&theName; @@ -902,7 +895,8 @@ nsresult COtherDTD::CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt3 nsresult COtherDTD::HandleEntityToken(CToken* aToken) { nsresult result=NS_OK; - nsString& theStr=aToken->GetStringValueXXX(); + nsAutoString theStr; + aToken->GetSource(theStr); PRUnichar theChar=theStr.CharAt(0); CToken *theToken=0; @@ -916,8 +910,10 @@ nsresult COtherDTD::HandleEntityToken(CToken* aToken) { else { //if you're here we have a bogus entity. //convert it into a text token. - theToken=(CTextToken*)mTokenAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text,NS_ConvertToString("&")); - + nsAutoString entityName; + entityName.AssignWithConversion("&"); + entityName.Append(theStr); //should append the entity name; fix bug 51161. + theToken=(CTextToken*)mTokenAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text,entityName); } result=HandleStartToken(theToken); } diff --git a/mozilla/parser/htmlparser/src/COtherDTD.h b/mozilla/parser/htmlparser/src/COtherDTD.h index 6297bdd6380..d2fd78f245e 100644 --- a/mozilla/parser/htmlparser/src/COtherDTD.h +++ b/mozilla/parser/htmlparser/src/COtherDTD.h @@ -311,8 +311,6 @@ CLASS_EXPORT_HTMLPARS COtherDTD : public nsIDTD { //by the parser to manage its context-stack. //************************************************* - static void ReleaseTable(void); - protected: nsresult CollectAttributes(nsCParserNode& aNode,eHTMLTags aTag,PRInt32 aCount); @@ -356,6 +354,7 @@ protected: extern NS_HTMLPARS nsresult NS_NewOtherHTMLDTD(nsIDTD** aInstancePtrResult); + CLASS_EXPORT_HTMLPARS CTransitionalDTD : public COtherDTD { public: diff --git a/mozilla/parser/htmlparser/src/COtherElements.h b/mozilla/parser/htmlparser/src/COtherElements.h index 8f542b343a7..6f261ba8817 100644 --- a/mozilla/parser/htmlparser/src/COtherElements.h +++ b/mozilla/parser/htmlparser/src/COtherElements.h @@ -1715,7 +1715,7 @@ public: nsCParserNode *theNode=(nsCParserNode*)aNode; nsresult result=NS_OK; if(theNode) { - nsString theStr=theNode->mToken->GetStringValueXXX(); + nsAutoString theStr(theNode->mToken->GetStringValue()); PRInt32 theLen=theStr.Length(); //PRInt32 thePos=theStr.RFindChar(kGreaterThan); diff --git a/mozilla/parser/htmlparser/src/Makefile.in b/mozilla/parser/htmlparser/src/Makefile.in index 97c9856e15c..933d6d5766f 100644 --- a/mozilla/parser/htmlparser/src/Makefile.in +++ b/mozilla/parser/htmlparser/src/Makefile.in @@ -60,7 +60,6 @@ CPPSRCS = \ nsElementTable.cpp \ CNavDTD.cpp \ COtherDTD.cpp \ - CRtfDTD.cpp \ nsHTMLEntities.cpp \ nsHTMLNullSink.cpp \ nsHTMLTags.cpp \ @@ -78,7 +77,6 @@ CPPSRCS = \ nsValidDTD.cpp \ nsWellFormedDTD.cpp \ nsViewSourceHTML.cpp \ - nsXIFDTD.cpp \ nsExpatDTD.cpp \ $(NULL) @@ -117,8 +115,6 @@ EXPORTS = \ COtherDTD.h \ nsWellFormedDTD.h \ nsValidDTD.h \ - CRtfDTD.h \ - nsXIFDTD.h \ nsParserCIID.h \ nsExpatDTD.h \ nsParserError.h \ diff --git a/mozilla/parser/htmlparser/src/makefile.win b/mozilla/parser/htmlparser/src/makefile.win index fdedcd06545..1546be84bfa 100644 --- a/mozilla/parser/htmlparser/src/makefile.win +++ b/mozilla/parser/htmlparser/src/makefile.win @@ -37,7 +37,6 @@ CPPSRCS= \ nsElementTable.cpp \ CNavDTD.cpp \ COtherDTD.cpp \ - CRtfDTD.cpp \ nsDTDDebug.cpp \ nsHTMLEntities.cpp \ nsHTMLNullSink.cpp \ @@ -55,11 +54,9 @@ CPPSRCS= \ nsValidDTD.cpp \ nsWellFormedDTD.cpp \ nsViewSourceHTML.cpp \ - nsXIFDTD.cpp \ nsExpatDTD.cpp \ prstrm.cpp \ nsParserModule.cpp \ - nsXIFDTD.cpp \ $(NULL) CPP_OBJS= \ @@ -70,7 +67,6 @@ CPP_OBJS= \ .\$(OBJDIR)\nsElementTable.obj \ .\$(OBJDIR)\CNavDTD.obj \ .\$(OBJDIR)\COtherDTD.obj \ - .\$(OBJDIR)\CRtfDTD.obj \ .\$(OBJDIR)\nsDTDDebug.obj \ .\$(OBJDIR)\nsHTMLEntities.obj \ .\$(OBJDIR)\nsHTMLNullSink.obj \ @@ -88,11 +84,9 @@ CPP_OBJS= \ .\$(OBJDIR)\nsValidDTD.obj \ .\$(OBJDIR)\nsWellFormedDTD.obj \ .\$(OBJDIR)\nsViewSourceHTML.obj \ - .\$(OBJDIR)\nsXIFDTD.obj \ .\$(OBJDIR)\nsExpatDTD.obj \ .\$(OBJDIR)\prstrm.obj \ .\$(OBJDIR)\nsParserModule.obj \ - .\$(OBJDIR)\nsXIFDTD.obj \ $(NULL) EXPORTS= \ @@ -119,10 +113,8 @@ EXPORTS= \ CNavDTD.h \ nsWellFormedDTD.h \ nsValidDTD.h \ - CRTFDTD.h \ COtherDTD.h \ nsIDTD.h \ - nsXIFDTD.h \ nsExpatDTD.h \ nsParserCIID.h \ nsParserError.h \ diff --git a/mozilla/parser/htmlparser/src/nsDTDUtils.cpp b/mozilla/parser/htmlparser/src/nsDTDUtils.cpp index 65d73a01952..bba36f66711 100644 --- a/mozilla/parser/htmlparser/src/nsDTDUtils.cpp +++ b/mozilla/parser/htmlparser/src/nsDTDUtils.cpp @@ -802,7 +802,7 @@ PRInt32 nsDTDContext::IncrementCounter(eHTMLTags aTag,nsCParserNode& aNode,nsStr CAbacus::eNumFormat theNumFormat=CAbacus::eDecimal; for(theIndex=0;theIndex<theCount;theIndex++){ - const nsString& theKey=aNode.GetKeyAt(theIndex); + nsAutoString theKey(aNode.GetKeyAt(theIndex)); const nsString& theValue=aNode.GetValueAt(theIndex); if(theKey.EqualsWithConversion("name",PR_TRUE)){ @@ -1225,7 +1225,7 @@ public: * * @return ptr to new token (or 0). */ -CToken* nsTokenAllocator::CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag, const nsString& aString) { +CToken* nsTokenAllocator::CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag, const nsAReadableString& aString) { CToken* result=0; @@ -1233,22 +1233,22 @@ CToken* nsTokenAllocator::CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag mTotals[aType-1]++; #endif switch(aType){ - case eToken_start: result=new(mArenaPool) CStartToken(aTag); break; - case eToken_end: result=new(mArenaPool) CEndToken(aTag); break; - case eToken_comment: result=new(mArenaPool) CCommentToken(); break; + case eToken_start: result=new(mArenaPool) CStartToken(aString, aTag); break; + case eToken_end: result=new(mArenaPool) CEndToken(aString, aTag); break; + case eToken_comment: result=new(mArenaPool) CCommentToken(aString); break; case eToken_entity: result=new(mArenaPool) CEntityToken(aString); break; - case eToken_whitespace: result=new(mArenaPool) CWhitespaceToken(); break; + case eToken_whitespace: result=new(mArenaPool) CWhitespaceToken(aString); break; case eToken_newline: result=new(mArenaPool) CNewlineToken(); break; case eToken_text: result=new(mArenaPool) CTextToken(aString); break; case eToken_attribute: result=new(mArenaPool) CAttributeToken(aString); break; - case eToken_script: result=new(mArenaPool) CScriptToken(); break; - case eToken_style: result=new(mArenaPool) CStyleToken(); break; - case eToken_skippedcontent: result=new(mArenaPool) CSkippedContentToken(aString); break; - case eToken_instruction: result=new(mArenaPool) CInstructionToken(); break; - case eToken_cdatasection: result=new(mArenaPool) CCDATASectionToken(); break; + case eToken_script: result=new(mArenaPool) CScriptToken(aString); break; + case eToken_style: result=new(mArenaPool) CStyleToken(aString); break; + case eToken_instruction: result=new(mArenaPool) CInstructionToken(aString); break; + case eToken_cdatasection: result=new(mArenaPool) CCDATASectionToken(aString); break; case eToken_error: result=new(mArenaPool) CErrorToken(); break; case eToken_doctypeDecl: result=new(mArenaPool) CDoctypeDeclToken(); break; default: + NS_ASSERTION(PR_FALSE, "nsDTDUtils::CreateTokenOfType: illegal token type"); break; } @@ -1279,45 +1279,21 @@ CToken* nsTokenAllocator::CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag case eToken_entity: result=new(mArenaPool) CEntityToken(); break; case eToken_whitespace: result=new(mArenaPool) CWhitespaceToken(); break; case eToken_newline: result=new(mArenaPool) CNewlineToken(); break; - case eToken_text: result=new(mArenaPool) CTextToken(NS_ConvertToString("")); break; + case eToken_text: result=new(mArenaPool) CTextToken(); break; case eToken_script: result=new(mArenaPool) CScriptToken(); break; case eToken_style: result=new(mArenaPool) CStyleToken(); break; - case eToken_skippedcontent: result=new(mArenaPool) CSkippedContentToken(NS_ConvertToString("")); break; case eToken_instruction: result=new(mArenaPool) CInstructionToken(); break; case eToken_cdatasection: result=new(mArenaPool) CCDATASectionToken(); break; case eToken_error: result=new(mArenaPool) CErrorToken(); break; case eToken_doctypeDecl: result=new(mArenaPool) CDoctypeDeclToken(aTag); break; default: + NS_ASSERTION(PR_FALSE, "nsDTDUtils::CreateTokenOfType: illegal token type"); break; } return result; } -/** - * Let's get this code ready to be reused by all the contexts. - * - * @update harishd 08/04/00 - * @param aType -- tells you the type of token to create - * @param aTag -- tells you the type of tag to init with this token - * - * @return ptr to new token (or 0). - */ -CToken* nsTokenAllocator::CreateRTFTokenOfType(eRTFTokenTypes aType,eRTFTags aTag) { - - CToken* result=0; - - switch(aType){ - case eRTFToken_controlword: result=new(mArenaPool) CRTFControlWord(aTag); break; - case eRTFToken_content: result=new(mArenaPool) CRTFContent(); break; - default: - break; - } - - return result; -} - - CNodeRecycler::CNodeRecycler(): mSharedNodes(0) { MOZ_COUNT_CTOR(CNodeRecycler); @@ -1550,7 +1526,7 @@ nsresult nsObserverTopic::Notify(eHTMLTags aTag,nsIParserNode& aNode,void* aUniq mValues.Empty(); int index = 0; for(index=0; index<theAttrCount; index++) { - mKeys.Push((PRUnichar*)aNode.GetKeyAt(index).GetUnicode()); + mKeys.Push((void*)nsPromiseFlatString(aNode.GetKeyAt(index)).get()); mValues.Push((PRUnichar*)aNode.GetValueAt(index).GetUnicode()); } diff --git a/mozilla/parser/htmlparser/src/nsDTDUtils.h b/mozilla/parser/htmlparser/src/nsDTDUtils.h index d8ba383bd9c..6f7f4da884f 100644 --- a/mozilla/parser/htmlparser/src/nsDTDUtils.h +++ b/mozilla/parser/htmlparser/src/nsDTDUtils.h @@ -43,7 +43,6 @@ #include "nsIElementObserver.h" #include "nsIParserNode.h" #include "nsFixedSizeAllocator.h" -#include "CRtfDTD.h" #define IF_HOLD(_ptr) if(_ptr) { _ptr->AddRef(); } #define IF_FREE(_ptr) if(_ptr) { _ptr->Release(); _ptr=0; } // recycles _ptr @@ -226,9 +225,8 @@ public: nsTokenAllocator(); virtual ~nsTokenAllocator(); - virtual CToken* CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag, const nsString& aString); + virtual CToken* CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag, const nsAReadableString& aString); virtual CToken* CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag); - virtual CToken* CreateRTFTokenOfType(eRTFTokenTypes aType,eRTFTags aTag); protected: nsFixedSizeAllocator mArenaPool; diff --git a/mozilla/parser/htmlparser/src/nsElementTable.cpp b/mozilla/parser/htmlparser/src/nsElementTable.cpp index f9d081bf74f..21bd12e240c 100644 --- a/mozilla/parser/htmlparser/src/nsElementTable.cpp +++ b/mozilla/parser/htmlparser/src/nsElementTable.cpp @@ -1307,6 +1307,14 @@ void InitializeElementTable(void) { }//if }; +void DeleteElementTable(void) +{ + if(gHTMLElements) { + delete [] gHTMLElements; //fixed bug 49564 + gHTMLElements=0; + } +} + int nsHTMLElement::GetSynonymousGroups(eHTMLTags aTag) { int result=0; diff --git a/mozilla/parser/htmlparser/src/nsElementTable.h b/mozilla/parser/htmlparser/src/nsElementTable.h index 23e16a3675c..6c77d16aa24 100644 --- a/mozilla/parser/htmlparser/src/nsElementTable.h +++ b/mozilla/parser/htmlparser/src/nsElementTable.h @@ -78,7 +78,7 @@ static const int kAllTags = 0xffffff; extern void InitializeElementTable(void); - +extern void DeleteElementTable(void); /** * We're asking the question: is aTest a member of bitset. diff --git a/mozilla/parser/htmlparser/src/nsExpatTokenizer.cpp b/mozilla/parser/htmlparser/src/nsExpatTokenizer.cpp index b5d32e0c713..99e8b53aa88 100644 --- a/mozilla/parser/htmlparser/src/nsExpatTokenizer.cpp +++ b/mozilla/parser/htmlparser/src/nsExpatTokenizer.cpp @@ -44,10 +44,16 @@ typedef struct _XMLParserState { XML_Parser parser; + nsScanner* scanner; + const PRUnichar* bufferStart; + const PRUnichar* bufferEnd; + nsReadingIterator<PRUnichar> currentIterator; nsDeque* tokenDeque; nsTokenAllocator* tokenAllocator; - CToken* doctypeToken; - CToken* cdataToken; // Used by the begin and end handlers of the cdata section + nsString doctypeText; + PRBool indoctype; + nsString cdataText; + PRBool incdata; } XMLParserState; /************************************************************************ @@ -176,10 +182,10 @@ nsExpatTokenizer::nsExpatTokenizer(nsString* aURL) : nsHTMLTokenizer() { mBytesParsed = 0; mState = new XMLParserState; mState->tokenAllocator = nsnull; - mState->cdataToken = nsnull; mState->parser = nsnull; mState->tokenDeque = nsnull; - mState->doctypeToken = nsnull; + mState->indoctype = PR_FALSE; + mState->incdata = PR_FALSE; nsAutoString buffer; buffer.AssignWithConversion("UTF-16"); const PRUnichar* encoding = buffer.GetUnicode(); @@ -341,18 +347,15 @@ nsExpatTokenizer::AddErrorMessageTokens(nsParserError* aError) AddToken(newToken, NS_OK, mState->tokenDeque, mState->tokenAllocator); CAttributeToken* attrToken = (CAttributeToken*) - mState->tokenAllocator->CreateTokenOfType(eToken_attribute, eHTMLTag_unknown); - nsString& key = attrToken->GetKey(); - key.AssignWithConversion("xmlns"); - attrToken->SetCStringValue(kHTMLNameSpaceURI); + mState->tokenAllocator->CreateTokenOfType(eToken_attribute, eHTMLTag_unknown, NS_ConvertASCIItoUCS2(kHTMLNameSpaceURI)); + attrToken->SetKey(NS_LITERAL_STRING("xmlns")); newToken->SetAttributeCount(1); newToken = (CToken*) attrToken; AddToken(newToken, NS_OK, mState->tokenDeque, mState->tokenAllocator); nsAutoString textStr; CreateErrorText(aError, textStr); - newToken = mState->tokenAllocator->CreateTokenOfType(eToken_text, eHTMLTag_unknown); - newToken->SetStringValue(textStr); + newToken = mState->tokenAllocator->CreateTokenOfType(eToken_text, eHTMLTag_unknown, textStr); AddToken(newToken, NS_OK, mState->tokenDeque, mState->tokenAllocator); newToken = mState->tokenAllocator->CreateTokenOfType(eToken_start, eHTMLTag_sourcetext); @@ -360,8 +363,7 @@ nsExpatTokenizer::AddErrorMessageTokens(nsParserError* aError) textStr.Truncate(); CreateSourceText(aError, textStr); - newToken = mState->tokenAllocator->CreateTokenOfType(eToken_text, eHTMLTag_unknown); - newToken->SetStringValue(textStr); + newToken = mState->tokenAllocator->CreateTokenOfType(eToken_text, eHTMLTag_unknown,textStr); AddToken(newToken, NS_OK, mState->tokenDeque, mState->tokenAllocator); newToken = mState->tokenAllocator->CreateTokenOfType(eToken_end, eHTMLTag_sourcetext); @@ -470,19 +472,35 @@ nsresult nsExpatTokenizer::ConsumeToken(nsScanner& aScanner,PRBool& aFlushTokens // Ask the scanner to send us all the data it has // scanned and pass that data to expat. nsresult result = NS_OK; - nsString& theBuffer = aScanner.GetBuffer(); - PRUint32 bufLength = theBuffer.Length() * sizeof(PRUnichar); - const PRUnichar* expatBuffer = (bufLength) ? theBuffer.GetUnicode() : nsnull; - + nsReadingIterator<PRUnichar> start, end; + aScanner.CurrentPosition(start); + aScanner.EndReading(end); mState->tokenDeque = &mTokenDeque; mState->parser = mExpatParser; + mState->scanner = &aScanner; - result = ParseXMLBuffer((const char *)expatBuffer, bufLength); - - theBuffer.Truncate(0); + while (start != end) { + PRUint32 fragLength = PRUint32(start.size_forward()); + PRUint32 bufLength = fragLength * sizeof(PRUnichar); + const PRUnichar* expatBuffer = start.get(); + + mState->bufferStart = expatBuffer; + mState->bufferEnd = expatBuffer + fragLength; + mState->currentIterator = start; + result = ParseXMLBuffer((const char *)expatBuffer, bufLength); + if (NS_FAILED(result)) return result; + + start.advance(fragLength); + } + + aScanner.SetPosition(end, PR_TRUE); if(NS_OK==result) result=aScanner.Eof(); + + mState->scanner = nsnull; + mState->bufferStart = mState->bufferEnd = nsnull; + return result; } @@ -506,7 +524,7 @@ void nsExpatTokenizer::FrontloadMisplacedContent(nsDeque& aDeque){ void nsExpatTokenizer::HandleStartElement(void *userData, const XML_Char *name, const XML_Char **atts) { XMLParserState* state = (XMLParserState*) userData; - CToken* theToken = state->tokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_unknown); + CToken* theToken = state->tokenAllocator->CreateTokenOfType(eToken_start,eHTMLTag_unknown, nsLiteralString((PRUnichar*)name)); if(theToken) { // If an ID attribute exists for this element, set it on the start token PRInt32 index = XML_GetIdAttributeIndex(state->parser); @@ -516,9 +534,6 @@ void nsExpatTokenizer::HandleStartElement(void *userData, const XML_Char *name, startToken->SetIDAttributeAtom(attributeAtom); } - // Set the element name on the start token and add the token to the token queue - nsString& theString=theToken->GetStringValueXXX(); - theString.Assign((PRUnichar *) name); AddToken(theToken, NS_OK, state->tokenDeque, state->tokenAllocator); // For each attribute on this element, create and add attribute tokens to the token queue @@ -526,15 +541,25 @@ void nsExpatTokenizer::HandleStartElement(void *userData, const XML_Char *name, while(*atts){ theAttrCount++; CAttributeToken* theAttrToken = (CAttributeToken*) - state->tokenAllocator->CreateTokenOfType(eToken_attribute, eHTMLTag_unknown); + state->tokenAllocator->CreateTokenOfType(eToken_attribute, eHTMLTag_unknown, nsLiteralString((PRUnichar*)atts[1])); if(theAttrToken){ - nsString& theKey=theAttrToken->GetKey(); - theKey.Assign((PRUnichar *) (*atts++)); - nsString& theValue=theAttrToken->GetStringValueXXX(); - theValue.Assign((PRUnichar *) (*atts++)); + PRUnichar* ptr = (PRUnichar*)atts[0]; + if ((ptr >= state->bufferStart) && (ptr < state->bufferEnd)) { + PRUint32 len = nsCRT::strlen(ptr); + nsReadingIterator<PRUnichar> start, end; + start = state->currentIterator; + start.advance(ptr - state->bufferStart); + end = start; + end.advance(len); + theAttrToken->BindKey(state->scanner, start, end); + } + else { + theAttrToken->SetKey(nsLiteralString(ptr)); + } } CToken* theTok=(CToken*)theAttrToken; AddToken(theTok, NS_OK, state->tokenDeque, state->tokenAllocator); + atts += 2; } theToken->SetAttributeCount(theAttrCount); } @@ -545,10 +570,8 @@ void nsExpatTokenizer::HandleStartElement(void *userData, const XML_Char *name, void nsExpatTokenizer::HandleEndElement(void *userData, const XML_Char *name) { XMLParserState* state = (XMLParserState*) userData; - CToken* theToken = state->tokenAllocator->CreateTokenOfType(eToken_end,eHTMLTag_unknown); + CToken* theToken = state->tokenAllocator->CreateTokenOfType(eToken_end,eHTMLTag_unknown, nsLiteralString((PRUnichar *) name)); if(theToken) { - nsString& theString=theToken->GetStringValueXXX(); - theString.Assign((PRUnichar *) name); AddToken(theToken, NS_OK, state->tokenDeque, state->tokenAllocator); } else{ @@ -558,13 +581,11 @@ void nsExpatTokenizer::HandleEndElement(void *userData, const XML_Char *name) { void nsExpatTokenizer::HandleCharacterData(void *userData, const XML_Char *s, int len) { XMLParserState* state = (XMLParserState*) userData; - CCDATASectionToken* currentCDataToken = (CCDATASectionToken*) state->cdataToken; - if (currentCDataToken) { - // While there exists a current CDATA token, keep appending all strings + if (state->incdata) { + // While we're in a CDATASection, keep appending all strings // from expat into it. - nsString& theString = currentCDataToken->GetStringValueXXX(); - theString.Append((PRUnichar *) s,len); + state->cdataText.Append((PRUnichar *) s,len); } else { CToken* newToken = 0; @@ -575,17 +596,28 @@ void nsExpatTokenizer::HandleCharacterData(void *userData, const XML_Char *s, in break; case kSpace: case kTab: - newToken = state->tokenAllocator->CreateTokenOfType(eToken_whitespace,eHTMLTag_unknown); + newToken = state->tokenAllocator->CreateTokenOfType(eToken_whitespace,eHTMLTag_unknown, nsLiteralString((PRUnichar*)s, len)); break; default: - newToken = state->tokenAllocator->CreateTokenOfType(eToken_text,eHTMLTag_unknown); + { + CTextToken* textToken = (CTextToken*)state->tokenAllocator->CreateTokenOfType(eToken_text, eHTMLTag_unknown); + PRUnichar* ptr = (PRUnichar*)s; + if ((ptr >= state->bufferStart) && (ptr < state->bufferEnd)) { + nsReadingIterator<PRUnichar> start, end; + start = state->currentIterator; + start.advance(ptr - state->bufferStart); + end = start; + end.advance(len); + textToken->Bind(state->scanner, start, end); + } + else { + textToken->Bind(nsLiteralString(ptr, len)); + } + newToken = textToken; + } } if(newToken) { - if ((((PRUnichar*)s)[0] != (XML_Char)kNewLine) && (((PRUnichar*)s)[0] != (XML_Char)kCR)) { - nsString& theString=newToken->GetStringValueXXX(); - theString.Append((PRUnichar *) s,len); - } AddToken(newToken, NS_OK, state->tokenDeque, state->tokenAllocator); } else { @@ -596,10 +628,8 @@ void nsExpatTokenizer::HandleCharacterData(void *userData, const XML_Char *s, in void nsExpatTokenizer::HandleComment(void *userData, const XML_Char *name) { XMLParserState* state = (XMLParserState*) userData; - CToken* theToken = state->tokenAllocator->CreateTokenOfType(eToken_comment, eHTMLTag_unknown); + CToken* theToken = state->tokenAllocator->CreateTokenOfType(eToken_comment, eHTMLTag_unknown, nsLiteralString((PRUnichar*)name)); if(theToken) { - nsString& theString=theToken->GetStringValueXXX(); - theString.Assign((PRUnichar *) name); AddToken(theToken, NS_OK, state->tokenDeque, state->tokenAllocator); } else{ @@ -609,21 +639,22 @@ void nsExpatTokenizer::HandleComment(void *userData, const XML_Char *name) { void nsExpatTokenizer::HandleStartCdataSection(void *userData) { XMLParserState* state = (XMLParserState*) userData; - CToken* cdataToken = state->tokenAllocator->CreateTokenOfType(eToken_cdatasection, - eHTMLTag_unknown); - state->cdataToken = cdataToken; + state->incdata = PR_TRUE; } void nsExpatTokenizer::HandleEndCdataSection(void *userData) { XMLParserState* state = (XMLParserState*) userData; - CToken* currentCDataToken = (CToken*) state->cdataToken; + CToken* cdataToken = state->tokenAllocator->CreateTokenOfType(eToken_cdatasection, + eHTMLTag_unknown, + state->cdataText); // We've reached the end of the current CDATA section. Push the current // CDATA token onto the token queue - AddToken(currentCDataToken, NS_OK, state->tokenDeque, state->tokenAllocator); + AddToken(cdataToken, NS_OK, state->tokenDeque, state->tokenAllocator); - state->cdataToken = nsnull; + state->incdata = PR_FALSE; + state->cdataText.Truncate(); } void nsExpatTokenizer::HandleProcessingInstruction(void *userData, @@ -631,16 +662,17 @@ void nsExpatTokenizer::HandleProcessingInstruction(void *userData, const XML_Char *data) { XMLParserState* state = (XMLParserState*) userData; - CToken* theToken = state->tokenAllocator->CreateTokenOfType(eToken_instruction,eHTMLTag_unknown); + nsAutoString theString; + theString. AppendWithConversion("<?"); + theString.Append((PRUnichar *) target); + if(data) { + theString.AppendWithConversion(" "); + theString.Append((PRUnichar *) data); + } + theString.AppendWithConversion("?>"); + + CToken* theToken = state->tokenAllocator->CreateTokenOfType(eToken_instruction,eHTMLTag_unknown, theString); if(theToken) { - nsString& theString=theToken->GetStringValueXXX(); - theString. AppendWithConversion("<?"); - theString.Append((PRUnichar *) target); - if(data) { - theString.AppendWithConversion(" "); - theString.Append((PRUnichar *) data); - } - theString.AppendWithConversion("?>"); AddToken(theToken, NS_OK, state->tokenDeque, state->tokenAllocator); } else{ @@ -650,9 +682,8 @@ void nsExpatTokenizer::HandleProcessingInstruction(void *userData, void nsExpatTokenizer::HandleDefault(void *userData, const XML_Char *s, int len) { XMLParserState* state = (XMLParserState*) userData; - if (state->doctypeToken) { - nsString& doctypestr = state->doctypeToken->GetStringValueXXX(); - doctypestr.Append((PRUnichar*)s, len); + if (state->indoctype) { + state->doctypeText.Append((PRUnichar*)s, len); } else { nsAutoString str((PRUnichar *)s, len); @@ -872,23 +903,20 @@ void nsExpatTokenizer::HandleStartDoctypeDecl(void *userData, const XML_Char *doctypeName) { XMLParserState* state = (XMLParserState*) userData; - CToken* token = state->tokenAllocator->CreateTokenOfType(eToken_doctypeDecl, eHTMLTag_unknown); - if (token) { - nsString& str = token->GetStringValueXXX(); - str.AppendWithConversion(kDocTypeDeclPrefix); - state->doctypeToken = token; - } + state->indoctype = PR_TRUE; + state->doctypeText.Assign((PRUnichar*)kDocTypeDeclPrefix); } void nsExpatTokenizer::HandleEndDoctypeDecl(void *userData) { XMLParserState* state = (XMLParserState*) userData; - CToken* token = state->doctypeToken; + + state->doctypeText.AppendWithConversion(">"); + CToken* token = state->tokenAllocator->CreateTokenOfType(eToken_doctypeDecl, eHTMLTag_unknown, state->doctypeText); if (token) { - nsString& str = token->GetStringValueXXX(); - str.AppendWithConversion(">"); AddToken(token, NS_OK, state->tokenDeque, state->tokenAllocator); - state->doctypeToken = nsnull; } + state->indoctype = PR_FALSE; + state->doctypeText.Truncate(); // Do nothing } diff --git a/mozilla/parser/htmlparser/src/nsHTMLContentSinkStream.cpp b/mozilla/parser/htmlparser/src/nsHTMLContentSinkStream.cpp index 04fcede6a29..47cc43332db 100644 --- a/mozilla/parser/htmlparser/src/nsHTMLContentSinkStream.cpp +++ b/mozilla/parser/htmlparser/src/nsHTMLContentSinkStream.cpp @@ -272,7 +272,7 @@ void nsHTMLContentSinkStream::EnsureBufferSize(PRInt32 aNewSize) * @param aString - the string to write. * @return The number of characters written. */ -PRInt32 nsHTMLContentSinkStream::Write(const nsString& aString) +PRInt32 nsHTMLContentSinkStream::Write(const nsAReadableString& aString) { if (mBodyOnly && !mInBody) return 0; @@ -289,7 +289,7 @@ PRInt32 nsHTMLContentSinkStream::Write(const nsString& aString) { nsresult res; PRUnichar *encodedBuffer = nsnull; - res = mEntityConverter->ConvertToEntities(aString.GetUnicode(), + res = mEntityConverter->ConvertToEntities(nsPromiseFlatString(aString), nsIEntityConverter::html40Latin1, &encodedBuffer); if (NS_SUCCEEDED(res) && encodedBuffer) @@ -328,7 +328,7 @@ PRInt32 nsHTMLContentSinkStream::Write(const nsString& aString) { // Call the converter to convert to the target charset. // Convert() takes a char* output param even though it's writing unicode. - res = mCharsetEncoder->Convert(aString.GetUnicode(), &encodedBuffer); + res = mCharsetEncoder->Convert(nsPromiseFlatString(aString), &encodedBuffer); if (NS_SUCCEEDED(res) && encodedBuffer) { charsWritten = nsCRT::strlen(encodedBuffer); @@ -339,7 +339,7 @@ PRInt32 nsHTMLContentSinkStream::Write(const nsString& aString) // If it didn't work, just write the unicode else { - const PRUnichar* unicode = aString.GetUnicode(); + const PRUnichar* unicode = nsPromiseFlatString(aString); charsWritten = aString.Length(); out.write(unicode, charsWritten); } @@ -348,7 +348,7 @@ PRInt32 nsHTMLContentSinkStream::Write(const nsString& aString) // If we couldn't get an encoder, just write the unicode else { - const PRUnichar* unicode = aString.GetUnicode(); + const PRUnichar* unicode = nsPromiseFlatString(aString); charsWritten = aString.Length(); out.write(unicode, charsWritten); } @@ -399,7 +399,7 @@ void nsHTMLContentSinkStream::WriteAttributes(const nsIParserNode& aNode) if(theCount) { int i=0; for(i=0;i<theCount;i++){ - nsString& key = (nsString&)aNode.GetKeyAt(i); + nsAutoString key(aNode.GetKeyAt(i)); // See if there's an attribute: // note that we copy here, because we're going to have to trim quotes. @@ -591,7 +591,7 @@ PRBool nsHTMLContentSinkStream::IsDirty(const nsIParserNode& aNode) { for(int i=0; i < theCount; i++) { - nsString& key = (nsString&)aNode.GetKeyAt(i); + const nsAReadableString& key = (nsString&)aNode.GetKeyAt(i); if (key.Equals(gMozDirty)) return PR_TRUE; } @@ -614,7 +614,7 @@ void nsHTMLContentSinkStream::AddStartTag(const nsIParserNode& aNode) eHTMLTags tag = (eHTMLTags)aNode.GetNodeType(); PRBool isDirty = IsDirty(aNode); - const nsString& name = aNode.GetText(); + const nsAReadableString& name = aNode.GetText(); nsAutoString tagName; if (tag == eHTMLTag_body) @@ -722,7 +722,7 @@ void nsHTMLContentSinkStream::AddEndTag(const nsIParserNode& aNode) #ifdef DEBUG_prettyprint if (isDirty) printf("AddEndTag(%s): BBO=%d, BAO=%d, BBC=%d, BAC=%d\n", - aNode.GetText().ToNewCString(), + (const char*)NS_ConvertUCS2toUTF8(aNode.GetText()), BreakBeforeOpen(tag), BreakAfterOpen(tag), BreakBeforeClose(tag), @@ -845,7 +845,7 @@ nsHTMLContentSinkStream::AddLeaf(const nsIParserNode& aNode) else if (type == eHTMLTag_entity) { Write('&'); - const nsString& entity = aNode.GetText(); + const nsAReadableString& entity = aNode.GetText(); mColPos += Write(entity) + 1; // Don't write the semicolon; // rely on the DTD to include it if one is wanted. @@ -857,7 +857,7 @@ nsHTMLContentSinkStream::AddLeaf(const nsIParserNode& aNode) && (mFlags & nsIDocumentEncoder::OutputSelectionOnly)) return NS_OK; - const nsString& text = aNode.GetText(); + const nsAReadableString& text = aNode.GetText(); if (mPreLevel > 0) { Write(text); @@ -884,7 +884,7 @@ nsHTMLContentSinkStream::AddLeaf(const nsIParserNode& aNode) { if (!mDoFormat || mPreLevel > 0) { - const nsString& text = aNode.GetText(); + const nsAReadableString& text = aNode.GetText(); Write(text); mColPos += text.Length(); } @@ -904,15 +904,14 @@ nsHTMLContentSinkStream::AddLeaf(const nsIParserNode& aNode) // See if the string has any lines longer than longLineLen: // if so, we presume formatting is wonky (e.g. the node has been edited) // and we'd better rewrap the whole text node. -PRBool nsHTMLContentSinkStream::HasLongLines(const nsString& text) +PRBool nsHTMLContentSinkStream::HasLongLines(const nsAReadableString& text) { const PRUint32 longLineLen = 128; - nsString str = text; PRUint32 start=0; PRUint32 theLen=text.Length(); for (start = 0; start < theLen; ) { - PRInt32 eol = text.FindChar('\n', PR_FALSE, start); + PRInt32 eol = text.FindChar('\n', start); if (eol < 0) eol = text.Length(); if ((PRUint32)(eol - start) > longLineLen) return PR_TRUE; @@ -921,7 +920,7 @@ PRBool nsHTMLContentSinkStream::HasLongLines(const nsString& text) return PR_FALSE; } -void nsHTMLContentSinkStream::WriteWrapped(const nsString& text) +void nsHTMLContentSinkStream::WriteWrapped(const nsAReadableString& text) { // 1. Determine the length of the input string PRInt32 length = text.Length(); @@ -935,7 +934,7 @@ void nsHTMLContentSinkStream::WriteWrapped(const nsString& text) } else { - nsString str = text; + nsAutoString str(text); PRBool done = PR_FALSE; PRInt32 indx = 0; PRInt32 offset = mColPos; @@ -1051,16 +1050,16 @@ nsHTMLContentSinkStream::OpenContainer(const nsIParserNode& aNode) PRInt32 count=aNode.GetAttributeCount(); for(PRInt32 i=0;i<count;i++) { - const nsString& key=aNode.GetKeyAt(i); + const nsAReadableString& key=aNode.GetKeyAt(i); - if (key.EqualsWithConversion("charset")) + if (key.Equals(NS_LITERAL_STRING("charset"))) { const nsString& value=aNode.GetValueAt(i); if (mCharsetOverride.IsEmpty()) mCharsetOverride.Assign(value); InitEncoders(); } - else if (key.EqualsWithConversion("uri")) + else if (key.Equals(NS_LITERAL_STRING("uri"))) { nsAutoString uristring; uristring.Assign(aNode.GetValueAt(i)); diff --git a/mozilla/parser/htmlparser/src/nsHTMLContentSinkStream.h b/mozilla/parser/htmlparser/src/nsHTMLContentSinkStream.h index 90d0945cd65..330e8675322 100644 --- a/mozilla/parser/htmlparser/src/nsHTMLContentSinkStream.h +++ b/mozilla/parser/htmlparser/src/nsHTMLContentSinkStream.h @@ -164,13 +164,13 @@ protected: NS_IMETHOD InitEncoders(); - PRInt32 Write(const nsString& aString); // returns # chars written + PRInt32 Write(const nsAReadableString& aString); // returns # chars written void Write(const char* aCharBuffer); void Write(char aChar); // Handle wrapping and conditional wrapping: - PRBool HasLongLines(const nsString& text); - void WriteWrapped(const nsString& text); + PRBool HasLongLines(const nsAReadableString& text); + void WriteWrapped(const nsAReadableString& text); // Is this node "dirty", needing reformatting? PRBool IsDirty(const nsIParserNode& aNode); diff --git a/mozilla/parser/htmlparser/src/nsHTMLEntities.cpp b/mozilla/parser/htmlparser/src/nsHTMLEntities.cpp index 4942fc2eb43..9ba225b2887 100644 --- a/mozilla/parser/htmlparser/src/nsHTMLEntities.cpp +++ b/mozilla/parser/htmlparser/src/nsHTMLEntities.cpp @@ -174,7 +174,7 @@ nsHTMLEntities::EntityToUnicode(const nsCString& aEntity) PRInt32 -nsHTMLEntities::EntityToUnicode(const nsString& aEntity) { +nsHTMLEntities::EntityToUnicode(const nsAReadableString& aEntity) { nsCAutoString theEntity; theEntity.AssignWithConversion(aEntity); if(';'==theEntity.Last()) { theEntity.Truncate(theEntity.Length()-1); diff --git a/mozilla/parser/htmlparser/src/nsHTMLEntities.h b/mozilla/parser/htmlparser/src/nsHTMLEntities.h index 6c1da7a49cb..074cb02f05f 100644 --- a/mozilla/parser/htmlparser/src/nsHTMLEntities.h +++ b/mozilla/parser/htmlparser/src/nsHTMLEntities.h @@ -37,7 +37,7 @@ public: * passed in must NOT have the leading "&" nor the trailing ";" * in it. */ - static PRInt32 EntityToUnicode(const nsString& aEntity); + static PRInt32 EntityToUnicode(const nsAReadableString& aEntity); static PRInt32 EntityToUnicode(const nsCString& aEntity); /** diff --git a/mozilla/parser/htmlparser/src/nsHTMLNullSink.cpp b/mozilla/parser/htmlparser/src/nsHTMLNullSink.cpp index 17c0c3d9984..e866257ec45 100644 --- a/mozilla/parser/htmlparser/src/nsHTMLNullSink.cpp +++ b/mozilla/parser/htmlparser/src/nsHTMLNullSink.cpp @@ -23,7 +23,6 @@ #include "nsHTMLTokens.h" #include "nsIParser.h" #include "prtypes.h" - #define VERBOSE_DEBUG static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); @@ -128,12 +127,11 @@ nsHTMLNullSink::~nsHTMLNullSink() { } #ifdef VERBOSE_DEBUG -static void DebugDump(const char* str1,const nsString& str2,PRInt32 tabs) { +static void DebugDump(const char* str1,const nsAReadableString& str2,PRInt32 tabs) { for(PRInt32 i=0;i<tabs;i++) cout << " "; //add some tabbing to debug output... - char* cp = str2.ToNewCString(); + const char* cp = NS_ConvertUCS2toUTF8(str2); cout << str1 << cp << ">" << endl; - delete[] cp; } #endif diff --git a/mozilla/parser/htmlparser/src/nsHTMLToTXTSinkStream.cpp b/mozilla/parser/htmlparser/src/nsHTMLToTXTSinkStream.cpp index 41768f72ded..2b99e82364a 100644 --- a/mozilla/parser/htmlparser/src/nsHTMLToTXTSinkStream.cpp +++ b/mozilla/parser/htmlparser/src/nsHTMLToTXTSinkStream.cpp @@ -449,8 +449,8 @@ nsHTMLToTXTSinkStream::GetValueOfAttribute(const nsIParserNode& aNode, PRInt32 count=aNode.GetAttributeCount(); for (PRInt32 i=0;i<count;i++) { - const nsString& key = aNode.GetKeyAt(i); - if (key == matchKey) + const nsAReadableString& key = aNode.GetKeyAt(i); + if (key.Equals(matchKey)) { aValueRet = aNode.GetValueAt(i); return NS_OK; @@ -509,8 +509,8 @@ NS_IMETHODIMP nsHTMLToTXTSinkStream::OpenContainer(const nsIParserNode& aNode) { eHTMLTags type = (eHTMLTags)aNode.GetNodeType(); - const nsString& name = aNode.GetText(); - if (name.EqualsWithConversion("document_info")) + const nsAReadableString& name = aNode.GetText(); + if (name.Equals(NS_LITERAL_STRING("document_info"))) { nsString value; if (NS_SUCCEEDED(GetValueOfAttribute(aNode, "charset", value))) @@ -893,7 +893,7 @@ nsHTMLToTXTSinkStream::AddLeaf(const nsIParserNode& aNode) eHTMLTags type = (eHTMLTags)aNode.GetNodeType(); - nsString text = aNode.GetText(); + nsAutoString text(aNode.GetText()); if (mTagStackIndex > 1 && mTagStack[mTagStackIndex-2] == eHTMLTag_select) { diff --git a/mozilla/parser/htmlparser/src/nsHTMLTokenizer.cpp b/mozilla/parser/htmlparser/src/nsHTMLTokenizer.cpp index 8bfca2430d5..4e82e5744ec 100644 --- a/mozilla/parser/htmlparser/src/nsHTMLTokenizer.cpp +++ b/mozilla/parser/htmlparser/src/nsHTMLTokenizer.cpp @@ -33,6 +33,7 @@ #include "nsElementTable.h" #include "nsHTMLEntities.h" #include "CParserContext.h" +#include "nsReadableUtils.h" /************************************************************************ And now for the main class -- nsHTMLTokenizer... @@ -441,7 +442,7 @@ nsresult nsHTMLTokenizer::ConsumeToken(nsScanner& aScanner,PRBool& aFlushTokens) PRUnichar theChar; CToken* theToken=0; - nsresult result=aScanner.GetChar(theChar); + nsresult result=aScanner.Peek(theChar); switch(result) { case kEOF: @@ -468,8 +469,7 @@ nsresult nsHTMLTokenizer::ConsumeToken(nsScanner& aScanner,PRBool& aFlushTokens) } else { if(!nsCRT::IsAsciiSpace(theChar)) { - nsAutoString temp(theChar); - result=ConsumeText(temp,theToken,aScanner); + result=ConsumeText(theToken,aScanner); break; } result=ConsumeWhitespace(theChar,theToken,aScanner); @@ -494,16 +494,19 @@ nsresult nsHTMLTokenizer::ConsumeToken(nsScanner& aScanner,PRBool& aFlushTokens) */ nsresult nsHTMLTokenizer::ConsumeTag(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner,PRBool& aFlushTokens) { - nsresult result=aScanner.GetChar(aChar); + PRUnichar theNextChar, oldChar; + nsresult result=aScanner.Peek(aChar,1); if(NS_OK==result) { switch(aChar) { case kForwardSlash: - PRUnichar ch; - result=aScanner.Peek(ch); + // Get the original "<" (we've already seen it with a Peek) + aScanner.GetChar(oldChar); + + result=aScanner.Peek(theNextChar, 1); if(NS_OK==result) { - if(nsCRT::IsAsciiAlpha(ch)||(kGreaterThan==ch)) { + if(nsCRT::IsAsciiAlpha(theNextChar)||(kGreaterThan==theNextChar)) { result=ConsumeEndTag(aChar,aToken,aScanner); } else result=ConsumeComment(aChar,aToken,aScanner); @@ -511,8 +514,10 @@ nsresult nsHTMLTokenizer::ConsumeTag(PRUnichar aChar,CToken*& aToken,nsScanner& break; case kExclamation: - PRUnichar theNextChar; - result=aScanner.Peek(theNextChar); + // Get the original "<" (we've already seen it with a Peek) + aScanner.GetChar(oldChar); + + result=aScanner.Peek(theNextChar, 1); if(NS_OK==result) { if((kMinus==theNextChar) || (kGreaterThan==theNextChar)) { result=ConsumeComment(aChar,aToken,aScanner); @@ -523,18 +528,21 @@ nsresult nsHTMLTokenizer::ConsumeTag(PRUnichar aChar,CToken*& aToken,nsScanner& break; case kQuestionMark: //it must be an XML processing instruction... + // Get the original "<" (we've already seen it with a Peek) + aScanner.GetChar(oldChar); result=ConsumeProcessingInstruction(aChar,aToken,aScanner); break; default: - if(nsCRT::IsAsciiAlpha(aChar)) + if(nsCRT::IsAsciiAlpha(aChar)) { + // Get the original "<" (we've already seen it with a Peek) + aScanner.GetChar(oldChar); result=ConsumeStartTag(aChar,aToken,aScanner,aFlushTokens); + } else if(kEOF!=aChar) { - // We are not dealing with a tag. So, put back the char - // and leave the decision to ConsumeText(). - aScanner.PutBack(aChar); - nsAutoString temp; temp.AssignWithConversion("<"); - result=ConsumeText(temp,aToken,aScanner); + // We are not dealing with a tag. So, don't consume the original + // char and leave the decision to ConsumeText(). + result=ConsumeText(aToken,aScanner); } } //switch @@ -552,7 +560,7 @@ nsresult nsHTMLTokenizer::ConsumeTag(PRUnichar aChar,CToken*& aToken,nsScanner& * @param aLeadingWS: contains ws chars that preceeded the first attribute * @return */ -nsresult nsHTMLTokenizer::ConsumeAttributes(PRUnichar aChar,CStartToken* aToken,nsScanner& aScanner,nsString& aLeadingWS) { +nsresult nsHTMLTokenizer::ConsumeAttributes(PRUnichar aChar,CStartToken* aToken,nsScanner& aScanner) { PRBool done=PR_FALSE; nsresult result=NS_OK; PRInt16 theAttrCount=0; @@ -560,13 +568,8 @@ nsresult nsHTMLTokenizer::ConsumeAttributes(PRUnichar aChar,CStartToken* aToken, nsTokenAllocator* theAllocator=this->GetTokenAllocator(); while((!done) && (result==NS_OK)) { - CToken* theToken= (CAttributeToken*)theAllocator->CreateTokenOfType(eToken_attribute,eHTMLTag_unknown); + CAttributeToken* theToken= NS_STATIC_CAST(CAttributeToken*, theAllocator->CreateTokenOfType(eToken_attribute,eHTMLTag_unknown)); if(theToken){ - if(aLeadingWS.Length()) { - nsString& theKey=((CAttributeToken*)theToken)->GetKey(); - theKey=aLeadingWS; - aLeadingWS.Truncate(0); - } result=theToken->Consume(aChar,aScanner,PRBool(eViewSource==mParserCommand)); //tell new token to finish consuming text... //Much as I hate to do this, here's some special case code. @@ -575,8 +578,8 @@ nsresult nsHTMLTokenizer::ConsumeAttributes(PRUnichar aChar,CStartToken* aToken, //and a textkey of "/". We should destroy it, and tell the //start token it was empty. if(NS_SUCCEEDED(result)) { - nsString& key=((CAttributeToken*)theToken)->GetKey(); - nsString& text=theToken->GetStringValueXXX(); + const nsAReadableString& key=theToken->GetKey(); + const nsAReadableString& text=theToken->GetValue(); if((mDoXMLEmptyTags) && (kForwardSlash==key.CharAt(0)) && (0==text.Length())){ //tada! our special case! Treat it like an empty start tag... aToken->SetEmpty(PR_TRUE); @@ -584,7 +587,7 @@ nsresult nsHTMLTokenizer::ConsumeAttributes(PRUnichar aChar,CStartToken* aToken, } else { theAttrCount++; - AddToken(theToken,result,&mTokenDeque,theAllocator); + AddToken((CToken*&)theToken,result,&mTokenDeque,theAllocator); } } else { //if(NS_ERROR_HTMLPARSER_BADATTRIBUTE==result){ @@ -654,7 +657,10 @@ nsresult nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar,CToken*& aToken,nsScan aToken=theAllocator->CreateTokenOfType(eToken_start,eHTMLTag_unknown); if(aToken) { - ((CStartToken*)aToken)->mOrigin=aScanner.GetOffset()-1; // Save the position after '<' for use in recording traling contents. Ref: Bug. 15204. + // Save the position after '<' for use in recording traling contents. Ref: Bug. 15204. + nsReadingIterator<PRUnichar> origin; + aScanner.CurrentPosition(origin); + PRBool isHTML=((eHTML3Text==mDocType) || (eHTML4Text==mDocType)); result= aToken->Consume(aChar,aScanner,isHTML); //tell new token to finish consuming text... @@ -665,25 +671,33 @@ nsresult nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar,CToken*& aToken,nsScan //Good. Now, let's see if the next char is ">". //If so, we have a complete tag, otherwise, we have attributes. - nsString &theScratchStr=GetScratchString(); PRBool theTagHasAttributes=PR_FALSE; + nsReadingIterator<PRUnichar> start, end; if(NS_OK==result) { - result=(eViewSource==mParserCommand) ? aScanner.ReadWhitespace(theScratchStr) : aScanner.SkipWhitespace(); + result=(eViewSource==mParserCommand) ? aScanner.ReadWhitespace(start, end) : aScanner.SkipWhitespace(); aToken->mNewlineCount += aScanner.GetNewlinesSkipped(); if(NS_OK==result) { - result=aScanner.GetChar(aChar); + result=aScanner.Peek(aChar); if(NS_OK==result) { if(kGreaterThan!=aChar) { //look for '>' //push that char back, since we apparently have attributes... - result=aScanner.PutBack(aChar); theTagHasAttributes=PR_TRUE; } //if + else { + aScanner.GetChar(aChar); + } } //if }//if } if(theTagHasAttributes) { - result=ConsumeAttributes(aChar,(CStartToken*)aToken,aScanner,theScratchStr); + if (eViewSource==mParserCommand) { + // Since we conserve whitespace in view-source mode, + // go back to the beginning of the whitespace section + // and let the first attribute grab it. + aScanner.SetPosition(start, PR_FALSE, PR_TRUE); + } + result=ConsumeAttributes(aChar,(CStartToken*)aToken,aScanner); } /* Now that that's over with, we have one more problem to solve. @@ -699,7 +713,7 @@ nsresult nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar,CToken*& aToken,nsScan } if(mRecordTrailingContent) - RecordTrailingContent((CStartToken*)aToken,aScanner); + RecordTrailingContent((CStartToken*)aToken,aScanner,origin); //if((eHTMLTag_style==theTag) || (eHTMLTag_script==theTag)) { if(gHTMLElements[theTag].CanContainType(kCDATA)) { @@ -739,6 +753,9 @@ nsresult nsHTMLTokenizer::ConsumeStartTag(PRUnichar aChar,CToken*& aToken,nsScan * @return */ nsresult nsHTMLTokenizer::ConsumeEndTag(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner) { + + // Get the "/" (we've already seen it with a Peek) + aScanner.GetChar(aChar); nsTokenAllocator* theAllocator=this->GetTokenAllocator(); aToken=theAllocator->CreateTokenOfType(eToken_end,eHTMLTag_unknown); @@ -749,7 +766,8 @@ nsresult nsHTMLTokenizer::ConsumeEndTag(PRUnichar aChar,CToken*& aToken,nsScanne if((theTag==eHTMLTag_textarea || theTag==eHTMLTag_xmp) && mRecordTrailingContent) { mRecordTrailingContent=PR_FALSE; } - result= aToken->Consume(aChar,aScanner,mParseMode); //tell new token to finish consuming text... + PRBool isHTML=((eHTML3Text==mDocType) || (eHTML4Text==mDocType)); + result= aToken->Consume(aChar,aScanner,isHTML); //tell new token to finish consuming text... AddToken(aToken,result,&mTokenDeque,theAllocator); } //if return result; @@ -767,39 +785,33 @@ nsresult nsHTMLTokenizer::ConsumeEndTag(PRUnichar aChar,CToken*& aToken,nsScanne */ nsresult nsHTMLTokenizer::ConsumeEntity(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner) { PRUnichar theChar; - nsresult result=aScanner.GetChar(theChar); + nsresult result=aScanner.Peek(theChar, 1); nsTokenAllocator* theAllocator=this->GetTokenAllocator(); if(NS_OK==result) { if(nsCRT::IsAsciiAlpha(theChar)) { //handle common enity references &xxx; or �. + // Get the "&" + aScanner.GetChar(theChar); aToken = theAllocator->CreateTokenOfType(eToken_entity,eHTMLTag_entity); + + // Get the first entity character + aScanner.GetChar(theChar); result = aToken->Consume(theChar,aScanner,mParseMode); //tell new token to finish consuming text... } else if(kHashsign==theChar) { + // Get the "&" + aScanner.GetChar(theChar); aToken = theAllocator->CreateTokenOfType(eToken_entity,eHTMLTag_entity); + + // Get the first numerical entity character + aScanner.GetChar(theChar); result=aToken->Consume(theChar,aScanner,mParseMode); } else { //oops, we're actually looking at plain text... - nsAutoString temp; temp.AssignWithConversion("&"); - aScanner.PutBack(theChar); - return ConsumeText(temp,aToken,aScanner); + return ConsumeText(aToken,aScanner); }//if if(aToken){ -#if 0 - nsString& theStr=aToken->GetStringValueXXX(); - - if((kHashsign!=theChar) && (-1==nsHTMLEntities::EntityToUnicode(theStr))){ - //if you're here we have a bogus entity. - //convert it into a text token. - nsAutoString temp; temp.AssignWithConversion("&"); - temp.Append(theStr); - CToken* theToken=theAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text,temp); - IF_FREE(aToken); - aToken=theToken; - } -#endif - if(mIsFinalChunk && (kEOF==result)) { result=NS_OK; //use as much of the entity as you can get. } @@ -821,6 +833,9 @@ nsresult nsHTMLTokenizer::ConsumeEntity(PRUnichar aChar,CToken*& aToken,nsScanne * @return new token or null */ nsresult nsHTMLTokenizer::ConsumeWhitespace(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner) { + // Get the whitespace character + aScanner.GetChar(aChar); + nsTokenAllocator* theAllocator=this->GetTokenAllocator(); aToken = theAllocator->CreateTokenOfType(eToken_whitespace,eHTMLTag_whitespace); nsresult result=NS_OK; @@ -842,6 +857,9 @@ nsresult nsHTMLTokenizer::ConsumeWhitespace(PRUnichar aChar,CToken*& aToken,nsSc * @return new token or null */ nsresult nsHTMLTokenizer::ConsumeComment(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner){ + // Get the "!" + aScanner.GetChar(aChar); + nsTokenAllocator* theAllocator=this->GetTokenAllocator(); aToken = theAllocator->CreateTokenOfType(eToken_comment,eHTMLTag_comment); nsresult result=NS_OK; @@ -862,21 +880,21 @@ nsresult nsHTMLTokenizer::ConsumeComment(PRUnichar aChar,CToken*& aToken,nsScann * @param anErrorCode: arg that will hold error condition * @return new token or null */ -nsresult nsHTMLTokenizer::ConsumeText(const nsString& aString,CToken*& aToken,nsScanner& aScanner){ +nsresult nsHTMLTokenizer::ConsumeText(CToken*& aToken,nsScanner& aScanner){ nsresult result=NS_OK; nsTokenAllocator* theAllocator=this->GetTokenAllocator(); - aToken=theAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text,aString); - if(aToken) { + CTextToken* theToken = (CTextToken*)theAllocator->CreateTokenOfType(eToken_text,eHTMLTag_text); + if(theToken) { PRUnichar ch=0; - result=aToken->Consume(ch,aScanner,mParseMode); + result=theToken->Consume(ch,aScanner,mParseMode); if(!NS_SUCCEEDED(result)) { - nsString& temp=aToken->GetStringValueXXX(); - if(0==temp.Length()){ + if(0==theToken->GetTextLength()){ IF_FREE(aToken); aToken = nsnull; } else result=NS_OK; } + aToken = theToken; AddToken(aToken,result,&mTokenDeque,theAllocator); } return result; @@ -894,10 +912,13 @@ nsresult nsHTMLTokenizer::ConsumeText(const nsString& aString,CToken*& aToken,ns * @return new token or null */ nsresult nsHTMLTokenizer::ConsumeSpecialMarkup(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner){ + + // Get the "!" + aScanner.GetChar(aChar); + nsresult result=NS_OK; nsAutoString theBufCopy; - nsString& theBuffer=aScanner.GetBuffer(); - theBuffer.Mid(theBufCopy,aScanner.GetOffset(),20); + aScanner.Peek(theBufCopy, 20); theBufCopy.ToUpperCase(); PRInt32 theIndex=theBufCopy.Find("DOCTYPE"); nsTokenAllocator* theAllocator=this->GetTokenAllocator(); @@ -927,6 +948,9 @@ nsresult nsHTMLTokenizer::ConsumeSpecialMarkup(PRUnichar aChar,CToken*& aToken,n * @return error code */ nsresult nsHTMLTokenizer::ConsumeNewline(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner){ + // Get the newline character + aScanner.GetChar(aChar); + nsTokenAllocator* theAllocator=this->GetTokenAllocator(); aToken=theAllocator->CreateTokenOfType(eToken_newline,eHTMLTag_newline); nsresult result=NS_OK; @@ -948,6 +972,10 @@ nsresult nsHTMLTokenizer::ConsumeNewline(PRUnichar aChar,CToken*& aToken,nsScann * @return error code */ nsresult nsHTMLTokenizer::ConsumeProcessingInstruction(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner){ + + // Get the "?" + aScanner.GetChar(aChar); + nsTokenAllocator* theAllocator=this->GetTokenAllocator(); aToken=theAllocator->CreateTokenOfType(eToken_instruction,eHTMLTag_unknown); nsresult result=NS_OK; @@ -969,16 +997,20 @@ nsresult nsHTMLTokenizer::ConsumeProcessingInstruction(PRUnichar aChar,CToken*& * */ -void nsHTMLTokenizer::RecordTrailingContent(CStartToken* aStartToken, nsScanner& aScanner) { +void nsHTMLTokenizer::RecordTrailingContent(CStartToken* aStartToken, nsScanner& aScanner, nsReadingIterator<PRUnichar> aOrigin) { if(aStartToken) { - PRInt32 theOrigin =aStartToken->mOrigin; - PRInt32 theCurrOffset =aScanner.GetOffset(); - PRInt32 theLength =(theCurrOffset>theOrigin)? theCurrOffset-theOrigin:-1; - if(theLength>0) { - nsString& theRawXXX =aStartToken->mTrailingContent; - const PRUnichar* theBuff =(aScanner.GetBuffer()).GetUnicode(); - theRawXXX.Append(&theBuff[theOrigin],theLength); - } + nsReadingIterator<PRUnichar> theCurrentPosition; + aScanner.CurrentPosition(theCurrentPosition); + + nsString& trailingContent =aStartToken->mTrailingContent; + PRUint32 oldLength = trailingContent.Length(); + trailingContent.SetLength(oldLength + Distance(aOrigin, theCurrentPosition)); + + nsWritingIterator<PRUnichar> beginWriting; + trailingContent.BeginWriting(beginWriting); + beginWriting.advance(oldLength); + + copy_string( aOrigin, theCurrentPosition, beginWriting ); } } diff --git a/mozilla/parser/htmlparser/src/nsHTMLTokenizer.h b/mozilla/parser/htmlparser/src/nsHTMLTokenizer.h index 4af4ce9c1d8..a22553eeaa7 100644 --- a/mozilla/parser/htmlparser/src/nsHTMLTokenizer.h +++ b/mozilla/parser/htmlparser/src/nsHTMLTokenizer.h @@ -81,18 +81,18 @@ protected: virtual nsresult ConsumeTag(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner,PRBool& aFlushTokens); virtual nsresult ConsumeStartTag(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner,PRBool& aFlushTokens); virtual nsresult ConsumeEndTag(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner); - virtual nsresult ConsumeAttributes(PRUnichar aChar,CStartToken* aToken,nsScanner& aScanner,nsString& aLeadingWS); + virtual nsresult ConsumeAttributes(PRUnichar aChar,CStartToken* aToken,nsScanner& aScanner); virtual nsresult ConsumeEntity(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner); virtual nsresult ConsumeWhitespace(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner); virtual nsresult ConsumeComment(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner); virtual nsresult ConsumeNewline(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner); - virtual nsresult ConsumeText(const nsString& aString,CToken*& aToken,nsScanner& aScanner); + virtual nsresult ConsumeText(CToken*& aToken,nsScanner& aScanner); virtual nsresult ConsumeSpecialMarkup(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner); virtual nsresult ConsumeProcessingInstruction(PRUnichar aChar,CToken*& aToken,nsScanner& aScanner); nsresult ScanDocStructure(PRBool aIsFinalChunk); - virtual void RecordTrailingContent(CStartToken* aStartToken,nsScanner& aScanner); + virtual void RecordTrailingContent(CStartToken* aStartToken, nsScanner& aScanner, nsReadingIterator<PRUnichar> aOrigin); static void AddToken(CToken*& aToken,nsresult aResult,nsDeque* aDeque,nsTokenAllocator* aTokenAllocator); diff --git a/mozilla/parser/htmlparser/src/nsHTMLTokens.cpp b/mozilla/parser/htmlparser/src/nsHTMLTokens.cpp index 63cbe84738f..61f94a0bdc8 100644 --- a/mozilla/parser/htmlparser/src/nsHTMLTokens.cpp +++ b/mozilla/parser/htmlparser/src/nsHTMLTokens.cpp @@ -32,7 +32,8 @@ #include "nsHTMLTags.h" #include "nsHTMLEntities.h" #include "nsCRT.h" - +#include "nsReadableUtils.h" +#include "nsScanner.h" static const char* gUserdefined = "userdefined"; @@ -42,17 +43,6 @@ static const char* gUserdefined = "userdefined"; And now for the token classes... **************************************************************/ -/* - * default constructor - * - * @update gess 3/25/98 - * @param - * @return - */ -CHTMLToken::CHTMLToken(const nsString& aName,eHTMLTags aTag) : CToken(aName) { - mTypeID=aTag; -} - /* * constructor from tag id * @@ -68,35 +58,6 @@ CHTMLToken::~CHTMLToken() { } -/** - * Setter method that changes the string value of this token - * @update gess5/11/98 - * @param name is a char* value containing new string value - */ -void CHTMLToken::SetCStringValue(const char* name){ - if(name) { - mTextValue.AssignWithConversion(name); - mTypeID = nsHTMLTags::LookupTag(mTextValue); - } -} - - -/** - * This method retrieves the value of this internal string. - * - * @update gess 3/25/98 - * @return nsString reference to internal string value - */ -nsString& CHTMLToken::GetStringValueXXX(void) { - - if((eHTMLTag_unknown<mTypeID) && (mTypeID<eHTMLTag_text)) { - if(!mTextValue.Length()) { - mTextValue.AssignWithConversion(nsHTMLTags::GetStringValue((nsHTMLTag) mTypeID)); - } - } - return mTextValue; -} - /* * constructor from tag id * @@ -111,41 +72,20 @@ CStartToken::CStartToken(eHTMLTags aTag) : CHTMLToken(aTag) { mContainerInfo=eFormUnknown; } -/* - * constructor from tag id - * - * @update gess 3/25/98 - * @param - * @return - */ -CStartToken::CStartToken(const nsString& aString) : CHTMLToken(aString) { +CStartToken::CStartToken(const nsAReadableString& aName) : CHTMLToken(eHTMLTag_unknown) { mAttributed=PR_FALSE; mEmpty=PR_FALSE; mOrigin=-1; mContainerInfo=eFormUnknown; + mTextValue.Assign(aName); } -CStartToken::CStartToken(const nsString& aName,eHTMLTags aTag) : CHTMLToken(aName,aTag) { +CStartToken::CStartToken(const nsAReadableString& aName,eHTMLTags aTag) : CHTMLToken(aTag) { mAttributed=PR_FALSE; mEmpty=PR_FALSE; mOrigin=-1; mContainerInfo=eFormUnknown; -} - -/** - * - * @update gess8/4/98 - * @param - * @return - */ -void CStartToken::Reinitialize(PRInt32 aTag, const nsString& aString){ - CToken::Reinitialize(aTag,aString); - mAttributed=PR_FALSE; - mUseCount=1; - mEmpty=PR_FALSE; - mOrigin=-1; - mTrailingContent.Truncate(); - mContainerInfo=eFormUnknown; + mTextValue.Assign(aName); } nsresult CStartToken::GetIDAttributeAtom(nsIAtom** aResult) @@ -265,17 +205,15 @@ nsresult CStartToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode //NOTE: We don't Consume the tag attributes here, nor do we eat the ">" nsresult result=NS_OK; - if(0==aMode) { - nsSubsumeStr theSubstr; - result=aScanner.GetIdentifier(theSubstr,!aMode); + if(1==aMode) { + nsAutoString theSubstr; + result=aScanner.GetIdentifier(theSubstr,PR_TRUE); mTypeID = (PRInt32)nsHTMLTags::LookupTag(theSubstr); if(eHTMLTag_userdefined==mTypeID) { mTextValue=theSubstr; } } else { - mTextValue.Assign(aChar); - //added PR_TRUE to readId() call below to fix bug 46083. The problem was that the tag given //was written <title_> but since we didn't respect the '_', we only saw <title>. Then //we searched for end title, which never comes (they give </title_>). @@ -303,6 +241,16 @@ void CStartToken::DebugDumpSource(nsOutputStream& out) { out << ">"; } +const nsAReadableString& CStartToken::GetStringValue() +{ + if((eHTMLTag_unknown<mTypeID) && (mTypeID<eHTMLTag_text)) { + if(!mTextValue.Length()) { + mTextValue.AssignWithConversion(nsHTMLTags::GetStringValue((nsHTMLTag) mTypeID)); + } + } + return mTextValue; +} + /* * * @@ -357,18 +305,11 @@ void CStartToken::AppendSource(nsString& anOutputString){ * @return */ CEndToken::CEndToken(eHTMLTags aTag) : CHTMLToken(aTag) { - SetCStringValue(GetTagName(aTag)); } -/* - * default constructor for end token - * - * @update gess 3/25/98 - * @param aName -- char* containing token name - * @return - */ -CEndToken::CEndToken(const nsString& aName) : CHTMLToken(aName) { +CEndToken::CEndToken(const nsAReadableString& aName,eHTMLTags aTag) : CHTMLToken(aTag) { + mTextValue.Assign(aName); } /* @@ -377,6 +318,7 @@ CEndToken::CEndToken(const nsString& aName) : CHTMLToken(aName) { * @update gess 3/25/98 * @param aChar -- last char consumed from stream * @param aScanner -- controller of underlying input source + * @param aMode -- 1=HTML; 0=text (or other ML) * @return error result */ nsresult CEndToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) { @@ -385,15 +327,41 @@ nsresult CEndToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) //Stop consuming as soon as you see a space or a '>'. //NOTE: We don't Consume the tag attributes here, nor do we eat the ">" - mTextValue.SetLength(0); - nsresult result=aScanner.ReadUntil(mTextValue,kGreaterThan,PR_FALSE); + nsresult result=NS_OK; + nsAutoString buffer; + PRInt32 offset; + if(1==aMode) { + nsAutoString theSubstr; + result=aScanner.ReadUntil(theSubstr,kGreaterThan,PR_FALSE); + if (NS_FAILED(result)) { + return result; + } + + offset = theSubstr.FindCharInSet(" \r\n\t\b",0); + if (offset != kNotFound) { + theSubstr.Left(buffer, offset); + mTypeID = nsHTMLTags::LookupTag(buffer); + } + else { + mTypeID = nsHTMLTags::LookupTag(theSubstr); + } + + if(eHTMLTag_userdefined==mTypeID) { + mTextValue=theSubstr; + } - if(NS_OK==result){ - nsAutoString buffer; - mTextValue.Left(buffer, mTextValue.FindCharInSet(" \r\n\t\b",0)); - mTypeID= nsHTMLTags::LookupTag(buffer); - result=aScanner.GetChar(aChar); //eat the closing '>; } + else { + mTextValue.SetLength(0); + result=aScanner.ReadUntil(mTextValue,kGreaterThan,PR_FALSE); + if (NS_FAILED(result)) { + return result; + } + mTypeID = eHTMLTag_userdefined; + } + + result=aScanner.GetChar(aChar); //eat the closing '>; + return result; } @@ -457,6 +425,16 @@ void CEndToken::DebugDumpSource(nsOutputStream& out) { out << "</" << buffer << ">"; } +const nsAReadableString& CEndToken::GetStringValue() +{ + if((eHTMLTag_unknown<mTypeID) && (mTypeID<eHTMLTag_text)) { + if(!mTextValue.Length()) { + mTextValue.AssignWithConversion(nsHTMLTags::GetStringValue((nsHTMLTag) mTypeID)); + } + } + return mTextValue; +} + /* * * @@ -466,7 +444,10 @@ void CEndToken::DebugDumpSource(nsOutputStream& out) { */ void CEndToken::GetSource(nsString& anOutputString){ anOutputString.AppendWithConversion("</"); - anOutputString+=mTextValue; + if(mTextValue.Length()>0) + anOutputString.Append(mTextValue); + else + anOutputString.AppendWithConversion(GetTagName(mTypeID)); anOutputString.AppendWithConversion(">"); } @@ -479,7 +460,10 @@ void CEndToken::GetSource(nsString& anOutputString){ */ void CEndToken::AppendSource(nsString& anOutputString){ anOutputString.AppendWithConversion("</"); - anOutputString+=mTextValue; + if(mTextValue.Length()>0) + anOutputString.Append(mTextValue); + else + anOutputString.AppendWithConversion(GetTagName(mTypeID)); anOutputString.AppendWithConversion(">"); } @@ -501,8 +485,8 @@ CTextToken::CTextToken() : CHTMLToken(eHTMLTag_text) { * @param aName -- string to init token name with * @return */ -CTextToken::CTextToken(const nsString& aName) : CHTMLToken(aName) { - mTypeID=eHTMLTag_text; +CTextToken::CTextToken(const nsAReadableString& aName) : CHTMLToken(eHTMLTag_text) { + mTextValue.Rebind(aName); } /* @@ -527,6 +511,10 @@ PRInt32 CTextToken::GetTokenType(void) { return eToken_text; } +PRInt32 CTextToken::GetTextLength(void) { + return mTextValue.Length(); +} + /* * Consume as much clear text from scanner as possible. * @@ -539,9 +527,17 @@ nsresult CTextToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) static nsString theTerminals = NS_ConvertToString("\n\r&<",4); nsresult result=NS_OK; PRBool done=PR_FALSE; + nsReadingIterator<PRUnichar> origin, start, end; + + // Start scanning after the first character, because we know it to + // be part of this text token (we wouldn't have come here if it weren't) + aScanner.CurrentPosition(origin); + start = origin; + start++; + aScanner.SetPosition(start); while((NS_OK==result) && (!done)) { - result=aScanner.ReadUntil(mTextValue,theTerminals,PR_FALSE); + result=aScanner.ReadUntil(start, end, theTerminals,PR_FALSE); if(NS_OK==result) { result=aScanner.Peek(aChar); @@ -553,31 +549,21 @@ nsresult CTextToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) case kCR: // result=aScanner.GetChar(aChar); if(kLF==theNextChar) { + // If the "\r" is followed by a "\n", don't replace it and + // let it be ignored by the layout system + end += 2; result=aScanner.GetChar(theNextChar); } - else if(kCR==theNextChar) { - result=aScanner.GetChar(theNextChar); - result=aScanner.Peek(theNextChar); //then see what's next. - if(kLF==theNextChar) { - result=aScanner.GetChar(theNextChar); - } - mTextValue.AppendWithConversion("\n"); - mNewlineCount++; + else { + // If it standalone, replace the "\r" with a "\n" so that + // it will be considered by the layout system + aScanner.ReplaceCharacter(end, kLF); + end++; } - mTextValue.AppendWithConversion("\n"); mNewlineCount++; break; case kLF: - if((kLF==theNextChar) || (kCR==theNextChar)) { - result=aScanner.GetChar(theNextChar); - mTextValue.AppendWithConversion("\n"); - mNewlineCount++; - } - mTextValue.AppendWithConversion("\n"); - mNewlineCount++; - break; - default: - mTextValue.AppendWithConversion("\n"); + end++; mNewlineCount++; break; } //switch @@ -585,6 +571,9 @@ nsresult CTextToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) else done=PR_TRUE; } } + + aScanner.BindSubstring(mTextValue, origin, end); + return result; } @@ -599,16 +588,16 @@ nsresult CTextToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScanner& aScanner, nsString& aTerminalString,PRInt32 aMode,PRBool& aFlushTokens){ nsresult result=NS_OK; - PRInt32 theTermStrPos=0;; - nsString& theBuffer=aScanner.GetBuffer(); - PRInt32 theStartOffset=aScanner.GetOffset(); - PRInt32 theCurrOffset=theStartOffset; - PRInt32 theStartCommentPos=kNotFound; - PRInt32 theAltTermStrPos=kNotFound; + nsReadingIterator<PRUnichar> theStartOffset, theCurrOffset, theTermStrPos, theStartCommentPos, theAltTermStrPos, endPos; PRBool done=PR_FALSE; PRBool theLastIteration=PR_FALSE; PRInt32 termStrLen=aTerminalString.Length(); + aScanner.CurrentPosition(theStartOffset); + theCurrOffset = theStartOffset; + aScanner.EndReading(endPos); + theTermStrPos = theStartCommentPos = theAltTermStrPos = endPos; + // ALGORITHM: *** The performance is based on correctness of the document *** // 1. Look for a '<' character. This could be // a) Start of a comment (<!--), b) Start of the terminal string, or c) a start of a tag. @@ -630,74 +619,96 @@ nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScann // When is the disaster enabled? // a) when the buffer runs out ot data. // b) when the terminal string is not found. - PRBool disaster=PR_FALSE; - while(result==NS_OK && !done) { - theCurrOffset=theBuffer.FindChar(kLessThan,PR_TRUE,theCurrOffset); - if(-1<theCurrOffset) { - PRInt32 tempOffset=theCurrOffset; + PRBool disaster = PR_FALSE; + while((result == NS_OK) && !done) { + if (FindCharInReadable(PRUnichar(kLessThan), theCurrOffset, endPos)) { + nsReadingIterator<PRUnichar> tempOffset = theCurrOffset; while(1) { - theTermStrPos=kNotFound; - tempOffset=theBuffer.FindChar(kGreaterThan,PR_TRUE,tempOffset); - if(tempOffset>-1) { - //theTermStrPos=theBuffer.RFind(aTerminalString,PR_TRUE,tempOffset,termStrLen+2); - theTermStrPos=theBuffer.RFind(aTerminalString,PR_TRUE,tempOffset,tempOffset-(theCurrOffset-2)); //bug43513... - if(theTermStrPos>-1) break; - tempOffset++; + if (FindCharInReadable(PRUnichar(kGreaterThan), tempOffset, endPos)) { + + // Make a copy of the (presumed) end tag and + // do a case-insensitive comparision + nsAutoString str; + + nsReadingIterator<PRUnichar> start(tempOffset), end(tempOffset); + start.advance(-termStrLen); + + CopyUnicodeTo(start, end, str); + + if (str.EqualsIgnoreCase(aTerminalString)) { + theTermStrPos = tempOffset; + theTermStrPos.advance(-termStrLen); + break; + } + tempOffset.advance(1); + } + else { + break; } - else break; } - //theTermStrPos=theBuffer.Find(aTerminalString,PR_TRUE,theCurrOffset); - if(theTermStrPos>kNotFound) { - if((aMode!=eDTDMode_strict) && (aMode!=eDTDMode_transitional) && !theLastIteration) { - if(!aIgnoreComments) { - theCurrOffset=theBuffer.Find("<!--",PR_TRUE,theCurrOffset,5); - if(theStartCommentPos==kNotFound && theCurrOffset>kNotFound) { - theStartCommentPos=theCurrOffset; - } - if(theStartCommentPos>kNotFound) { - // Search for --> between <!-- and </TERMINALSTRING>. - theCurrOffset=theBuffer.RFind("-->",PR_TRUE,theTermStrPos,theTermStrPos-theStartCommentPos); - if(theCurrOffset==kNotFound) { - // If you're here it means that we have a bogus terminal string. - theAltTermStrPos=(theAltTermStrPos>-1)? theAltTermStrPos:theTermStrPos; // This could be helpful in case we hit the rock bottom. - theCurrOffset=theTermStrPos+termStrLen; // We did not find '-->' so keep searching for terminal string. - continue; - } - } + + if (theTermStrPos != endPos) { + if((aMode != eDTDMode_strict) && (aMode != eDTDMode_transitional) && + !theLastIteration && !aIgnoreComments) { + nsReadingIterator<PRUnichar> endComment(theCurrOffset); + endComment += 5; + if ((theStartCommentPos == endPos) && + FindInReadable(NS_LITERAL_STRING("<!--"), theCurrOffset, endComment)) { + theStartCommentPos = theCurrOffset; } - PRInt32 thePos=theBuffer.FindChar(kGreaterThan,PR_TRUE,theTermStrPos,20); - if(thePos>kNotFound && thePos>theTermStrPos+termStrLen) { - termStrLen +=(thePos-(theTermStrPos+termStrLen)); + if (theStartCommentPos != endPos) { + // Search for --> between <!-- and </TERMINALSTRING>. + theCurrOffset = theStartCommentPos; + nsReadingIterator<PRUnichar> terminal(theTermStrPos); + if (!RFindInReadable(NS_LITERAL_STRING("-->"), + theCurrOffset, terminal)) { + // If you're here it means that we have a bogus terminal string. + + // Even though it is bogus, the position of the terminal string + // could be helpful in case we hit the rock bottom. + if (theAltTermStrPos != endPos) { + theAltTermStrPos = theTermStrPos; + } + + // We did not find '-->' so keep searching for terminal string. + theCurrOffset = theTermStrPos; + theCurrOffset.advance(termStrLen); + continue; + } } } - + disaster=PR_FALSE; - theCurrOffset=theTermStrPos; - theBuffer.Mid(aTerminalString,theTermStrPos+2,termStrLen-2); - PRUnichar ch=theBuffer.CharAt(theTermStrPos+termStrLen); - theTermStrPos=(ch==kGreaterThan)? theTermStrPos+termStrLen:kNotFound; - if(theTermStrPos>kNotFound) { - theBuffer.Mid(mTextValue,theStartOffset,theCurrOffset-theStartOffset); - aScanner.Mark(theTermStrPos+1); - aFlushTokens=PR_TRUE; // We found </SCRIPT>...permit flushing -> Ref: Bug 22485 - } - done=PR_TRUE; + + aScanner.BindSubstring(mTextValue, theStartOffset, theTermStrPos); + + theTermStrPos.advance(termStrLen+1); + aScanner.SetPosition(theTermStrPos); + + // We found </SCRIPT>...permit flushing -> Ref: Bug 22485 + aFlushTokens=PR_TRUE; + done = PR_TRUE; + } + else { + disaster = PR_TRUE; } - else disaster=PR_TRUE; } - else disaster=PR_TRUE; + else { + disaster = PR_TRUE; + } + if(disaster) { if(!aScanner.IsIncremental()) { - if(theAltTermStrPos>kNotFound) { + if(theAltTermStrPos != endPos) { // If you're here it means..we hit the rock bottom and therefore switch to plan B. - theCurrOffset=theAltTermStrPos; - theLastIteration=PR_TRUE; + theCurrOffset = theAltTermStrPos; + theLastIteration = PR_TRUE; } else { - aTerminalString.Cut(0,2); // Do this to fix Bug. 35456 - done=PR_TRUE; + aTerminalString.Cut(0,2); + done = PR_TRUE; // Do this to fix Bug. 35456 } } else @@ -707,6 +718,26 @@ nsresult CTextToken::ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScann return result; } +void CTextToken::CopyTo(nsAWritableString& aStr) +{ + aStr.Assign(mTextValue); +} + +const nsAReadableString& CTextToken::GetStringValue(void) +{ + return mTextValue; +} + +void CTextToken::Bind(nsScanner* aScanner, nsReadingIterator<PRUnichar>& aStart, nsReadingIterator<PRUnichar>& aEnd) +{ + aScanner->BindSubstring(mTextValue, aStart, aEnd); +} + +void CTextToken::Bind(const nsAReadableString& aStr) +{ + mTextValue.Rebind(aStr); +} + /* * default constructor * @@ -725,8 +756,8 @@ CCDATASectionToken::CCDATASectionToken() : CHTMLToken(eHTMLTag_unknown) { * @param aName -- string to init token name with * @return */ -CCDATASectionToken::CCDATASectionToken(const nsString& aName) : CHTMLToken(aName) { - mTypeID=eHTMLTag_unknown; +CCDATASectionToken::CCDATASectionToken(const nsAReadableString& aName) : CHTMLToken(eHTMLTag_unknown) { + mTextValue.Assign(aName); } /* @@ -806,6 +837,11 @@ nsresult CCDATASectionToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt3 return result; } +const nsAReadableString& CCDATASectionToken::GetStringValue(void) +{ + return mTextValue; +} + /* * Default constructor @@ -825,8 +861,8 @@ CCommentToken::CCommentToken() : CHTMLToken(eHTMLTag_comment) { * @param * @return */ -CCommentToken::CCommentToken(const nsString& aName) : CHTMLToken(aName) { - mTypeID=eHTMLTag_comment; +CCommentToken::CCommentToken(const nsAReadableString& aName) : CHTMLToken(eHTMLTag_comment) { + mTextValue.Assign(aName); } /* @@ -918,11 +954,11 @@ nsresult ConsumeComment(PRUnichar aChar, nsScanner& aScanner,nsString& aString) per spec (But then, neither does IE or Nav). *********************************************************/ - PRInt32 theBestAltPos=kNotFound; - nsString& theBuffer=aScanner.GetBuffer(); - PRInt32 theStartOffset=aScanner.GetOffset(); - PRInt32 theCurrOffset=theStartOffset; + nsReadingIterator<PRUnichar> theStartOffset, theCurrOffset, theBestAltPos, endPos; + aScanner.EndReading(endPos); + theBestAltPos = endPos; + aScanner.CurrentPosition(theStartOffset); result=aScanner.GetChar(aChar); if(NS_OK==result) { if(kMinus==aChar) { @@ -930,22 +966,26 @@ nsresult ConsumeComment(PRUnichar aChar, nsScanner& aScanner,nsString& aString) if(NS_OK==result) { if(kMinus==aChar) { //in this case, we're reading a long-form comment <-- xxx --> - + + theCurrOffset = theStartOffset; + while((NS_OK==result)) { - theCurrOffset=theBuffer.FindChar(kGreaterThan,PR_TRUE,theCurrOffset); - if(kNotFound!=theCurrOffset) { + if (FindCharInReadable(PRUnichar(kGreaterThan), theCurrOffset, endPos)) { theCurrOffset++; - aChar=theBuffer[theCurrOffset-3]; + nsReadingIterator<PRUnichar> temp = theCurrOffset; + temp.advance(-3); + aChar=*temp; if(kMinus==aChar) { - aChar=theBuffer[theCurrOffset-2]; + temp++; + aChar=*temp; if(kMinus==aChar) { - theStartOffset=theStartOffset-2; // Include "<!" also.. - theBuffer.Mid(aString,theStartOffset,theCurrOffset-theStartOffset); - aScanner.Mark(theCurrOffset); + theStartOffset -= 2; // Include "<!" also.. + CopyUnicodeTo(theStartOffset, theCurrOffset, aString); + aScanner.SetPosition(theCurrOffset); return result; // We have found the dflt end comment delimiter ("-->") } } - if(kNotFound==theBestAltPos) { + if(theBestAltPos == endPos) { // If we did not find the dflt then assume that '>' is the end comment // until we find '-->'. Nav. Compatibility -- Ref: Bug# 24006 theBestAltPos=theCurrOffset; @@ -955,16 +995,16 @@ nsresult ConsumeComment(PRUnichar aChar, nsScanner& aScanner,nsString& aString) result=kEOF; } } //while - if((kNotFound==theCurrOffset) && (!aScanner.IsIncremental())) { + if((endPos==theCurrOffset) && (!aScanner.IsIncremental())) { //if you're here, then we're in a special state. //The problem at hand is that we've hit the end of the document without finding the normal endcomment delimiter "-->". //In this case, the first thing we try is to see if we found one of the alternate endcomment delimiter ">". //If so, rewind just pass than, and use everything up to that point as your comment. //If not, the document has no end comment and should be treated as one big comment. - if(kNotFound<theBestAltPos) { - theStartOffset=theStartOffset-2;// Include "<!" also.. - theBuffer.Mid(aString,theStartOffset,theBestAltPos-theStartOffset); - aScanner.Mark(theBestAltPos); + if(endPos != theBestAltPos) { + theStartOffset -= 2;// Include "<!" also.. + CopyUnicodeTo(theStartOffset, theBestAltPos, aString); + aScanner.SetPosition(theBestAltPos); result=NS_OK; } } @@ -1013,6 +1053,10 @@ nsresult CCommentToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMo return result; } +const nsAReadableString& CCommentToken::GetStringValue(void) +{ + return mTextValue; +} /* * @@ -1047,17 +1091,6 @@ CNewlineToken::CNewlineToken() : CHTMLToken(eHTMLTag_newline) { } -/* - * default constructor - * - * @update gess 3/25/98 - * @param aName -- string value to init token name with - * @return - */ -CNewlineToken::CNewlineToken(const nsString& aName) : CHTMLToken(aName) { - mTypeID=eHTMLTag_newline; -} - /* * * @@ -1080,19 +1113,29 @@ PRInt32 CNewlineToken::GetTokenType(void) { return eToken_newline; } + +static nsSlidingSubstring* gNewlineStr; +void CNewlineToken::AllocNewline() +{ + gNewlineStr = new nsSlidingSubstring(NS_LITERAL_STRING("\n")); +} + +void CNewlineToken::FreeNewline() +{ + if (gNewlineStr) { + delete gNewlineStr; + gNewlineStr = nsnull; + } +} + /** * This method retrieves the value of this internal string. * * @update gess 3/25/98 * @return nsString reference to internal string value */ -nsString& CNewlineToken::GetStringValueXXX(void) { - static nsString* theStr=0; - if(!theStr) { - theStr=new nsString; - theStr->AssignWithConversion("\n"); - } - return *theStr; +const nsAReadableString& CNewlineToken::GetStringValue(void) { + return *gNewlineStr; } /* @@ -1105,12 +1148,6 @@ nsString& CNewlineToken::GetStringValueXXX(void) { */ nsresult CNewlineToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMode) { -#if 1 - mTextValue.Assign(kNewLine); //This is what I THINK we should be doing. -#else - mTextValue=aChar; -#endif - /******************************************************************* Here's what the HTML spec says about newlines: @@ -1129,7 +1166,6 @@ nsresult CNewlineToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 aMo case kNewLine: if(kCR==theChar) { result=aScanner.GetChar(theChar); - mTextValue+=theChar; } break; case kCR: @@ -1164,8 +1200,8 @@ CAttributeToken::CAttributeToken() : CHTMLToken(eHTMLTag_unknown) { * @param aName -- string value to init token name with * @return */ -CAttributeToken::CAttributeToken(const nsString& aName) : CHTMLToken(aName), - mTextKey() { +CAttributeToken::CAttributeToken(const nsAReadableString& aName) : CHTMLToken(eHTMLTag_unknown) { + mTextValue.Assign(aName); mLastAttribute=PR_FALSE; mHasEqualWithoutValue=PR_FALSE; } @@ -1178,21 +1214,9 @@ CAttributeToken::CAttributeToken(const nsString& aName) : CHTMLToken(aName), * @param aName -- string value to init token name with * @return */ -CAttributeToken::CAttributeToken(const nsString& aKey, const nsString& aName) : CHTMLToken(aName) { - mTextKey = aKey; - mLastAttribute=PR_FALSE; - mHasEqualWithoutValue=PR_FALSE; -} - -/** - * - * @update gess8/4/98 - * @param - * @return - */ -void CAttributeToken::Reinitialize(PRInt32 aTag, const nsString& aString){ - CHTMLToken::Reinitialize(aTag,aString); - mTextKey.Truncate(); +CAttributeToken::CAttributeToken(const nsAReadableString& aKey, const nsAReadableString& aName) : CHTMLToken(eHTMLTag_unknown) { + mTextValue.Assign(aName); + mTextKey.Rebind(aKey); mLastAttribute=PR_FALSE; mHasEqualWithoutValue=PR_FALSE; } @@ -1229,14 +1253,28 @@ PRInt32 CAttributeToken::GetTokenType(void) { void CAttributeToken::SanitizeKey() { PRInt32 length=mTextKey.Length(); if(length > 0) { - PRUnichar theChar=mTextKey.Last(); - while(!nsCRT::IsAsciiAlpha(theChar) && !nsCRT::IsAsciiDigit(theChar)) { - mTextKey.Truncate(length-1); - length = mTextKey.Length(); - if(length <= 0) break; - theChar = mTextKey.Last(); + nsReadingIterator<PRUnichar> iter, begin, end; + mTextKey.BeginReading(begin); + mTextKey.EndReading(end); + iter = end; + + // Look for the first legal character starting from + // the end of the string + do { + --iter; + } while (!nsCRT::IsAsciiAlpha(*iter) && + !nsCRT::IsAsciiDigit(*iter) && + (iter != begin)); + + // If there were any illegal characters, just copy out the + // legal part + if (iter != --end) { + nsAutoString str; + CopyUnicodeTo(begin, iter, str); + mTextKey.Rebind(str); } } + return; } @@ -1249,11 +1287,17 @@ void CAttributeToken::SanitizeKey() { */ void CAttributeToken::DebugDumpToken(nsOutputStream& out) { char buffer[200]; - mTextKey.ToCString(buffer,sizeof(buffer)); - out << "[" << GetClassName() << "] " << buffer << "="; + nsCAutoString str; + CopyUCS2toASCII(mTextKey, str); + out << "[" << GetClassName() << "] " << str.GetBuffer() << "="; mTextValue.ToCString(buffer,sizeof(buffer)); out << buffer << ": " << mTypeID << nsEndl; } + +const nsAReadableString& CAttributeToken::GetStringValue(void) +{ + return mTextValue; +} /* * @@ -1275,10 +1319,10 @@ void CAttributeToken::GetSource(nsString& anOutputString){ * @return nada */ void CAttributeToken::AppendSource(nsString& anOutputString){ - anOutputString+=mTextKey; + anOutputString.Append(mTextKey); if(mTextValue.Length() || mHasEqualWithoutValue) anOutputString.AppendWithConversion("="); - anOutputString+=mTextValue; + anOutputString.Append(mTextValue); // anOutputString.AppendWithConversion(";"); } @@ -1293,7 +1337,8 @@ void CAttributeToken::AppendSource(nsString& anOutputString){ */ nsresult ConsumeQuotedString(PRUnichar aChar,nsString& aString,nsScanner& aScanner){ nsresult result=NS_OK; - PRInt32 theOffset=aScanner.GetOffset(); + nsReadingIterator<PRUnichar> theOffset; + aScanner.CurrentPosition(theOffset); switch(aChar) { case kQuote: @@ -1316,7 +1361,7 @@ nsresult ConsumeQuotedString(PRUnichar aChar,nsString& aString,nsScanner& aScann PRUnichar ch=aString.Last(); if(ch!=aChar) { if(!aScanner.IsIncremental() && result==kEOF) { - aScanner.Mark(theOffset); + aScanner.SetPosition(theOffset, PR_FALSE, PR_TRUE); aString.Assign(aChar); result=kBadStringLiteral; } @@ -1374,41 +1419,36 @@ nsresult CAttributeToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 a //I changed a bit of this method to use aRetainWhitespace so that we do the right //thing in viewsource. The ws/cr/lf sequences are now maintained, and viewsource looks good. - result=(aRetainWhitespace) ? aScanner.ReadWhitespace(mTextKey) : aScanner.SkipWhitespace(); + nsReadingIterator<PRUnichar> wsstart, wsend; + result=(aRetainWhitespace) ? aScanner.ReadWhitespace(wsstart, wsend) : aScanner.SkipWhitespace(); if(NS_OK==result) { result=aScanner.Peek(aChar); if(NS_OK==result) { - if(kQuote==aChar) { //if you're here, handle quoted key... - result=aScanner.GetChar(aChar); //skip the quote character... - if(NS_OK==result) { - mTextKey.Append(aChar); - result=ConsumeQuotedString(aChar,mTextKey,aScanner); - if(result==kBadStringLiteral) { - // Ref. Bug: 58455 - // If you're here it means that we have searched all the way thro' - // the document for a matching quote and haven't found it. Tell the - // caller that we are done searching and proceed with whatever we have. - result=NS_OK; - } - if(!aRetainWhitespace) - mTextKey.StripChars("\r\n"); //per the HTML spec, ignore linefeeds... - }//if - } - else if((kHashsign==aChar) || (nsCRT::IsAsciiDigit(aChar))){ - result=aScanner.ReadNumber(mTextKey); + nsReadingIterator<PRUnichar> start, end; + if((kHashsign==aChar) || (nsCRT::IsAsciiDigit(aChar))){ + result=aScanner.ReadNumber(start, end); } else { //If you're here, handle an unquoted key. - static nsString theTerminals = NS_ConvertToString("\b\t\n\r \"=>",8); - result=aScanner.ReadUntil(mTextKey,theTerminals,PR_FALSE); + static nsAutoString theTerminals = NS_ConvertToString("\b\t\n\r \"=>",8); + result=aScanner.ReadUntil(start,end,theTerminals,PR_FALSE); + } + if (!aRetainWhitespace) { + aScanner.BindSubstring(mTextKey, start, end); } //now it's time to Consume the (optional) value... if(NS_OK==result) { - result=(aRetainWhitespace) ? aScanner.ReadWhitespace(mTextKey) : aScanner.SkipWhitespace(); + if (aRetainWhitespace) { + aScanner.ReadWhitespace(start, wsend); + aScanner.BindSubstring(mTextKey, wsstart, wsend); + } + else { + aScanner.SkipWhitespace(); + } if(NS_OK==result) { result=aScanner.Peek(aChar); //Skip ahead until you find an equal sign or a '>'... @@ -1420,9 +1460,10 @@ nsresult CAttributeToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 a result=(aRetainWhitespace) ? aScanner.ReadWhitespace(mTextValue) : aScanner.SkipWhitespace(); if(NS_OK==result) { - result=aScanner.GetChar(aChar); //and grab the next char. + result=aScanner.Peek(aChar); //and grab the next char. if(NS_OK==result) { if((kQuote==aChar) || (kApostrophe==aChar)) { + aScanner.GetChar(aChar); mTextValue.Append(aChar); result=ConsumeQuotedString(aChar,mTextValue,aScanner); if(result==kBadStringLiteral) { @@ -1439,11 +1480,11 @@ nsresult CAttributeToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 a } else if(kGreaterThan==aChar){ mHasEqualWithoutValue=PR_TRUE; - result=aScanner.PutBack(aChar); } else if(kAmpersand==aChar) { // XXX - Discard script entity for now....except in // view-source + aScanner.GetChar(aChar); PRBool discard=!aRetainWhitespace; mTextValue.Append(aChar); result=aScanner.GetChar(aChar); @@ -1454,6 +1495,7 @@ nsresult CAttributeToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 a if(discard) mTextValue.Truncate(); } else { + aScanner.GetChar(aChar); mTextValue.Append(aChar); //it's an alphanum attribute... result=ConsumeAttributeValueText(aChar,mTextValue,aScanner); } @@ -1500,8 +1542,9 @@ nsresult CAttributeToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 a */ void CAttributeToken::DebugDumpSource(nsOutputStream& out) { static char buffer[1000]; - mTextKey.ToCString(buffer,sizeof(buffer)); - out << " " << buffer; + nsCAutoString str; + CopyUCS2toASCII(mTextKey, str); + out << " " << str.GetBuffer(); if(mTextValue.Length()){ mTextValue.ToCString(buffer,sizeof(buffer)); out << "=" << buffer; @@ -1510,6 +1553,18 @@ void CAttributeToken::DebugDumpSource(nsOutputStream& out) { out<<">"; } +void CAttributeToken::SetKey(const nsAReadableString& aKey) +{ + mTextKey.Rebind(aKey); +} + +void CAttributeToken::BindKey(nsScanner* aScanner, + nsReadingIterator<PRUnichar>& aStart, + nsReadingIterator<PRUnichar>& aEnd) +{ + aScanner->BindSubstring(mTextKey, aStart, aEnd); +} + /* * default constructor * @@ -1528,8 +1583,8 @@ CWhitespaceToken::CWhitespaceToken() : CHTMLToken(eHTMLTag_whitespace) { * @param aName -- string value to init token name with * @return */ -CWhitespaceToken::CWhitespaceToken(const nsString& aName) : CHTMLToken(aName) { - mTypeID=eHTMLTag_whitespace; +CWhitespaceToken::CWhitespaceToken(const nsAReadableString& aName) : CHTMLToken(eHTMLTag_whitespace) { + mTextValue.Assign(aName); } /* @@ -1572,6 +1627,11 @@ nsresult CWhitespaceToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 return result; } +const nsAReadableString& CWhitespaceToken::GetStringValue(void) +{ + return mTextValue; +} + /* * default constructor * @@ -1589,8 +1649,8 @@ CEntityToken::CEntityToken() : CHTMLToken(eHTMLTag_entity) { * @param aName -- string value to init token name with * @return */ -CEntityToken::CEntityToken(const nsString& aName) : CHTMLToken(aName) { - mTypeID=eHTMLTag_entity; +CEntityToken::CEntityToken(const nsAReadableString& aName) : CHTMLToken(eHTMLTag_entity) { + mTextValue.Assign(aName); #ifdef VERBOSE_DEBUG if(!VerifyEntityTable()) { cout<<"Entity table is invalid!" << endl; @@ -1796,6 +1856,11 @@ void CEntityToken::DebugDumpSource(nsOutputStream& out) { delete[] cp; } +const nsAReadableString& CEntityToken::GetStringValue(void) +{ + return mTextValue; +} + /* * * @@ -1839,7 +1904,8 @@ CScriptToken::CScriptToken() : CHTMLToken(eHTMLTag_script) { * @param aName -- string to init token name with * @return */ -CScriptToken::CScriptToken(const nsString& aString) : CHTMLToken(aString,eHTMLTag_script) { +CScriptToken::CScriptToken(const nsAReadableString& aString) : CHTMLToken(eHTMLTag_script) { + mTextValue.Assign(aString); } @@ -1865,6 +1931,11 @@ PRInt32 CScriptToken::GetTokenType(void) { return eToken_script; } +const nsAReadableString& CScriptToken::GetStringValue(void) +{ + return mTextValue; +} + /* * default constructor * @@ -1875,6 +1946,10 @@ PRInt32 CScriptToken::GetTokenType(void) { CStyleToken::CStyleToken() : CHTMLToken(eHTMLTag_style) { } +CStyleToken::CStyleToken(const nsAReadableString& aString) : CHTMLToken(eHTMLTag_style) { + mTextValue.Assign(aString); +} + /* * * @@ -1897,138 +1972,11 @@ PRInt32 CStyleToken::GetTokenType(void) { return eToken_style; } - -/* - * string based constructor - * - * @update gess 3/25/98 - * @param aName -- string value to init token name with - * @return - */ -CSkippedContentToken::CSkippedContentToken(const nsString& aName) : CAttributeToken(aName) { - mTextKey.AssignWithConversion("$skipped-content");/* XXX need a better answer! */ +const nsAReadableString& CStyleToken::GetStringValue(void) +{ + return mTextValue; } -/* - * - * - * @update gess 3/25/98 - * @param - * @return - */ -const char* CSkippedContentToken::GetClassName(void) { - return "skipped"; -} - -/* - * Retrieve the token type as an int. - * @update gess 3/25/98 - * @return - */ -PRInt32 CSkippedContentToken::GetTokenType(void) { - return eToken_skippedcontent; -} - -/* - * Consume content until you find an end sequence that matches - * this objects current mTextValue. Note that this is complicated - * by the fact that you can be parsing content that itself - * contains quoted content of the same type (like <SCRIPT>). - * That means we have to look for quote-pairs, and ignore the - * content inside them. - * - * @update gess 7/25/98 - * @param aScanner -- controller of underlying input source - * @return error result - */ -nsresult CSkippedContentToken::Consume(PRUnichar aChar,nsScanner& aScanner,PRInt32 aMode) { - PRBool done=PR_FALSE; - nsresult result=NS_OK; - nsString temp; - PRUnichar theChar; - - //We're going to try a new algorithm here. Rather than scan for the matching - //end tag like we used to do, we're now going to scan for whitespace and comments. - //If we find either, just eat them. If we find text or a tag, then go to the - //target endtag, or the start of another comment. - - while((!done) && (NS_OK==result)) { - result=aScanner.GetChar(aChar); - if((NS_OK==result) && (kLessThan==aChar)) { - //we're reading a tag or a comment... - result=aScanner.GetChar(theChar); - if((NS_OK==result) && (kExclamation==theChar)) { - //read a comment... - static CCommentToken theComment; - result=theComment.Consume(aChar,aScanner,aMode); - if(NS_OK==result) { - //result=aScanner.SkipWhitespace(); - temp.Append(theComment.GetStringValueXXX()); - } - } else { - //read a tag... - temp+=aChar; - temp+=theChar; - result=aScanner.ReadUntil(temp,kGreaterThan,PR_TRUE); - } - } - else if(('\b'==theChar) || ('\t'==theChar) || (' '==theChar)) { - static CWhitespaceToken theWS; - result=theWS.Consume(aChar,aScanner,aMode); - if(NS_OK==result) { - temp.Append(theWS.GetStringValueXXX()); - } - } - else { - temp+=aChar; - result=aScanner.ReadUntil(temp,kLessThan,PR_FALSE); - } - nsAutoString theRight; - temp.Right(theRight,mTextValue.Length()); - done=PRBool(0==theRight.CompareWithConversion(mTextValue,PR_TRUE)); - } - int len=temp.Length(); - temp.Truncate(len-mTextValue.Length()); - mTextKey=temp; - return result; -} - -/* - * Dump contents of this token to givne output stream - * - * @update gess 3/25/98 - * @param out -- ostream to output content - * @return - */ -void CSkippedContentToken::DebugDumpSource(nsOutputStream& out) { - static char buffer[1000]; - mTextKey.ToCString(buffer,sizeof(buffer)); - out << " " << buffer; - if(mLastAttribute) - out<<">"; -} - -/* - * - * - * @update gess 3/25/98 - * @param anOutputString will recieve the result - * @return nada - */ -void CSkippedContentToken::GetSource(nsString& anOutputString){ - anOutputString.AppendWithConversion("$skipped-content"); -} - -/* - * - * - * @update harishd 03/23/00 - * @param result appended to the output string. - * @return nada - */ -void CSkippedContentToken::AppendSource(nsString& anOutputString){ - anOutputString.AppendWithConversion("$skipped-content"); -} /** * @@ -2064,7 +2012,8 @@ CInstructionToken::CInstructionToken() : CHTMLToken(eHTMLTag_unknown) { * @param * @return */ -CInstructionToken::CInstructionToken(const nsString& aString) : CHTMLToken(aString) { +CInstructionToken::CInstructionToken(const nsAReadableString& aString) : CHTMLToken(eHTMLTag_unknown) { + mTextValue.Assign(aString); } /** @@ -2102,6 +2051,11 @@ PRInt32 CInstructionToken::GetTokenType(void){ return eToken_instruction; } +const nsAReadableString& CInstructionToken::GetStringValue(void) +{ + return mTextValue; +} + CErrorToken::CErrorToken(nsParserError *aError) : CHTMLToken(eHTMLTag_unknown) { @@ -2130,6 +2084,11 @@ const nsParserError * CErrorToken::GetError(void) return mError; } +const nsAReadableString& CErrorToken::GetStringValue(void) +{ + return mTextValue; +} + // Doctype decl token CDoctypeDeclToken::CDoctypeDeclToken(eHTMLTags aTag) : CHTMLToken(aTag) { @@ -2147,13 +2106,14 @@ nsresult CDoctypeDeclToken::Consume(PRUnichar aChar, nsScanner& aScanner,PRInt32 nsresult result =NS_OK; - nsString& theBuffer=aScanner.GetBuffer(); - PRInt32 theCurrOffset=aScanner.GetOffset(); - PRInt32 thePos=(aScanner.GetBuffer()).FindChar(kLessThan,PR_TRUE,theCurrOffset); + nsReadingIterator<PRUnichar> theCurrOffset, endPos; + aScanner.CurrentPosition(theCurrOffset); + aScanner.EndReading(endPos); + FindCharInReadable(PRUnichar(kLessThan), theCurrOffset, endPos); mTextValue.AssignWithConversion("<!"); - if(thePos>-1) { + if(theCurrOffset != endPos) { result=aScanner.ReadUntil(mTextValue,'<',PR_FALSE); } else { @@ -2169,3 +2129,13 @@ const char* CDoctypeDeclToken::GetClassName(void) { PRInt32 CDoctypeDeclToken::GetTokenType(void) { return eToken_doctypeDecl; } + +const nsAReadableString& CDoctypeDeclToken::GetStringValue(void) +{ + return mTextValue; +} + +void CDoctypeDeclToken::SetStringValue(const nsAReadableString& aStr) +{ + mTextValue.Assign(aStr); +} diff --git a/mozilla/parser/htmlparser/src/nsHTMLTokens.h b/mozilla/parser/htmlparser/src/nsHTMLTokens.h index 228e0c9dcac..73dd88d9a07 100644 --- a/mozilla/parser/htmlparser/src/nsHTMLTokens.h +++ b/mozilla/parser/htmlparser/src/nsHTMLTokens.h @@ -47,6 +47,7 @@ #include "nsHTMLTags.h" #include "nsParserError.h" #include "nsString.h" +#include "nsSlidingString.h" class nsScanner; @@ -99,9 +100,6 @@ public: virtual ~CHTMLToken(); CHTMLToken(eHTMLTags aTag); - CHTMLToken(const nsString& aString,eHTMLTags aTag=eHTMLTag_unknown); - virtual void SetCStringValue(const char* name); - virtual nsString& GetStringValueXXX(void); virtual eContainerInfo GetContainerInfo(void) const {return eFormUnknown;} virtual void SetContainerInfo(eContainerInfo aInfo) { } @@ -118,8 +116,8 @@ protected: class CStartToken: public CHTMLToken { public: CStartToken(eHTMLTags aTag=eHTMLTag_unknown); - CStartToken(const nsString& aString); - CStartToken(const nsString& aName,eHTMLTags aTag); + CStartToken(const nsAReadableString& aString); + CStartToken(const nsAReadableString& aName,eHTMLTags aTag); virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,PRInt32 aMode); virtual PRInt32 GetTypeID(void); @@ -131,6 +129,7 @@ class CStartToken: public CHTMLToken { PRBool IsEmpty(void); void SetEmpty(PRBool aValue); virtual void DebugDumpSource(nsOutputStream& out); + virtual const nsAReadableString& GetStringValue(); virtual void GetSource(nsString& anOutputString); virtual void AppendSource(nsString& anOutputString); @@ -139,7 +138,6 @@ class CStartToken: public CHTMLToken { virtual void SetContainerInfo(eContainerInfo aContainerInfo) {mContainerInfo=aContainerInfo;} virtual PRBool IsWellFormed(void) const {return PRBool(eWellFormed==mContainerInfo);} - virtual void Reinitialize(PRInt32 aTag, const nsString& aString); /* * Get and set the ID attribute atom for this element. @@ -150,6 +148,7 @@ class CStartToken: public CHTMLToken { virtual nsresult GetIDAttributeAtom(nsIAtom** aResult); virtual nsresult SetIDAttributeAtom(nsIAtom* aID); + nsString mTextValue; nsString mTrailingContent; PRInt32 mOrigin; protected: @@ -171,14 +170,19 @@ class CStartToken: public CHTMLToken { class CEndToken: public CHTMLToken { public: CEndToken(eHTMLTags aTag); - CEndToken(const nsString& aString); + CEndToken(const nsAReadableString& aString); + CEndToken(const nsAReadableString& aName,eHTMLTags aTag); virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,PRInt32 aMode); virtual PRInt32 GetTypeID(void); virtual const char* GetClassName(void); virtual PRInt32 GetTokenType(void); virtual void DebugDumpSource(nsOutputStream& out); + virtual const nsAReadableString& GetStringValue(); virtual void GetSource(nsString& anOutputString); virtual void AppendSource(nsString& anOutputString); + + protected: + nsString mTextValue; }; @@ -193,11 +197,15 @@ class CEndToken: public CHTMLToken { class CCommentToken: public CHTMLToken { public: CCommentToken(); - CCommentToken(const nsString& aString); + CCommentToken(const nsAReadableString& aString); virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,PRInt32 aMode); virtual const char* GetClassName(void); virtual PRInt32 GetTokenType(void); + virtual const nsAReadableString& GetStringValue(void); char mLeadingChar; + + protected: + nsString mTextValue; }; @@ -211,7 +219,7 @@ class CCommentToken: public CHTMLToken { class CEntityToken : public CHTMLToken { public: CEntityToken(); - CEntityToken(const nsString& aString); + CEntityToken(const nsAReadableString& aString); virtual const char* GetClassName(void); virtual PRInt32 GetTokenType(void); PRInt32 TranslateToUnicodeStr(nsString& aString); @@ -219,8 +227,12 @@ class CEntityToken : public CHTMLToken { static PRInt32 ConsumeEntity(PRUnichar aChar,nsString& aString,nsScanner& aScanner); static PRInt32 TranslateToUnicodeStr(PRInt32 aValue,nsString& aString); virtual void DebugDumpSource(nsOutputStream& out); + virtual const nsAReadableString& GetStringValue(void); virtual void GetSource(nsString& anOutputString); virtual void AppendSource(nsString& anOutputString); + + protected: + nsString mTextValue; }; @@ -234,10 +246,14 @@ class CEntityToken : public CHTMLToken { class CWhitespaceToken: public CHTMLToken { public: CWhitespaceToken(); - CWhitespaceToken(const nsString& aString); + CWhitespaceToken(const nsAReadableString& aString); virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,PRInt32 aMode); virtual const char* GetClassName(void); virtual PRInt32 GetTokenType(void); + virtual const nsAReadableString& GetStringValue(void); + + protected: + nsString mTextValue; }; /** @@ -250,12 +266,20 @@ class CWhitespaceToken: public CHTMLToken { class CTextToken: public CHTMLToken { public: CTextToken(); - CTextToken(const nsString& aString); + CTextToken(const nsAReadableString& aString); virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,PRInt32 aMode); nsresult ConsumeUntil(PRUnichar aChar,PRBool aIgnoreComments,nsScanner& aScanner, nsString& aTerminalString,PRInt32 aMode,PRBool& aFlushTokens); virtual const char* GetClassName(void); virtual PRInt32 GetTokenType(void); + virtual PRInt32 GetTextLength(void); + virtual void CopyTo(nsAWritableString& aStr); + virtual const nsAReadableString& GetStringValue(void); + virtual void Bind(nsScanner* aScanner, nsReadingIterator<PRUnichar>& aStart, nsReadingIterator<PRUnichar>& aEnd); + virtual void Bind(const nsAReadableString& aStr); + + protected: + nsSlidingSubstring mTextValue; }; @@ -269,10 +293,14 @@ class CTextToken: public CHTMLToken { class CCDATASectionToken : public CHTMLToken { public: CCDATASectionToken(); - CCDATASectionToken(const nsString& aString); + CCDATASectionToken(const nsAReadableString& aString); virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,PRInt32 aMode); virtual const char* GetClassName(void); virtual PRInt32 GetTokenType(void); + virtual const nsAReadableString& GetStringValue(void); + + protected: + nsString mTextValue; }; @@ -288,23 +316,28 @@ public: class CAttributeToken: public CHTMLToken { public: CAttributeToken(); - CAttributeToken(const nsString& aString); - CAttributeToken(const nsString& aKey, const nsString& aString); - ~CAttributeToken() { mTextKey.SetCapacity(0);} + CAttributeToken(const nsAReadableString& aString); + CAttributeToken(const nsAReadableString& aKey, const nsAReadableString& aString); + ~CAttributeToken() {} virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,PRInt32 aMode); virtual const char* GetClassName(void); virtual PRInt32 GetTokenType(void); - virtual nsString& GetKey(void) {return mTextKey;} + virtual const nsAReadableString& GetKey(void) {return mTextKey;} + virtual void SetKey(const nsAReadableString& aKey); + virtual void BindKey(nsScanner* aScanner, nsReadingIterator<PRUnichar>& aStart, nsReadingIterator<PRUnichar>& aEnd); + virtual const nsString& GetValue(void) {return mTextValue;} virtual void SanitizeKey(); virtual void DebugDumpToken(nsOutputStream& out); + virtual const nsAReadableString& GetStringValue(void); virtual void GetSource(nsString& anOutputString); virtual void AppendSource(nsString& anOutputString); virtual void DebugDumpSource(nsOutputStream& out); PRBool mLastAttribute; - virtual void Reinitialize(PRInt32 aTag, const nsString& aString); PRBool mHasEqualWithoutValue; - nsString mTextKey; + protected: + nsAutoString mTextValue; + nsSlidingSubstring mTextKey; }; @@ -317,11 +350,13 @@ class CAttributeToken: public CHTMLToken { class CNewlineToken: public CHTMLToken { public: CNewlineToken(); - CNewlineToken(const nsString& aString); virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,PRInt32 aMode); virtual const char* GetClassName(void); virtual PRInt32 GetTokenType(void); - virtual nsString& GetStringValueXXX(void); + virtual const nsAReadableString& GetStringValue(void); + + static void AllocNewline(); + static void FreeNewline(); }; @@ -337,10 +372,13 @@ class CNewlineToken: public CHTMLToken { class CScriptToken: public CHTMLToken { public: CScriptToken(); - CScriptToken(const nsString& aString); + CScriptToken(const nsAReadableString& aString); virtual const char* GetClassName(void); virtual PRInt32 GetTokenType(void); + virtual const nsAReadableString& GetStringValue(void); + protected: + nsString mTextValue; }; @@ -355,29 +393,13 @@ class CScriptToken: public CHTMLToken { class CStyleToken: public CHTMLToken { public: CStyleToken(); - CStyleToken(const nsString& aString); + CStyleToken(const nsAReadableString& aString); virtual const char* GetClassName(void); virtual PRInt32 GetTokenType(void); - protected: -}; + virtual const nsAReadableString& GetStringValue(void); - -/** - * This is a placeholder token, which is being deprecated. - * Don't bother paying attention to this. - * - * @update gess 3/25/98 - */ -class CSkippedContentToken: public CAttributeToken { - public: - CSkippedContentToken(const nsString& aString); - virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,PRInt32 aMode); - virtual const char* GetClassName(void); - virtual PRInt32 GetTokenType(void); - virtual void DebugDumpSource(nsOutputStream& out); - virtual void GetSource(nsString& anOutputString); - virtual void AppendSource(nsString& anOutputString); protected: + nsString mTextValue; }; @@ -391,10 +413,14 @@ class CSkippedContentToken: public CAttributeToken { class CInstructionToken: public CHTMLToken { public: CInstructionToken(); - CInstructionToken(const nsString& aString); + CInstructionToken(const nsAReadableString& aString); virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,PRInt32 aMode); virtual const char* GetClassName(void); virtual PRInt32 GetTokenType(void); + virtual const nsAReadableString& GetStringValue(void); + + protected: + nsString mTextValue; }; class CErrorToken : public CHTMLToken { @@ -411,7 +437,9 @@ public: // of nsParserError is returned which needs to be destroyed by the consumer? const nsParserError* GetError(void); + virtual const nsAReadableString& GetStringValue(void); protected: + nsString mTextValue; nsParserError* mError; }; @@ -427,6 +455,11 @@ public: virtual nsresult Consume(PRUnichar aChar,nsScanner& aScanner,PRInt32 aMode); virtual const char* GetClassName(void); virtual PRInt32 GetTokenType(void); + virtual const nsAReadableString& GetStringValue(void); + virtual void SetStringValue(const nsAReadableString& aStr); + + protected: + nsString mTextValue; }; #endif diff --git a/mozilla/parser/htmlparser/src/nsIElementObserver.h b/mozilla/parser/htmlparser/src/nsIElementObserver.h index b047970f60c..d308a05e416 100644 --- a/mozilla/parser/htmlparser/src/nsIElementObserver.h +++ b/mozilla/parser/htmlparser/src/nsIElementObserver.h @@ -32,7 +32,7 @@ #include "nsISupports.h" #include "prtypes.h" -#include "nsHTMLTokens.h" +#include "nsHTMLTags.h" #include "nsDeque.h" diff --git a/mozilla/parser/htmlparser/src/nsIParserFilter.h b/mozilla/parser/htmlparser/src/nsIParserFilter.h index 80ee6f82a01..c9704c88197 100644 --- a/mozilla/parser/htmlparser/src/nsIParserFilter.h +++ b/mozilla/parser/htmlparser/src/nsIParserFilter.h @@ -47,7 +47,7 @@ class nsIParserFilter : public nsISupports { NS_DEFINE_STATIC_IID_ACCESSOR(NS_IPARSERFILTER_IID) - NS_IMETHOD RawBuffer(char * buffer, PRUint32 * buffer_length) = 0; + NS_IMETHOD RawBuffer(const char * buffer, PRUint32 * buffer_length) = 0; NS_IMETHOD WillAddToken(CToken & token) = 0; diff --git a/mozilla/parser/htmlparser/src/nsIParserNode.h b/mozilla/parser/htmlparser/src/nsIParserNode.h index d129adb5095..8fe06fe980b 100644 --- a/mozilla/parser/htmlparser/src/nsIParserNode.h +++ b/mozilla/parser/htmlparser/src/nsIParserNode.h @@ -78,7 +78,7 @@ class nsIParserNode : public nsISupports { * @update gess5/11/98 * @return string containing node text */ - virtual const nsString& GetText() const =0; //get plain text if available + virtual const nsAReadableString& GetText() const =0; //get plain text if available /** * Retrieve skipped context from node @@ -114,7 +114,7 @@ class nsIParserNode : public nsISupports { * @param anIndex is the index of the key you want * @return string containing key. */ - virtual const nsString& GetKeyAt(PRUint32 anIndex) const =0; + virtual const nsAReadableString& GetKeyAt(PRUint32 anIndex) const =0; /** * Retrieve the value (of key/value pair) at given index diff --git a/mozilla/parser/htmlparser/src/nsLoggingSink.cpp b/mozilla/parser/htmlparser/src/nsLoggingSink.cpp index 26800df6941..4d2f58f65ab 100644 --- a/mozilla/parser/htmlparser/src/nsLoggingSink.cpp +++ b/mozilla/parser/htmlparser/src/nsLoggingSink.cpp @@ -92,10 +92,10 @@ nsLoggingSink::nsLoggingSink() nsLoggingSink::~nsLoggingSink() { - if (0 != mOutput) { - mOutput->flush(); - mOutput = 0; - } + //if (0 != mOutput) { + //mOutput->flush(); + // mOutput = 0; + //} } NS_IMPL_ADDREF(nsLoggingSink) @@ -269,11 +269,14 @@ nsLoggingSink::AddComment(const nsIParserNode& aNode){ NS_IMETHODIMP nsLoggingSink::SetTitle(const nsString& aValue) { - nsAutoString tmp; - QuoteText(aValue, tmp); + char* tmp; + GetNewCString(aValue, &tmp); WriteTabs(*mOutput,++mLevel); - (*mOutput) << "<title value=\"" << tmp << "\"/>" << endl; - --mLevel; + if(tmp) { + (*mOutput) << "<title value=\"" << tmp << "\"/>" << endl; + nsMemory::Free(tmp); + } + --mLevel; return NS_OK; } @@ -364,8 +367,8 @@ nsLoggingSink::OpenNode(const char* aKind, const nsIParserNode& aNode) (*mOutput) << "\"" << tag << "\""; } else { - const nsString& text = aNode.GetText(); - (*mOutput) << "\"" << text << " \""; + const nsAReadableString& text = aNode.GetText(); + (*mOutput) << "\"" << NS_ConvertUCS2toUTF8(text) << " \""; } if (WillWriteAttributes(aNode)) { @@ -392,31 +395,43 @@ nsLoggingSink::CloseNode(const char* aKind) nsresult nsLoggingSink::WriteAttributes(const nsIParserNode& aNode) { - nsAutoString tmp, tmp2; + WriteTabs(*mOutput,mLevel); + nsAutoString tmp; PRInt32 ac = aNode.GetAttributeCount(); for (PRInt32 i = 0; i < ac; i++) { - const nsString& k = aNode.GetKeyAt(i); + char* key=nsnull; + char* value=nsnull; + const nsAutoString k(aNode.GetKeyAt(i)); const nsString& v = aNode.GetValueAt(i); - (*mOutput) << " <attr key=\"" << k << "\" value=\""; + GetNewCString(k, &key); + if(key) { + (*mOutput) << " <attr key=\"" << key << "\" value=\""; + nsMemory::Free(key); + } tmp.Truncate(); tmp.Append(v); - PRUnichar first = tmp.First(); - if ((first == '"') || (first == '\'')) { - if (tmp.Last() == first) { - tmp.Cut(0, 1); - PRInt32 pos = tmp.Length() - 1; - if (pos >= 0) { - tmp.Cut(pos, 1); + if(tmp.Length() > 0) { + PRUnichar first = tmp.First(); + if ((first == '"') || (first == '\'')) { + if (tmp.Last() == first) { + tmp.Cut(0, 1); + PRInt32 pos = tmp.Length() - 1; + if (pos >= 0) { + tmp.Cut(pos, 1); + } + } else { + // Mismatched quotes - leave them in } - } else { - // Mismatched quotes - leave them in + } + GetNewCString(tmp, &value); + + if(value) { + (*mOutput) << value << "\"/>" << endl; + nsMemory::Free(value); } } - QuoteText(tmp, tmp2); - - (*mOutput) << tmp2 << "\"/>" << endl; } if (0 != strchr(gSkippedContentTags, aNode.GetNodeType())) { @@ -473,11 +488,15 @@ nsLoggingSink::LeafNode(const nsIParserNode& aNode) else { PRInt32 pos; nsAutoString tmp; + char* str; switch (nodeType) { case eHTMLTag_whitespace: case eHTMLTag_text: - QuoteText(aNode.GetText(), tmp); - (*mOutput) << "<text value=\"" << tmp << "\"/>" << endl; + GetNewCString(aNode.GetText(), &str); + if(str) { + (*mOutput) << "<text value=\"" << str << "\"/>" << endl; + nsMemory::Free(str); + } break; case eHTMLTag_newline: @@ -502,10 +521,10 @@ nsLoggingSink::LeafNode(const nsIParserNode& aNode) } nsresult -nsLoggingSink::QuoteText(const nsString& aValue, nsString& aResult) +nsLoggingSink::QuoteText(const nsAReadableString& aValue, nsString& aResult) { aResult.Truncate(); - const PRUnichar* cp = aValue.GetUnicode(); + const PRUnichar* cp = nsPromiseFlatString(aValue); const PRUnichar* end = cp + aValue.Length(); while (cp < end) { PRUnichar ch = *cp++; @@ -527,6 +546,29 @@ nsLoggingSink::QuoteText(const nsString& aValue, nsString& aResult) return NS_OK; } +/** + * Use this method to convert nsString to char*. + * REMEMBER: Match this call with nsMemory::Free(aResult); + * + * @update 04/04/99 harishd + * @param aValue - The string value + * @param aResult - String coverted to char*. + */ +nsresult +nsLoggingSink::GetNewCString(const nsAReadableString& aValue, char** aResult) +{ + nsresult result=NS_OK; + nsAutoString temp; + result=QuoteText(aValue,temp); + if(NS_SUCCEEDED(result)) { + if(temp.Length()>0) { + *aResult=temp.ToNewCString(); + } + } + return result; +} + + NS_IMETHODIMP nsLoggingSink::DoFragment(PRBool aFlag) { diff --git a/mozilla/parser/htmlparser/src/nsLoggingSink.h b/mozilla/parser/htmlparser/src/nsLoggingSink.h index 84bdb74bd56..e4224db3d69 100644 --- a/mozilla/parser/htmlparser/src/nsLoggingSink.h +++ b/mozilla/parser/htmlparser/src/nsLoggingSink.h @@ -75,7 +75,8 @@ public: nsresult CloseNode(const char* aKind); nsresult LeafNode(const nsIParserNode& aNode); nsresult WriteAttributes(const nsIParserNode& aNode); - nsresult QuoteText(const nsString& aValue, nsString& aResult); + nsresult QuoteText(const nsAReadableString& aValue, nsString& aResult); + nsresult GetNewCString(const nsAReadableString& aValue, char** aResult); PRBool WillWriteAttributes(const nsIParserNode& aNode); protected: diff --git a/mozilla/parser/htmlparser/src/nsParser.cpp b/mozilla/parser/htmlparser/src/nsParser.cpp index 7cb349ed20d..b546197e202 100644 --- a/mozilla/parser/htmlparser/src/nsParser.cpp +++ b/mozilla/parser/htmlparser/src/nsParser.cpp @@ -42,7 +42,6 @@ #include "nsIChannel.h" #include "nsIProgressEventSink.h" #include "nsIInputStream.h" -#include "CRtfDTD.h" #include "CNavDTD.h" #include "COtherDTD.h" #include "prenv.h" @@ -59,7 +58,6 @@ static NS_DEFINE_CID(kWellFormedDTDCID, NS_WELLFORMEDDTD_CID); static NS_DEFINE_CID(kNavDTDCID, NS_CNAVDTD_CID); static NS_DEFINE_CID(kCOtherDTDCID, NS_COTHER_DTD_CID); static NS_DEFINE_CID(kViewSourceDTDCID, NS_VIEWSOURCE_DTD_CID); -static NS_DEFINE_CID(kRtfDTDCID, NS_CRTF_DTD_CID); static const char* kNullURL = "Error: Null URL given"; static const char* kOnStartNotCalled = "Error: OnStartRequest() must be called before OnDataAvailable()"; @@ -117,7 +115,7 @@ public: mDTDDeque.Push(theDTD); mHasViewSourceDTD=PR_FALSE; - mHasRTFDTD=mHasXMLDTD=PR_FALSE; + mHasXMLDTD=PR_FALSE; } ~CSharedParserObjects() { @@ -141,7 +139,6 @@ public: nsDeque mDTDDeque; PRBool mHasViewSourceDTD; //this allows us to defer construction of this object. PRBool mHasXMLDTD; //also defer XML dtd construction - PRBool mHasRTFDTD; //also defer RTF dtd construction nsIDTD *mOtherDTD; //it's ok to leak this; the deque contains a copy too. }; @@ -677,11 +674,6 @@ void DetermineParseMode(nsString& aBuffer,nsDTDMode& aParseMode,eParserDocType& aParseMode=eDTDMode_quirks; return; } - else if(aMimeType.EqualsWithConversion(kRTFTextContentType)) { - aDocType=ePlainText; - aParseMode=eDTDMode_quirks; - return; - } else if(aMimeType.EqualsWithConversion(kTextCSSContentType)) { aDocType=ePlainText; aParseMode=eDTDMode_quirks; @@ -1024,10 +1016,6 @@ void DetermineParseMode2(nsString& aBuffer,nsDTDMode& aParseMode,eParserDocType& aDocType=ePlainText; aParseMode=eDTDMode_quirks; } - else if(aMimeType.EqualsWithConversion(kRTFTextContentType)) { - aDocType=ePlainText; - aParseMode=eDTDMode_quirks; - } if(theModeStr) { if(0==nsCRT::strcasecmp(theModeStr,"strict")) @@ -1094,11 +1082,6 @@ PRBool FindSuitableDTD( CParserContext& aParserContext,nsString& aBuffer) { gSharedObjects.mDTDDeque.Push(theDTD); gSharedObjects.mHasViewSourceDTD=PR_TRUE; } - else if(!gSharedObjects.mHasRTFDTD) { - NS_NewRTF_DTD(&theDTD); //do this so all non-html files can be viewed... - gSharedObjects.mDTDDeque.Push(theDTD); - gSharedObjects.mHasRTFDTD=PR_TRUE; - } } } @@ -1220,9 +1203,6 @@ NS_IMETHODIMP nsParser::CreateCompatibleDTD(nsIDTD** aDTD, aMimeType->EqualsWithConversion(kRDFTextContentType)) { theDTDClassID=&kWellFormedDTDCID; } - else if(aMimeType->EqualsWithConversion(kXIFTextContentType)) { - theDTDClassID=&kRtfDTDCID; - } else { theDTDClassID=&kNavDTDCID; } @@ -1406,7 +1386,10 @@ nsresult nsParser::WillBuildModel(nsString& aFilename){ mMajorIteration=-1; mMinorIteration=-1; - nsString& theBuffer=mParserContext->mScanner->GetBuffer(); + nsAutoString theBuffer; + // XXXVidur Make a copy and only check in the first 1k + mParserContext->mScanner->Peek(theBuffer, 1024); + DetermineParseMode(theBuffer,mParserContext->mDTDMode,mParserContext->mDocType,mParserContext->mMimeType); if(PR_TRUE==FindSuitableDTD(*mParserContext,theBuffer)) { @@ -2240,6 +2223,61 @@ static PRBool detectByteOrderMark(const unsigned char* aBytes, PRInt32 aLen, nsS return oCharset.Length() > 0; } +typedef struct { + PRBool mNeedCheckFirst4Bytes; + nsParser* mParser; + nsIParserFilter* mParserFilter; + nsScanner* mScanner; +} ParserWriteStruct; + +/* + * This function is invoked as a result of a call to a stream's + * ReadSegments() method. It is called for each contiguous buffer + * of data in the underlying stream or pipe. Using ReadSegments + * allows us to avoid copying data to read out of the stream. + */ +static NS_METHOD +ParserWriteFunc(nsIInputStream* in, + void* closure, + const char* fromRawSegment, + PRUint32 toOffset, + PRUint32 count, + PRUint32 *writeCount) +{ + nsresult result; + ParserWriteStruct* pws = NS_STATIC_CAST(ParserWriteStruct*, closure); + const char* buf = fromRawSegment; + PRUint32 theNumRead = count; + + if (!pws) { + return NS_ERROR_FAILURE; + } + + if(pws->mNeedCheckFirst4Bytes && (count >= 4)) { + nsCharsetSource guessSource; + nsAutoString guess; + + pws->mNeedCheckFirst4Bytes = PR_FALSE; + if(detectByteOrderMark((const unsigned char*)buf, + theNumRead, guess, guessSource)) + { +#ifdef DEBUG_XMLENCODING + printf("xmlencoding detect- %s\n", guess.ToNewCString()); +#endif + pws->mParser->SetDocumentCharset(guess, guessSource); + } + } + + if(pws->mParserFilter) + pws->mParserFilter->RawBuffer(buf, &theNumRead); + + result = pws->mScanner->Append(buf, theNumRead); + if (NS_SUCCEEDED(result)) { + *writeCount = count; + } + + return result; +} /** * @@ -2273,90 +2311,27 @@ NS_PRECONDITION(((eOnStart==mParserContext->mStreamListenerState)||(eOnDataAvail if(eInvalidDetect==theContext->mAutoDetectStatus) { if(theContext->mScanner) { - theContext->mScanner->GetBuffer().Truncate(); + nsReadingIterator<PRUnichar> iter; + theContext->mScanner->EndReading(iter); + theContext->mScanner->SetPosition(iter, PR_TRUE); } } - PRInt32 newLength=(aLength>theContext->mTransferBufferSize) ? aLength : -theContext->mTransferBufferSize; - if(!theContext->mTransferBuffer) { - theContext->mTransferBufferSize=newLength; - theContext->mTransferBuffer=new char[newLength+20]; - } - else if(aLength>theContext->mTransferBufferSize){ - delete [] theContext->mTransferBuffer; - theContext->mTransferBufferSize=newLength; - theContext->mTransferBuffer=new char[newLength+20]; - } - - if(theContext->mTransferBuffer) { - - //We need to add code to defensively deal with the case where the transfer buffer is null. - - PRUint32 theTotalRead=0; - PRUint32 theNumRead=1; //init to a non-zero value - int theStartPos=0; - - PRBool needCheckFirst4Bytes = + PRUint32 totalRead; + ParserWriteStruct pws; + pws.mNeedCheckFirst4Bytes = ((0 == sourceOffset) && (mCharsetSource<kCharsetFromAutoDetection)); - while ((theNumRead>0) && (aLength>theTotalRead) && (NS_OK==result)) { - result = pIStream->Read(theContext->mTransferBuffer, aLength, &theNumRead); - if(NS_SUCCEEDED(result) && (theNumRead>0)) { - if(needCheckFirst4Bytes && (theNumRead >= 4)) { - nsCharsetSource guessSource; - nsAutoString guess; - - needCheckFirst4Bytes = PR_FALSE; - if(detectByteOrderMark((const unsigned char*)theContext->mTransferBuffer, - theNumRead, guess, guessSource)) - { - #ifdef DEBUG_XMLENCODING - printf("xmlencoding detect- %s\n", guess.ToNewCString()); - #endif - this->SetDocumentCharset(guess, guessSource); - } - } - theTotalRead+=theNumRead; - if(mParserFilter) - mParserFilter->RawBuffer(theContext->mTransferBuffer, &theNumRead); + pws.mParser = this; + pws.mParserFilter = mParserFilter; + pws.mScanner = theContext->mScanner; - #ifdef rickgdebug - unsigned int index=0; - for(index=0;index<theNumRead;index++) { - if(0==theContext->mTransferBuffer[index]){ - printf("\nNull found at buffer[%i] provided by netlib...\n",index); - break; - } - } - #endif + result = pIStream->ReadSegments(ParserWriteFunc, (void*)&pws, aLength, &totalRead); + if (NS_FAILED(result)) { + return result; + } -#if 1 - static int dump=0; - if(dump) { - theContext->mTransferBuffer[theNumRead]=0; - printf("\n\n-----------------------------------------------------%s\n",theContext->mTransferBuffer); - } -#endif - - - theContext->mScanner->Append(theContext->mTransferBuffer,theNumRead); - - - #ifdef rickgdebug - theContext->mTransferBuffer[theNumRead]=0; - theContext->mTransferBuffer[theNumRead+1]=0; - theContext->mTransferBuffer[theNumRead+2]=0; - cout << theContext->mTransferBuffer; - #endif - - } //if - theStartPos+=theNumRead; - }//while - - result=ResumeParse(); - } //if - - } //if + result=ResumeParse(); + } return result; } diff --git a/mozilla/parser/htmlparser/src/nsParserModule.cpp b/mozilla/parser/htmlparser/src/nsParserModule.cpp index 0437a40572c..9a2939a40f1 100644 --- a/mozilla/parser/htmlparser/src/nsParserModule.cpp +++ b/mozilla/parser/htmlparser/src/nsParserModule.cpp @@ -32,9 +32,7 @@ #include "nsWellFormedDTD.h" #include "CNavDTD.h" #include "COtherDTD.h" -#include "nsXIFDTD.h" #include "COtherDTD.h" -#include "CRtfDTD.h" #include "nsViewSourceHTML.h" #include "nsHTMLContentSinkStream.h" #include "nsHTMLToTXTSinkStream.h" @@ -142,11 +140,9 @@ static NS_DEFINE_CID(kParserNodeCID, NS_PARSER_NODE_IID); static NS_DEFINE_CID(kLoggingSinkCID, NS_LOGGING_SINK_CID); static NS_DEFINE_CID(kWellFormedDTDCID, NS_WELLFORMEDDTD_CID); static NS_DEFINE_CID(kNavDTDCID, NS_CNAVDTD_CID); -static NS_DEFINE_CID(kXIFDTDCID, NS_XIF_DTD_CID); static NS_DEFINE_CID(kCOtherDTDCID, NS_COTHER_DTD_CID); static NS_DEFINE_CID(kCTransitionalDTDCID, NS_CTRANSITIONAL_DTD_CID); static NS_DEFINE_CID(kViewSourceDTDCID, NS_VIEWSOURCE_DTD_CID); -static NS_DEFINE_CID(kRtfDTDCID, NS_CRTF_DTD_CID); static NS_DEFINE_CID(kHTMLContentSinkStreamCID, NS_HTMLCONTENTSINKSTREAM_CID); static NS_DEFINE_CID(kHTMLToTXTSinkStreamCID, NS_HTMLTOTXTSINKSTREAM_CID); static NS_DEFINE_CID(kParserServiceCID, NS_PARSERSERVICE_CID); @@ -162,11 +158,9 @@ static Components gComponents[] = { { "Logging sink", &kLoggingSinkCID }, { "Well formed DTD", &kWellFormedDTDCID }, { "Navigator HTML DTD", &kNavDTDCID }, - { "XIF DTD", &kXIFDTDCID }, { "OTHER DTD", &kCOtherDTDCID }, { "Transitional DTD", &kCTransitionalDTDCID }, { "ViewSource DTD", &kViewSourceDTDCID }, - { "Rtf DTD", &kRtfDTDCID }, { "HTML Content Sink Stream", &kHTMLContentSinkStreamCID }, { "HTML To Text Sink Stream", &kHTMLToTXTSinkStreamCID }, { "ParserService", &kParserServiceCID }, @@ -179,11 +173,9 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsCParserNode) NS_GENERIC_FACTORY_CONSTRUCTOR(nsLoggingSink) NS_GENERIC_FACTORY_CONSTRUCTOR(CWellFormedDTD) NS_GENERIC_FACTORY_CONSTRUCTOR(CNavDTD) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsXIFDTD) NS_GENERIC_FACTORY_CONSTRUCTOR(COtherDTD) NS_GENERIC_FACTORY_CONSTRUCTOR(CTransitionalDTD) NS_GENERIC_FACTORY_CONSTRUCTOR(CViewSourceHTML) -NS_GENERIC_FACTORY_CONSTRUCTOR(CRtfDTD) NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLContentSinkStream) NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLToTXTSinkStream) NS_GENERIC_FACTORY_CONSTRUCTOR(nsParserService) @@ -210,11 +202,9 @@ protected: nsCOMPtr<nsIGenericFactory> mLoggingSinkFactory; nsCOMPtr<nsIGenericFactory> mWellFormedDTDFactory; nsCOMPtr<nsIGenericFactory> mNavHTMLDTDFactory; - nsCOMPtr<nsIGenericFactory> mXIFDTDFactory; nsCOMPtr<nsIGenericFactory> mOtherHTMLDTDFactory; nsCOMPtr<nsIGenericFactory> mTransitionalHTMLDTDFactory; nsCOMPtr<nsIGenericFactory> mViewSourceHTMLDTDFactory; - nsCOMPtr<nsIGenericFactory> mRtfHTMLDTDFactory; nsCOMPtr<nsIGenericFactory> mHTMLContentSinkStreamFactory; nsCOMPtr<nsIGenericFactory> mHTMLToTXTSinkStreamFactory; nsCOMPtr<nsIGenericFactory> mParserServiceFactory; @@ -242,6 +232,8 @@ nsParserModule::Initialize() nsHTMLTags::AddRefTable(); nsHTMLEntities::AddRefTable(); mInitialized = PR_TRUE; + InitializeElementTable(); + CNewlineToken::AllocNewline(); } return NS_OK; } @@ -255,8 +247,8 @@ nsParserModule::Shutdown() nsDTDContext::ReleaseGlobalObjects(); nsParser::FreeSharedObjects(); mInitialized = PR_FALSE; - COtherDTD::ReleaseTable(); - CNavDTD::ReleaseTable(); + DeleteElementTable(); + CNewlineToken::FreeNewline(); } } @@ -313,13 +305,6 @@ nsParserModule::GetClassObject(nsIComponentManager *aCompMgr, } fact = mNavHTMLDTDFactory; } - else if (aClass.Equals(kXIFDTDCID)) { - if (!mXIFDTDFactory) { - rv = NS_NewGenericFactory(getter_AddRefs(mXIFDTDFactory), - &nsXIFDTDConstructor); - } - fact = mXIFDTDFactory; - } else if (aClass.Equals(kCOtherDTDCID)) { if (!mOtherHTMLDTDFactory) { rv = NS_NewGenericFactory(getter_AddRefs(mOtherHTMLDTDFactory), @@ -341,13 +326,6 @@ nsParserModule::GetClassObject(nsIComponentManager *aCompMgr, } fact = mViewSourceHTMLDTDFactory; } - else if (aClass.Equals(kRtfDTDCID)) { - if (!mRtfHTMLDTDFactory) { - rv = NS_NewGenericFactory(getter_AddRefs(mRtfHTMLDTDFactory), - &CRtfDTDConstructor); - } - fact = mRtfHTMLDTDFactory; - } else if (aClass.Equals(kHTMLContentSinkStreamCID)) { if (!mHTMLContentSinkStreamFactory) { rv = NS_NewGenericFactory(getter_AddRefs(mHTMLContentSinkStreamFactory), diff --git a/mozilla/parser/htmlparser/src/nsParserNode.cpp b/mozilla/parser/htmlparser/src/nsParserNode.cpp index 777ba4b42f2..75838d0e3db 100644 --- a/mozilla/parser/htmlparser/src/nsParserNode.cpp +++ b/mozilla/parser/htmlparser/src/nsParserNode.cpp @@ -186,8 +186,8 @@ const nsString& nsCParserNode::GetName() const { * @param * @return string ref of text from internal token */ -const nsString& nsCParserNode::GetText() const { - return (mToken) ? mToken->GetStringValueXXX() : GetEmptyString(); +const nsAReadableString& nsCParserNode::GetText() const { + return (mToken) ? mToken->GetStringValue() : GetEmptyString(); } /** @@ -272,7 +272,7 @@ PRInt32 nsCParserNode::GetAttributeCount(PRBool askToken) const{ * @param anIndex-- offset of attribute to retrieve * @return string rep of given attribute text key */ -const nsString& nsCParserNode::GetKeyAt(PRUint32 anIndex) const { +const nsAReadableString& nsCParserNode::GetKeyAt(PRUint32 anIndex) const { PRInt32 theCount = (mAttributes) ? mAttributes->GetSize() : 0; if((PRInt32)anIndex<theCount) { CAttributeToken* tkn=(CAttributeToken*)mAttributes->ObjectAt(anIndex); @@ -296,7 +296,7 @@ const nsString& nsCParserNode::GetValueAt(PRUint32 anIndex) const { if(PRInt32(anIndex)<theCount) { CAttributeToken* tkn=(CAttributeToken*)mAttributes->ObjectAt(anIndex); - return tkn->GetStringValueXXX(); + return tkn->GetValue(); } return GetEmptyString(); } @@ -373,6 +373,7 @@ nsresult nsCParserNode::ReleaseAll() { //fixed a bug that patrick found, where the attributes deque existed //but was empty. In that case, the attributes deque itself was leaked. //THANKS PATRICK! + // Umm...why is this a useful comment in the source? if(mTokenAllocator) { RecycleTokens(mTokenAllocator,*mAttributes); diff --git a/mozilla/parser/htmlparser/src/nsParserNode.h b/mozilla/parser/htmlparser/src/nsParserNode.h index e9266b9765f..540da833188 100644 --- a/mozilla/parser/htmlparser/src/nsParserNode.h +++ b/mozilla/parser/htmlparser/src/nsParserNode.h @@ -85,7 +85,7 @@ class nsCParserNode : public nsIParserNode { * @update gess5/11/98 * @return string containing node text */ - virtual const nsString& GetText() const; + virtual const nsAReadableString& GetText() const; /** * Retrieve skipped context from node @@ -133,7 +133,7 @@ class nsCParserNode : public nsIParserNode { * @param anIndex is the index of the key you want * @return string containing key. */ - virtual const nsString& GetKeyAt(PRUint32 anIndex) const; + virtual const nsAReadableString& GetKeyAt(PRUint32 anIndex) const; /** * Retrieve the value (of key/value pair) at given index @@ -202,7 +202,7 @@ class nsCParserNode : public nsIParserNode { * @return void */ virtual nsresult ReleaseAll(); - + PRInt32 mLineNumber; CToken* mToken; nsDeque* mAttributes; diff --git a/mozilla/parser/htmlparser/src/nsScanner.cpp b/mozilla/parser/htmlparser/src/nsScanner.cpp index 8ffce4ff81b..0fcd1c29eb6 100644 --- a/mozilla/parser/htmlparser/src/nsScanner.cpp +++ b/mozilla/parser/htmlparser/src/nsScanner.cpp @@ -29,6 +29,34 @@ #include "nsICharsetConverterManager.h" #include "nsICharsetAlias.h" #include "nsFileSpec.h" +#include "nsReadableUtils.h" + +nsScannerString::nsScannerString(PRUnichar* aStorageStart, + PRUnichar* aDataEnd, + PRUnichar* aStorageEnd) : nsSlidingString(aStorageStart, aDataEnd, aStorageEnd) +{ +} + +void +nsScannerString::InsertBuffer(PRUnichar* aStorageStart, + PRUnichar* aDataEnd, + PRUnichar* aStorageEnd) +{ + // XXX This is where insertion of a buffer at the head + // of the buffer list will take place pending checkins + // from scc. +} + +void +nsScannerString::ReplaceCharacter(nsReadingIterator<PRUnichar>& aPosition, + PRUnichar aChar) +{ + // XXX Casting a const to non-const. Unless the base class + // provides support for writing iterators, this is the best + // that can be done. + PRUnichar* pos = (PRUnichar*)aPosition.get(); + *pos = aChar; +} static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID); @@ -52,16 +80,19 @@ MOZ_DECL_CTOR_COUNTER(nsScanner); * @param aMode represents the parser mode (nav, other) * @return */ -nsScanner::nsScanner(nsString& anHTMLString, const nsString& aCharset, nsCharsetSource aSource) : - mBuffer(anHTMLString) +nsScanner::nsScanner(nsString& anHTMLString, const nsString& aCharset, nsCharsetSource aSource) { MOZ_COUNT_CTOR(nsScanner); - mTotalRead=mBuffer.Length(); + PRUnichar* buffer = anHTMLString.ToNewUnicode(); + mTotalRead = anHTMLString.Length(); + mSlidingBuffer = nsnull; + mCountRemaining = 0; + AppendToBuffer(buffer, buffer+mTotalRead, buffer+mTotalRead); + mSlidingBuffer->BeginReading(mCurrentPosition); + mMarkPosition = mCurrentPosition; mIncremental=PR_FALSE; mOwnsStream=PR_FALSE; - mOffset=0; - mMarkPos=0; mInputStream=0; mUnicodeDecoder = 0; mCharsetSource = kCharsetUninitialized; @@ -83,9 +114,9 @@ nsScanner::nsScanner(nsString& aFilename,PRBool aCreateStream, const nsString& a { MOZ_COUNT_CTOR(nsScanner); + mSlidingBuffer = nsnull; mIncremental=PR_TRUE; - mOffset=0; - mMarkPos=0; + mCountRemaining = 0; mTotalRead=0; mOwnsStream=aCreateStream; mInputStream=0; @@ -112,9 +143,9 @@ nsScanner::nsScanner(nsString& aFilename,nsInputStream& aStream,const nsString& { MOZ_COUNT_CTOR(nsScanner); + mSlidingBuffer = nsnull; mIncremental=PR_FALSE; - mOffset=0; - mMarkPos=0; + mCountRemaining = 0; mTotalRead=0; mOwnsStream=PR_FALSE; mInputStream=&aStream; @@ -179,7 +210,11 @@ nsresult nsScanner::SetDocumentCharset(const nsString& aCharset , nsCharsetSourc * @return */ nsScanner::~nsScanner() { - + + if (mSlidingBuffer) { + delete mSlidingBuffer; + } + MOZ_COUNT_DTOR(nsScanner); if(mInputStream) { @@ -201,9 +236,9 @@ nsScanner::~nsScanner() { * @param * @return */ -PRUint32 nsScanner::RewindToMark(void){ - mOffset=mMarkPos; - return mOffset; +void nsScanner::RewindToMark(void){ + mCountRemaining += (Distance(mMarkPosition, mCurrentPosition)); + mCurrentPosition = mMarkPosition; } @@ -216,16 +251,11 @@ PRUint32 nsScanner::RewindToMark(void){ * @param * @return */ -PRUint32 nsScanner::Mark(PRInt32 anIndex){ - if(kNotFound==anIndex) { - if((mOffset>0) && (mOffset>eBufferSizeThreshold)) { - mBuffer.Cut(0,mOffset); //delete chars up to mark position - mOffset=0; - } - mMarkPos=mOffset; +void nsScanner::Mark() { + if (mSlidingBuffer) { + mMarkPosition = mCurrentPosition; + mSlidingBuffer->DiscardPrefix(mMarkPosition); } - else mOffset=(PRUint32)anIndex; - return 0; } @@ -237,9 +267,9 @@ PRUint32 nsScanner::Mark(PRInt32 anIndex){ * @return error code */ PRBool nsScanner::Insert(const nsAReadableString& aBuffer) { - - mBuffer.Insert(aBuffer,mOffset); - mTotalRead+=aBuffer.Length(); + // XXX This is where insertion of a buffer at the head + // of the buffer list will take place pending checkins + // from scc. return PR_TRUE; } @@ -251,16 +281,12 @@ PRBool nsScanner::Insert(const nsAReadableString& aBuffer) { * @return error code */ PRBool nsScanner::Append(const nsAReadableString& aBuffer) { + + PRUnichar* buffer = ToNewUnicode(aBuffer); + PRUint32 bufLen = aBuffer.Length(); + mTotalRead += bufLen; - PRUint32 theLen=mBuffer.Length(); - - mBuffer.Append(aBuffer); - mTotalRead+=aBuffer.Length(); - if(theLen<mBuffer.Length()) { - - //Now yank any nulls that were embedded in this given buffer - mBuffer.StripChar(0,theLen); - } + AppendToBuffer(buffer, buffer+bufLen, buffer+bufLen); return PR_TRUE; } @@ -273,31 +299,35 @@ PRBool nsScanner::Append(const nsAReadableString& aBuffer) { * @return */ PRBool nsScanner::Append(const char* aBuffer, PRUint32 aLen){ - - PRUint32 theLen=mBuffer.Length(); - + PRUnichar* unichars; if(mUnicodeDecoder) { - PRInt32 unicharBufLen = 0; - mUnicodeDecoder->GetMaxLength(aBuffer, aLen, &unicharBufLen); - mUnicodeXferBuf.SetCapacity(unicharBufLen+32); - mUnicodeXferBuf.Truncate(); - PRUnichar *unichars = (PRUnichar*)mUnicodeXferBuf.GetUnicode(); - + nsresult res; do { + PRInt32 unicharBufLen = 0; + mUnicodeDecoder->GetMaxLength(aBuffer, aLen, &unicharBufLen); + unichars = (PRUnichar*)nsMemory::Alloc((unicharBufLen+1) * sizeof(PRUnichar)); + if (!unichars) { + return PR_FALSE; + } + PRInt32 srcLength = aLen; PRInt32 unicharLength = unicharBufLen; res = mUnicodeDecoder->Convert(aBuffer, &srcLength, unichars, &unicharLength); - unichars[unicharLength]=0; //add this since the unicode converters can't be trusted to do so. - mBuffer.Append(unichars, unicharLength); + // if we failed, we consume one byte, replace it with U+FFFD + // and try the conversion again. + if(NS_FAILED(res)) { + unichars[unicharLength++] = (PRUnichar)0xFFFD; + } + + AppendToBuffer(unichars, unichars+unicharLength, + unichars+unicharBufLen); mTotalRead += unicharLength; - // if we failed, we consume one byte by replace it with U+FFFD - // and try conversion again. + + // Continuation of failure case if(NS_FAILED(res)) { mUnicodeDecoder->Reset(); - mBuffer.Append( (PRUnichar)0xFFFD); - mTotalRead++; if(((PRUint32) (srcLength + 1)) > aLen) srcLength = aLen; else @@ -306,52 +336,18 @@ PRBool nsScanner::Append(const char* aBuffer, PRUint32 aLen){ aLen -= srcLength; } } while (NS_FAILED(res) && (aLen > 0)); - // we continue convert the bytes data into Unicode - // if we have conversion error and we have more data. - - // delete[] unichars; } else { - mBuffer.AppendWithConversion(aBuffer,aLen); + nsLiteralCString str(aBuffer, aLen); + unichars = ToNewUnicode(str); + AppendToBuffer(unichars, unichars+aLen, unichars+aLen); mTotalRead+=aLen; - - } - - if(theLen<mBuffer.Length()) { - //Now yank any nulls that were embedded in this given buffer - mBuffer.StripChar(0,theLen); } return PR_TRUE; } -/** - * Append PRUNichar* data to the internal buffer of the scanner - * - * @update gess4/3/98 - * @return error code (it's always true) - */ -PRBool nsScanner::Append(const PRUnichar* aBuffer, PRUint32 aLen){ - - if(-1==(PRInt32)aLen) - aLen=nsCRT::strlen(aBuffer); - - CBufDescriptor theDesc(aBuffer,PR_TRUE, aLen+1,aLen); - nsAutoString theBuffer(theDesc); - - PRUint32 theLen=mBuffer.Length(); - mBuffer.Append(theBuffer); - mTotalRead+=aLen; - - if(theLen<mBuffer.Length()) { - //Now yank any nulls that were embedded in this given buffer - mBuffer.StripChar(0,theLen); - } - - return PR_TRUE; -} - /** * Grab data from underlying stream. * @@ -378,21 +374,24 @@ nsresult nsScanner::FillBuffer(void) { } else { PRInt32 numread=0; - char buf[kBufsize+1]; + char* buf = new char[kBufsize+1]; buf[kBufsize]=0; if(mInputStream) { numread = mInputStream->read(buf, kBufsize); if (0 == numread) { + delete [] buf; return kEOF; } } - mOffset=mBuffer.Length(); + if((0<numread) && (0==result)) { - mBuffer.AppendWithConversion((const char*)buf,numread); - mBuffer.StripChar(0); //yank the nulls that come in from the net. + nsLiteralCString str(buf, numread); + PRUnichar* unichars = ToNewUnicode(str); + AppendToBuffer(unichars, unichars+numread, unichars+kBufsize+1); } - mTotalRead+=mBuffer.Length(); + delete [] buf; + mTotalRead+=numread; } return result; @@ -407,13 +406,17 @@ nsresult nsScanner::FillBuffer(void) { */ nsresult nsScanner::Eof() { nsresult theError=NS_OK; + + if (!mSlidingBuffer) { + return kEOF; + } - if(mOffset>=(PRUint32)mBuffer.Length()) { + if (mCurrentPosition == mEndPosition) { theError=FillBuffer(); } - + if(NS_OK==theError) { - if (0==(PRUint32)mBuffer.Length()) { + if (0==(PRUint32)mSlidingBuffer->Length()) { return kEOF; } } @@ -431,11 +434,18 @@ nsresult nsScanner::Eof() { nsresult nsScanner::GetChar(PRUnichar& aChar) { nsresult result=NS_OK; aChar=0; - if(mOffset>=(PRUint32)mBuffer.Length()) + + if (!mSlidingBuffer) { + return kEOF; + } + + if (mCurrentPosition == mEndPosition) { result=Eof(); + } if(NS_OK == result){ - aChar=GetCharAt(mBuffer,mOffset++); + aChar=*mCurrentPosition++; + mCountRemaining--; } return result; } @@ -449,31 +459,61 @@ nsresult nsScanner::GetChar(PRUnichar& aChar) { * @param * @return */ -nsresult nsScanner::Peek(PRUnichar& aChar) { +nsresult nsScanner::Peek(PRUnichar& aChar, PRUint32 aOffset) { nsresult result=NS_OK; aChar=0; - if(mOffset>=(PRUint32)mBuffer.Length()) + + if (!mSlidingBuffer) { + return kEOF; + } + + if (mCurrentPosition == mEndPosition) { result=Eof(); + } if(NS_OK == result){ - aChar=GetCharAt(mBuffer,mOffset); + if (aOffset) { + if (mCountRemaining < aOffset) { + result = Eof(); + } + else { + nsReadingIterator<PRUnichar> pos = mCurrentPosition; + pos.advance(aOffset); + aChar=*pos; + } + } + else { + aChar=*mCurrentPosition; + } } return result; } +nsresult nsScanner::Peek(nsAWritableString& aStr, PRInt32 aNumChars) +{ + if (!mSlidingBuffer) { + return kEOF; + } + + if (mCurrentPosition == mEndPosition) { + return Eof(); + } + + nsReadingIterator<PRUnichar> start, end; + + start = mCurrentPosition; + + if (mCountRemaining < PRUint32(aNumChars)) { + end = mEndPosition; + } + else { + end = start; + end.advance(aNumChars); + } + + CopyUnicodeTo(start, end, aStr); -/** - * Push the given char back onto the scanner - * - * @update gess 3/25/98 - * @param - * @return error code - */ -nsresult nsScanner::PutBack(PRUnichar aChar) { - if(mOffset>0) - mOffset--; - else mBuffer.Insert(aChar,0); return NS_OK; } @@ -487,41 +527,44 @@ nsresult nsScanner::PutBack(PRUnichar aChar) { */ nsresult nsScanner::SkipWhitespace(void) { + if (!mSlidingBuffer) { + return kEOF; + } + PRUnichar theChar=0; nsresult result=Peek(theChar); - const PRUnichar* theBuf=mBuffer.GetUnicode(); - PRInt32 theOrigin=mOffset; + nsReadingIterator<PRUnichar> current, end; PRBool found=PR_FALSE; mNewlinesSkipped = 0; + current = mCurrentPosition; + end = mEndPosition; - while(NS_OK==result) { - - theChar=theBuf[mOffset++]; - if(theChar) { - switch(theChar) { - case '\n': mNewlinesSkipped++; - case ' ' : - case '\r': - case '\b': - case '\t': - found=PR_TRUE; - break; - default: - found=PR_FALSE; - break; - } - if(!found) { - mOffset-=1; + while(current != end) { + theChar=*current; + switch(theChar) { + case '\n': mNewlinesSkipped++; + case ' ' : + case '\r': + case '\b': + case '\t': + found=PR_TRUE; + break; + default: + found=PR_FALSE; break; - } } - else if ((PRUint32)mBuffer.Length()<=mOffset) { - mOffset-=1; - result=Peek(theChar); - theBuf=mBuffer.GetUnicode(); - theOrigin=mOffset; + if(!found) { + break; } + else { + current++; + } + } + + SetPosition(current); + if (current == end) { + return Eof(); } //DoErrTest(aString); @@ -539,16 +582,20 @@ nsresult nsScanner::SkipWhitespace(void) { */ nsresult nsScanner::SkipOver(PRUnichar aSkipChar){ + if (!mSlidingBuffer) { + return kEOF; + } + PRUnichar ch=0; nsresult result=NS_OK; while(NS_OK==result) { - result=GetChar(ch); + result=Peek(ch); if(NS_OK == result) { if(ch!=aSkipChar) { - PutBack(ch); break; } + GetChar(ch); } else break; } //while @@ -565,17 +612,21 @@ nsresult nsScanner::SkipOver(PRUnichar aSkipChar){ */ nsresult nsScanner::SkipOver(nsString& aSkipSet){ + if (!mSlidingBuffer) { + return kEOF; + } + PRUnichar theChar=0; nsresult result=NS_OK; while(NS_OK==result) { - result=GetChar(theChar); + result=Peek(theChar); if(NS_OK == result) { PRInt32 pos=aSkipSet.FindChar(theChar); if(kNotFound==pos) { - PutBack(theChar); break; } + GetChar(theChar); } else break; } //while @@ -593,17 +644,21 @@ nsresult nsScanner::SkipOver(nsString& aSkipSet){ * @return error code */ nsresult nsScanner::SkipTo(nsString& aValidSet){ + if (!mSlidingBuffer) { + return kEOF; + } + PRUnichar ch=0; nsresult result=NS_OK; while(NS_OK==result) { - result=GetChar(ch); + result=Peek(ch); if(NS_OK == result) { PRInt32 pos=aValidSet.FindChar(ch); if(kNotFound!=pos) { - PutBack(ch); break; } + GetChar(ch); } else break; } //while @@ -649,17 +704,23 @@ nsresult nsScanner::SkipPast(nsString& aValidSet){ * @param aIgnore - If set ignores ':','-','_' * @return error code */ -nsresult nsScanner::GetIdentifier(nsSubsumeStr& aString,PRBool allowPunct) { +nsresult nsScanner::GetIdentifier(nsString& aString,PRBool allowPunct) { + + if (!mSlidingBuffer) { + return kEOF; + } PRUnichar theChar=0; nsresult result=Peek(theChar); - const PRUnichar* theBuf=mBuffer.GetUnicode(); - PRInt32 theOrigin=mOffset; + nsReadingIterator<PRUnichar> current, end; PRBool found=PR_FALSE; + + current = mCurrentPosition; + end = mEndPosition; - while(NS_OK==result) { + while(current != end) { - theChar=theBuf[mOffset++]; + theChar=*current; if(theChar) { found=PR_FALSE; switch(theChar) { @@ -679,14 +740,22 @@ nsresult nsScanner::GetIdentifier(nsSubsumeStr& aString,PRBool allowPunct) { } if(!found) { - mOffset-=1; - PRUnichar* thePtr=(PRUnichar*)&theBuf[theOrigin-1]; - aString.Subsume(thePtr,PR_FALSE,mOffset-theOrigin+1); + // If we the current character isn't a valid character for + // the identifier, we're done. Copy the results into + // the string passed in. + CopyUnicodeTo(mCurrentPosition, current, aString); break; } + + current++; } } + SetPosition(current); + if (current == end) { + result = Eof(); + } + //DoErrTest(aString); return result; @@ -702,15 +771,22 @@ nsresult nsScanner::GetIdentifier(nsSubsumeStr& aString,PRBool allowPunct) { */ nsresult nsScanner::ReadIdentifier(nsString& aString,PRBool allowPunct) { + if (!mSlidingBuffer) { + return kEOF; + } + PRUnichar theChar=0; nsresult result=Peek(theChar); - const PRUnichar* theBuf=mBuffer.GetUnicode(); - PRInt32 theOrigin=mOffset; + nsReadingIterator<PRUnichar> origin, current, end; PRBool found=PR_FALSE; - while(NS_OK==result) { + origin = mCurrentPosition; + current = mCurrentPosition; + end = mEndPosition; + + while(current != end) { - theChar=theBuf[mOffset++]; + theChar=*current; if(theChar) { found=PR_FALSE; switch(theChar) { @@ -730,19 +806,79 @@ nsresult nsScanner::ReadIdentifier(nsString& aString,PRBool allowPunct) { } if(!found) { - mOffset-=1; - aString.Append(&theBuf[theOrigin],mOffset-theOrigin); + AppendUnicodeTo(mCurrentPosition, current, aString); break; } + + current++; } - else if ((PRUint32)mBuffer.Length()<=mOffset) { - mOffset -= 1; - aString.Append(&theBuf[theOrigin],mOffset-theOrigin); - result=Peek(theChar); - theBuf=mBuffer.GetUnicode(); - theOrigin=mOffset; + } + + SetPosition(current); + if (current == end) { + AppendUnicodeTo(origin, current, aString); + return Eof(); + } + + //DoErrTest(aString); + + return result; +} + +nsresult nsScanner::ReadIdentifier(nsReadingIterator<PRUnichar>& aStart, + nsReadingIterator<PRUnichar>& aEnd, + PRBool allowPunct) { + + if (!mSlidingBuffer) { + return kEOF; + } + + PRUnichar theChar=0; + nsresult result=Peek(theChar); + nsReadingIterator<PRUnichar> origin, current, end; + PRBool found=PR_FALSE; + + origin = mCurrentPosition; + current = mCurrentPosition; + end = mEndPosition; + + while(current != end) { + + theChar=*current; + if(theChar) { + found=PR_FALSE; + switch(theChar) { + case ':': + case '_': + case '-': + found=allowPunct; + break; + default: + if(('a'<=theChar) && (theChar<='z')) + found=PR_TRUE; + else if(('A'<=theChar) && (theChar<='Z')) + found=PR_TRUE; + else if(('0'<=theChar) && (theChar<='9')) + found=PR_TRUE; + break; + } + + if(!found) { + aStart = mCurrentPosition; + aEnd = current; + break; + } + + current++; } } + + SetPosition(current); + if (current == end) { + aStart = origin; + aEnd = current; + return Eof(); + } //DoErrTest(aString); @@ -759,15 +895,22 @@ nsresult nsScanner::ReadIdentifier(nsString& aString,PRBool allowPunct) { */ nsresult nsScanner::ReadNumber(nsString& aString) { + if (!mSlidingBuffer) { + return kEOF; + } + PRUnichar theChar=0; nsresult result=Peek(theChar); - const PRUnichar* theBuf=mBuffer.GetUnicode(); - PRInt32 theOrigin=mOffset; + nsReadingIterator<PRUnichar> origin, current, end; PRBool found=PR_FALSE; - while(NS_OK==result) { + origin = mCurrentPosition; + current = origin; + end = mEndPosition; + + while(current != end) { - theChar=theBuf[mOffset++]; + theChar=*current; if(theChar) { found=PR_FALSE; if(('a'<=theChar) && (theChar<='f')) @@ -778,21 +921,74 @@ nsresult nsScanner::ReadNumber(nsString& aString) { found=PR_TRUE; else if('#'==theChar) found=PR_TRUE; + if(!found) { - mOffset-=1; - aString.Append(&theBuf[theOrigin],mOffset-theOrigin); + AppendUnicodeTo(origin, current, aString); break; } + + current++; } - else if ((PRUint32)mBuffer.Length()<=mOffset) { - mOffset -= 1; - aString.Append(&theBuf[theOrigin],mOffset-theOrigin); - result=Peek(theChar); - theBuf=mBuffer.GetUnicode(); - theOrigin=mOffset; + } + + SetPosition(current); + if (current == end) { + AppendUnicodeTo(origin, current, aString); + return Eof(); + } + + //DoErrTest(aString); + + return result; +} + +nsresult nsScanner::ReadNumber(nsReadingIterator<PRUnichar>& aStart, + nsReadingIterator<PRUnichar>& aEnd) { + + if (!mSlidingBuffer) { + return kEOF; + } + + PRUnichar theChar=0; + nsresult result=Peek(theChar); + nsReadingIterator<PRUnichar> origin, current, end; + PRBool found=PR_FALSE; + + origin = mCurrentPosition; + current = origin; + end = mEndPosition; + + while(current != end) { + + theChar=*current; + if(theChar) { + found=PR_FALSE; + if(('a'<=theChar) && (theChar<='f')) + found=PR_TRUE; + else if(('A'<=theChar) && (theChar<='F')) + found=PR_TRUE; + else if(('0'<=theChar) && (theChar<='9')) + found=PR_TRUE; + else if('#'==theChar) + found=PR_TRUE; + + if(!found) { + aStart = origin; + aEnd = current; + break; + } + + current++; } } + SetPosition(current); + if (current == end) { + aStart = origin; + aEnd = current; + return Eof(); + } + //DoErrTest(aString); return result; @@ -808,15 +1004,22 @@ nsresult nsScanner::ReadNumber(nsString& aString) { */ nsresult nsScanner::ReadWhitespace(nsString& aString) { + if (!mSlidingBuffer) { + return kEOF; + } + PRUnichar theChar=0; nsresult result=Peek(theChar); - const PRUnichar* theBuf=mBuffer.GetUnicode(); - PRInt32 theOrigin=mOffset; + nsReadingIterator<PRUnichar> origin, current, end; PRBool found=PR_FALSE; - while(NS_OK==result) { + origin = mCurrentPosition; + current = origin; + end = mEndPosition; + + while(current != end) { - theChar=theBuf[mOffset++]; + theChar=*current; if(theChar) { switch(theChar) { case ' ': @@ -831,18 +1034,18 @@ nsresult nsScanner::ReadWhitespace(nsString& aString) { break; } if(!found) { - mOffset-=1; - aString.Append(&theBuf[theOrigin],mOffset-theOrigin); + AppendUnicodeTo(origin, current, aString); break; } + + current ++; } - else if ((PRUint32)mBuffer.Length()<=mOffset) { - mOffset -= 1; - aString.Append(&theBuf[theOrigin],mOffset-theOrigin); - result=Peek(theChar); - theBuf=mBuffer.GetUnicode(); - theOrigin=mOffset; - } + } + + SetPosition(current); + if (current == end) { + AppendUnicodeTo(origin, current, aString); + return Eof(); } //DoErrTest(aString); @@ -850,6 +1053,59 @@ nsresult nsScanner::ReadWhitespace(nsString& aString) { return result; } +nsresult nsScanner::ReadWhitespace(nsReadingIterator<PRUnichar>& aStart, + nsReadingIterator<PRUnichar>& aEnd) { + + if (!mSlidingBuffer) { + return kEOF; + } + + PRUnichar theChar=0; + nsresult result=Peek(theChar); + nsReadingIterator<PRUnichar> origin, current, end; + PRBool found=PR_FALSE; + + origin = mCurrentPosition; + current = origin; + end = mEndPosition; + + while(current != end) { + + theChar=*current; + if(theChar) { + switch(theChar) { + case ' ': + case '\b': + case '\t': + case kLF: + case kCR: + found=PR_TRUE; + break; + default: + found=PR_FALSE; + break; + } + if(!found) { + aStart = origin; + aEnd = current; + break; + } + + current ++; + } + } + + SetPosition(current); + if (current == end) { + aStart = origin; + aEnd = current; + return Eof(); + } + + //DoErrTest(aString); + + return result; +} /** * Consume chars as long as they are <i>in</i> the @@ -865,30 +1121,38 @@ nsresult nsScanner::ReadWhile(nsString& aString, nsString& aValidSet, PRBool addTerminal){ + if (!mSlidingBuffer) { + return kEOF; + } + PRUnichar theChar=0; nsresult result=Peek(theChar); - const PRUnichar* theBuf=mBuffer.GetUnicode(); - PRInt32 theOrigin=mOffset; + nsReadingIterator<PRUnichar> origin, current, end; - while(NS_OK==result) { + origin = mCurrentPosition; + current = origin; + end = mEndPosition; + + while(current != end) { - theChar=theBuf[mOffset++]; + theChar=*current; if(theChar) { PRInt32 pos=aValidSet.FindChar(theChar); if(kNotFound==pos) { - if(!addTerminal) - mOffset-=1; - aString.Append(&theBuf[theOrigin],mOffset-theOrigin); + if(addTerminal) + current++; + AppendUnicodeTo(origin, current, aString); break; } + + current++; } - else if ((PRUint32)mBuffer.Length()<=mOffset) { - mOffset -= 1; - aString.Append(&theBuf[theOrigin],mOffset-theOrigin); - result=Peek(theChar); - theBuf=mBuffer.GetUnicode(); - theOrigin=mOffset; - } + } + + SetPosition(current); + if (current == end) { + AppendUnicodeTo(origin, current, aString); + return Eof(); } //DoErrTest(aString); @@ -911,31 +1175,37 @@ nsresult nsScanner::ReadUntil(nsString& aString, nsString& aTerminalSet, PRBool addTerminal){ + if (!mSlidingBuffer) { + return kEOF; + } PRUnichar theChar=0; nsresult result=Peek(theChar); - const PRUnichar* theBuf=mBuffer.GetUnicode(); - PRInt32 theOrigin=mOffset; + nsReadingIterator<PRUnichar> origin, current, end; - while(NS_OK==result) { + origin = mCurrentPosition; + current = origin; + end = mEndPosition; + + while(current != end) { - theChar=theBuf[mOffset++]; + theChar=*current; if(theChar) { PRInt32 pos=aTerminalSet.FindChar(theChar); if(kNotFound!=pos) { - if(!addTerminal) - mOffset-=1; - aString.Append(&theBuf[theOrigin],mOffset-theOrigin); + if(addTerminal) + current++; + AppendUnicodeTo(origin, current, aString); break; - } - } - else if ((PRUint32)mBuffer.Length()<=mOffset) { - mOffset -= 1; - aString.Append(&theBuf[theOrigin],mOffset-theOrigin); - result=Peek(theChar); - theBuf=mBuffer.GetUnicode(); - theOrigin=mOffset; + } } + current++; + } + + SetPosition(current); + if (current == end) { + AppendUnicodeTo(origin, current, aString); + return Eof(); } //DoErrTest(aString); @@ -958,38 +1228,87 @@ nsresult nsScanner::ReadUntil(nsString& aString, nsCString& aTerminalSet, PRBool addTerminal){ + if (!mSlidingBuffer) { + return kEOF; + } + PRUnichar theChar=0; nsresult result=Peek(theChar); - const PRUnichar* theBuf=mBuffer.GetUnicode(); - PRInt32 theOrigin=mOffset; + nsReadingIterator<PRUnichar> origin, current, end; - while(NS_OK==result) { + origin = mCurrentPosition; + current = origin; + end = mEndPosition; + + while(current != end) { - theChar=theBuf[mOffset++]; + theChar=*current; if(theChar) { PRInt32 pos=aTerminalSet.FindChar(theChar); if(kNotFound!=pos) { - if(!addTerminal) - mOffset-=1; - aString.Append(&theBuf[theOrigin],mOffset-theOrigin); + if(addTerminal) + current++; + AppendUnicodeTo(origin, current, aString); break; } } - else if ((PRUint32)mBuffer.Length()<=mOffset) { - mOffset -= 1; - aString.Append(&theBuf[theOrigin],mOffset-theOrigin); - result=Peek(theChar); - theBuf=mBuffer.GetUnicode(); - theOrigin=mOffset; - } + current++; } + SetPosition(current); + if (current == end) { + AppendUnicodeTo(origin, current, aString); + return Eof(); + } //DoErrTest(aString); return result; } +nsresult nsScanner::ReadUntil(nsReadingIterator<PRUnichar>& aStart, + nsReadingIterator<PRUnichar>& aEnd, + nsString& aTerminalSet, + PRBool addTerminal){ + + if (!mSlidingBuffer) { + return kEOF; + } + + PRUnichar theChar=0; + nsresult result=Peek(theChar); + nsReadingIterator<PRUnichar> origin, current, end; + + origin = mCurrentPosition; + current = origin; + end = mEndPosition; + + while(current != end) { + + theChar=*current; + if(theChar) { + PRInt32 pos=aTerminalSet.FindChar(theChar); + if(kNotFound!=pos) { + if(addTerminal) + current++; + aStart = origin; + aEnd = current; + break; + } + } + current++; + } + + SetPosition(current); + if (current == end) { + aStart = origin; + aEnd = current; + return Eof(); + } + + return result; +} + /** * Consume characters until you encounter one contained in given * input set. @@ -1004,6 +1323,10 @@ nsresult nsScanner::ReadUntil(nsString& aString, const char* aTerminalSet, PRBool addTerminal) { + if (!mSlidingBuffer) { + return kEOF; + } + nsresult result=NS_OK; if(aTerminalSet) { PRInt32 len=nsCRT::strlen(aTerminalSet); @@ -1028,32 +1351,36 @@ nsresult nsScanner::ReadUntil(nsString& aString, nsresult nsScanner::ReadUntil(nsString& aString, PRUnichar aTerminalChar, PRBool addTerminal){ + if (!mSlidingBuffer) { + return kEOF; + } + PRUnichar theChar=0; - nsresult result=NS_OK; + nsresult result=Peek(theChar); + nsReadingIterator<PRUnichar> origin, current, end; - const PRUnichar* theBuf=mBuffer.GetUnicode(); - PRInt32 theOrigin=mOffset; - result=Peek(theChar); - PRUint32 theLen=mBuffer.Length(); + origin = mCurrentPosition; + current = origin; + end = mEndPosition; - while(NS_OK==result) { + while(current != end) { - theChar=theBuf[mOffset++]; + theChar=*current; if(theChar) { if(aTerminalChar==theChar) { - if(!addTerminal) - mOffset-=1; - aString.Append(&theBuf[theOrigin],mOffset-theOrigin); + if(addTerminal) + current++; + AppendUnicodeTo(origin, current, aString); break; } } - else if ((PRUint32)mBuffer.Length()<=mOffset) { - mOffset -= 1; - aString.Append(&theBuf[theOrigin],theLen-theOrigin); - mOffset=theLen; - result=Peek(theChar); - theLen=mBuffer.Length(); - } + current++; + } + + SetPosition(current); + if (current == end) { + AppendUnicodeTo(origin, current, aString); + return Eof(); } //DoErrTest(aString); @@ -1061,19 +1388,69 @@ nsresult nsScanner::ReadUntil(nsString& aString, } +void nsScanner::BindSubstring(nsSlidingSubstring& aSubstring, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd) +{ + aSubstring.Rebind(*mSlidingBuffer, aStart, aEnd); +} -/** - * - * @update gess 3/25/98 - * @param - * @return - */ -nsString& nsScanner::GetBuffer(void) { - return mBuffer; +void nsScanner::CurrentPosition(nsReadingIterator<PRUnichar>& aPosition) +{ + aPosition = mCurrentPosition; +} + +void nsScanner::EndReading(nsReadingIterator<PRUnichar>& aPosition) +{ + aPosition = mEndPosition; +} + +void nsScanner::SetPosition(nsReadingIterator<PRUnichar>& aPosition, PRBool aTerminate, PRBool aReverse) +{ + if (mSlidingBuffer) { + if (aReverse) { + mCountRemaining += (Distance(aPosition, mCurrentPosition)); + } + else { + mCountRemaining -= (Distance(mCurrentPosition, aPosition)); + } + mCurrentPosition = aPosition; + if (aTerminate && (mCurrentPosition == mEndPosition)) { + mMarkPosition = mCurrentPosition; + mSlidingBuffer->DiscardPrefix(mCurrentPosition); + } + } +} + +void nsScanner::ReplaceCharacter(nsReadingIterator<PRUnichar>& aPosition, + PRUnichar aChar) +{ + if (mSlidingBuffer) { + mSlidingBuffer->ReplaceCharacter(aPosition, aChar); + } +} + +void nsScanner::AppendToBuffer(PRUnichar* aStorageStart, + PRUnichar* aDataEnd, + PRUnichar* aStorageEnd) +{ + if (!mSlidingBuffer) { + mSlidingBuffer = new nsScannerString(aStorageStart, aDataEnd, aStorageEnd); + mSlidingBuffer->BeginReading(mCurrentPosition); + mMarkPosition = mCurrentPosition; + mSlidingBuffer->EndReading(mEndPosition); + mCountRemaining = (aDataEnd - aStorageStart); + } + else { + mSlidingBuffer->AppendBuffer(aStorageStart, aDataEnd, aStorageEnd); + if (mCurrentPosition == mEndPosition) { + mSlidingBuffer->BeginReading(mCurrentPosition); + } + mSlidingBuffer->EndReading(mEndPosition); + mCountRemaining += (aDataEnd - aStorageStart); + } } /** - * Call this to copy bytes out of the scanner that have not yet been consumed + * call this to copy bytes out of the scanner that have not yet been consumed * by the tokenization process. * * @update gess 5/12/98 @@ -1081,10 +1458,11 @@ nsString& nsScanner::GetBuffer(void) { * @return nada */ void nsScanner::CopyUnusedData(nsString& aCopyBuffer) { - PRInt32 theLen=mBuffer.Length(); - if(0<theLen) { - mBuffer.Right(aCopyBuffer,theLen-mMarkPos); - } + nsReadingIterator<PRUnichar> start, end; + start = mCurrentPosition; + end = mEndPosition; + + CopyUnicodeTo(start, end, aCopyBuffer); } /** diff --git a/mozilla/parser/htmlparser/src/nsScanner.h b/mozilla/parser/htmlparser/src/nsScanner.h index cb75d5b40df..e904af37b25 100644 --- a/mozilla/parser/htmlparser/src/nsScanner.h +++ b/mozilla/parser/htmlparser/src/nsScanner.h @@ -41,7 +41,19 @@ #include "prtypes.h" #include "nsIUnicodeDecoder.h" #include "nsFileStream.h" +#include "nsSlidingString.h" +class nsScannerString : public nsSlidingString { + public: + nsScannerString(PRUnichar* aStorageStart, + PRUnichar* aDataEnd, + PRUnichar* aStorageEnd); + virtual void InsertBuffer(PRUnichar* aStorageStart, + PRUnichar* aDataEnd, + PRUnichar* aStorageEnd); + virtual void ReplaceCharacter(nsReadingIterator<PRUnichar>& aPosition, + PRUnichar aChar); +}; class nsScanner { public: @@ -102,16 +114,9 @@ class nsScanner { * @param ch is the char to accept new value * @return error code reflecting read status */ - nsresult Peek(PRUnichar& ch); + nsresult Peek(PRUnichar& ch, PRUint32 aOffset=0); - /** - * Push the given char back onto the scanner - * - * @update gess 3/25/98 - * @param character to be pushed - * @return error code - */ - nsresult PutBack(PRUnichar ch); + nsresult Peek(nsAWritableString& aStr, PRInt32 aNumChars); /** * Skip over chars as long as they're in aSkipSet @@ -175,10 +180,17 @@ class nsScanner { * @param addTerminal tells us whether to append terminal to aString * @return error code */ - nsresult GetIdentifier(nsSubsumeStr& aString,PRBool allowPunct=PR_FALSE); + nsresult GetIdentifier(nsString& aString,PRBool allowPunct=PR_FALSE); nsresult ReadIdentifier(nsString& aString,PRBool allowPunct=PR_FALSE); + nsresult ReadIdentifier(nsReadingIterator<PRUnichar>& aStart, + nsReadingIterator<PRUnichar>& aEnd, + PRBool allowPunct=PR_FALSE); nsresult ReadNumber(nsString& aString); + nsresult ReadNumber(nsReadingIterator<PRUnichar>& aStart, + nsReadingIterator<PRUnichar>& aEnd); nsresult ReadWhitespace(nsString& aString); + nsresult ReadWhitespace(nsReadingIterator<PRUnichar>& aStart, + nsReadingIterator<PRUnichar>& aEnd); /** * Consume characters until you find the terminal char @@ -204,6 +216,8 @@ class nsScanner { nsresult ReadUntil(nsString& aString,nsString& aTermSet,PRBool addTerminal); nsresult ReadUntil(nsString& aString,nsCString& aTermSet,PRBool addTerminal); nsresult ReadUntil(nsString& aString,const char* aTermSet,PRBool addTerminal); + nsresult ReadUntil(nsReadingIterator<PRUnichar>& aStart, nsReadingIterator<PRUnichar>& aEnd, nsString& aTerminalSet,PRBool addTerminal); + /** * Consume characters while they're members of anInputSet @@ -225,7 +239,7 @@ class nsScanner { * @param * @return */ - PRUint32 Mark(PRInt32 anIndex=-1); + void Mark(void); /** * Resets current offset position of input stream to marked position. @@ -237,7 +251,7 @@ class nsScanner { * @param * @return */ - PRUint32 RewindToMark(void); + void RewindToMark(void); /** @@ -267,17 +281,6 @@ class nsScanner { */ PRBool Append(const char* aBuffer, PRUint32 aLen); - PRBool Append(const PRUnichar* aBuffer, PRUint32 aLen); - - /** - * - * - * @update gess 5/12/98 - * @param - * @return - */ - nsString& GetBuffer(void); - /** * Call this to copy bytes out of the scanner that have not yet been consumed * by the tokenization process. @@ -310,6 +313,15 @@ class nsScanner { */ nsresult SetDocumentCharset(const nsString& aCharset, nsCharsetSource aSource); + void BindSubstring(nsSlidingSubstring& aSubstring, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd); + void CurrentPosition(nsReadingIterator<PRUnichar>& aPosition); + void EndReading(nsReadingIterator<PRUnichar>& aPosition); + void SetPosition(nsReadingIterator<PRUnichar>& aPosition, + PRBool aTruncate = PR_FALSE, + PRBool aReverse = PR_FALSE); + void ReplaceCharacter(nsReadingIterator<PRUnichar>& aPosition, + PRUnichar aChar); + /** * Internal method used to cause the internal buffer to * be filled with data. @@ -319,7 +331,6 @@ class nsScanner { PRBool IsIncremental(void) {return mIncremental;} void SetIncremental(PRBool anIncrValue) {mIncremental=anIncrValue;} - PRUint32 GetOffset(void) {return mOffset;} PRInt32 GetNewlinesSkipped(void) { return mNewlinesSkipped; } protected: @@ -335,18 +346,24 @@ class nsScanner { */ nsresult FillBuffer(void); + void AppendToBuffer(PRUnichar* aStorageStart, + PRUnichar* aDataEnd, + PRUnichar* aStorageEnd); + nsInputStream* mInputStream; - nsString mBuffer; + nsScannerString* mSlidingBuffer; + nsReadingIterator<PRUnichar> mCurrentPosition; // The position we will next read from in the scanner buffer + nsReadingIterator<PRUnichar> mMarkPosition; // The position last marked (we may rewind to here) + nsReadingIterator<PRUnichar> mEndPosition; // The current end of the scanner buffer nsString mFilename; - PRUint32 mOffset; - PRUint32 mMarkPos; + PRUint32 mCountRemaining; // The number of bytes still to be read + // from the scanner buffer PRUint32 mTotalRead; PRBool mOwnsStream; PRBool mIncremental; nsCharsetSource mCharsetSource; nsString mCharset; nsIUnicodeDecoder *mUnicodeDecoder; - nsString mUnicodeXferBuf; PRInt32 mNewlinesSkipped; }; diff --git a/mozilla/parser/htmlparser/src/nsToken.cpp b/mozilla/parser/htmlparser/src/nsToken.cpp index afa33922a92..94573df308a 100644 --- a/mozilla/parser/htmlparser/src/nsToken.cpp +++ b/mozilla/parser/htmlparser/src/nsToken.cpp @@ -43,7 +43,7 @@ int CToken::GetTokenCount(){return TokenCount-DelTokenCount;} * * @update gess 7/21/98 */ -CToken::CToken(PRInt32 aTag) : mTextValue() { +CToken::CToken(PRInt32 aTag) { // Tokens are allocated through the arena ( not heap allocated..yay ). // We, therefore, don't need this macro anymore.. #ifdef MATCH_CTOR_DTOR @@ -65,65 +65,6 @@ CToken::CToken(PRInt32 aTag) : mTextValue() { #endif } -/** - * Constructor with string for tagname assignment - * - * @update gess 3/25/98 - * @param nsString--name of token - */ -CToken::CToken(const nsString& aName) : mTextValue(aName) { - // Tokens are allocated through the arena ( not heap allocated..yay ). - // We, therefore, don't need this macro anymore.. -#ifdef MATCH_CTOR_DTOR - MOZ_COUNT_CTOR(CToken); -#endif - - mTypeID=0; - mAttrCount=0; - mNewlineCount=0; - mOrigin=eSource; - // Note that the use count starts with 1 instead of 0. This - // is because of the assumption that any token created is in - // use and therefore does not require an explicit addref, or - // rather IF_HOLD. This, also, will make sure that tokens created - // on the stack do not accidently hit the arena recycler. - mUseCount=1; - -#ifdef NS_DEBUG - TokenCount++; -#endif -} - -/** - * constructor from char* - * - * @update gess 3/25/98 - * @param aName--char* containing name of token - */ -CToken::CToken(const char* aName) { - // Tokens are allocated through the arena ( not heap allocated..yay ). - // We, therefore, don't need this macro anymore.. -#ifdef MATCH_CTOR_DTOR - MOZ_COUNT_CTOR(CToken); -#endif - - mTypeID=0; - mAttrCount=0; - mNewlineCount=0; - mOrigin=eSource; - mTextValue.AssignWithConversion(aName); - // Note that the use count starts with 1 instead of 0. This - // is because of the assumption that any token created is in - // use and therefore does not require an explicit addref, or - // rather IF_HOLD. This, also, will make sure that tokens created - // on the stack do not accidently hit the arena recycler. - mUseCount=1; - -#ifdef NS_DEBUG - TokenCount++; -#endif -} - /** * Decstructor * @@ -139,31 +80,6 @@ CToken::~CToken() { mUseCount=0; } - -/** - * This method gets called when a token is about to be reused - * for some other purpose. The token should initialize itself - * to some reasonable default values. - * @update gess7/25/98 - * @param aTag - * @param aString - */ -void CToken::Reinitialize(PRInt32 aTag, const nsString& aString){ - if(0==aString.Length()) - mTextValue.Truncate(0); - else mTextValue=aString; - mAttrCount=0; - mAttrCount=0; - mNewlineCount=0; - mTypeID=aTag; - mOrigin=eSource; - // Note that the use count starts with 1 instead of 0. This - // is because of the assumption that any token created is in - // use and therefore does not require an explicit addref, or - // rather IF_HOLD. This, also, will make sure that tokens created - // on the stack do not accidently hit the arena recycler. - mUseCount=1; -} /** * Virtual method used to tell this toke to consume his @@ -190,9 +106,9 @@ nsresult CToken::Consume(PRUnichar aChar,nsScanner& aScanner,PRInt32 aMode) { void CToken::DebugDumpToken(nsOutputStream& anOutputStream) { anOutputStream << "[" << GetClassName() << "] "; PRUint32 i=0; - PRUint32 theLen=mTextValue.Length(); + PRUint32 theLen=GetStringValue().Length(); for(i=0;i<theLen;i++){ - anOutputStream << char(mTextValue.CharAt(i)); + anOutputStream << (const char*)NS_ConvertUCS2toUTF8(GetStringValue()); } anOutputStream << " TypeID: " << mTypeID << " AttrCount: " << mAttrCount << nsEndl; } @@ -205,36 +121,9 @@ void CToken::DebugDumpToken(nsOutputStream& anOutputStream) { * @param ostream -- output stream to accept output data */ void CToken::DebugDumpSource(nsOutputStream& anOutputStream) { - char buf[256]; - mTextValue.ToCString(buf,sizeof(buf)); - anOutputStream << buf; + anOutputStream << (const char*)NS_ConvertUCS2toUTF8(GetStringValue()); } -/** - * Setter method that changes the string value of this token - * @update gess5/11/98 - * @param name is a char* value containing new string value - */ -void CToken::SetCStringValue(const char* name){ - mTextValue.AssignWithConversion(name); -} - -/** - * Setter method for the string value of this token - */ -void CToken::SetStringValue(nsString& aStr) { - mTextValue = aStr; -} - -/** - * This method retrieves the value of this internal string. - * - * @update gess 3/25/98 - * @return nsString reference to internal string value - */ -nsString& CToken::GetStringValueXXX(void) { - return mTextValue; -} /** * Get string of full contents, suitable for debug dump. @@ -243,7 +132,7 @@ nsString& CToken::GetStringValueXXX(void) { * @return reference to string containing string value */ void CToken::GetSource(nsString& anOutputString){ - anOutputString=mTextValue; + anOutputString.Assign(GetStringValue()); } /** @@ -251,19 +140,7 @@ void CToken::GetSource(nsString& anOutputString){ * @return reference to string containing string value */ void CToken::AppendSource(nsString& anOutputString){ - anOutputString+=mTextValue; -} - -/** - * This method retrieves the value of this internal string - * as a cstring. - * - * @update gess 3/25/98 - * @return char* rep of internal string value - */ -char* CToken::GetCStringValue(char* aBuffer, PRInt32 aMaxLen) { - strcpy(aBuffer,"string"); - return aBuffer; + anOutputString.Append(GetStringValue()); } /** diff --git a/mozilla/parser/htmlparser/src/nsToken.h b/mozilla/parser/htmlparser/src/nsToken.h index 80684f25a58..8fe686c4334 100644 --- a/mozilla/parser/htmlparser/src/nsToken.h +++ b/mozilla/parser/htmlparser/src/nsToken.h @@ -114,42 +114,18 @@ class CToken { */ CToken(PRInt32 aTag=0); - /** - * Constructor with string assignment for tag - * @update gess5/11/98 - * @param aName is the given name of the token - */ - CToken(const nsString& aName); - - /** - * constructor from char* - * @update gess5/11/98 - * @param aName is the given name of the token - */ - CToken(const char* aName); - /** * destructor * @update gess5/11/98 */ virtual ~CToken(); - /** - * This method gets called when a token is about to be reused - * for some other purpose. The token should reinit itself to - * some reasonable default values. - * @update gess7/25/98 - * @param aTag - * @param aString - */ - virtual void Reinitialize(PRInt32 aTag, const nsString& aString); - /** * Retrieve string value of the token * @update gess5/11/98 * @return reference to string containing string value */ - virtual nsString& GetStringValueXXX(void); + virtual const nsAReadableString& GetStringValue(void) = 0; /** * Get string of full contents, suitable for debug dump. @@ -164,25 +140,6 @@ class CToken { */ virtual void AppendSource(nsString& anOutputString); - /** - * Setter method that changes the string value of this token - * @update gess5/11/98 - * @param name is a char* value containing new string value - */ - virtual void SetCStringValue(const char* name); - - /** - * Setter method for the string value of this token - */ - virtual void SetStringValue(nsString& aStr); - - /** - * Retrieve string value of the token as a c-string - * @update gess5/11/98 - * @return reference to string containing string value - */ - virtual char* GetCStringValue(char* aBuffer, PRInt32 aMaxLen); - /** * Sets the ordinal value of this token (not currently used) * @update gess5/11/98 @@ -276,7 +233,6 @@ protected: PRInt32 mTypeID; PRInt16 mAttrCount; - nsString mTextValue; PRInt32 mUseCount; }; diff --git a/mozilla/parser/htmlparser/src/nsViewSourceHTML.cpp b/mozilla/parser/htmlparser/src/nsViewSourceHTML.cpp index ab13dfade48..e2d4cdaed49 100644 --- a/mozilla/parser/htmlparser/src/nsViewSourceHTML.cpp +++ b/mozilla/parser/htmlparser/src/nsViewSourceHTML.cpp @@ -74,6 +74,7 @@ static NS_DEFINE_CID(kPrefCID, NS_PREF_CID); #endif // VIEW_SOURCE_COLORING #include "COtherDTD.h" +#include "nsElementTable.h" #include "prenv.h" //this is here for debug reasons... #include "prtypes.h" //this is here for debug reasons... @@ -169,15 +170,15 @@ public: mIndirectString=0; } - void SetIndirectString(const nsString& aString) { + void SetIndirectString(const nsAReadableString& aString) { mIndirectString=&aString; } - virtual nsString& GetStringValueXXX(void){ - return (nsString&)*mIndirectString; + virtual const nsAReadableString& GetStringValue(void){ + return (nsAReadableString&)*mIndirectString; } - const nsString* mIndirectString; + const nsAReadableString* mIndirectString; }; @@ -196,7 +197,7 @@ public: mITextToken(), mITextNode(&mITextToken), mTextToken(), - mErrorToken("error"), + mErrorToken(NS_ConvertASCIItoUCS2("error")), mTextNode(&mTextToken){ } @@ -215,7 +216,7 @@ public: CIndirectTextToken mITextToken; nsCParserNode mITextNode; CTextToken mTextToken; - CToken mErrorToken; + CTextToken mErrorToken; nsCParserNode mTextNode; }; @@ -235,6 +236,7 @@ enum { VIEW_SOURCE_POPUP = 11 }; +#ifdef VIEW_SOURCE_COLORING static char* kElementStyles[] = { "color: purple; font-weight:bold;", "color: purple; font-weight:bold;", @@ -249,6 +251,7 @@ static char* kElementStyles[] = { "display:block; background-color:#FFFFCC; width:90%; border:solid; border-width:1pt; font-family: Sans-serif;", "font-weight: normal;" }; +#endif static char* kBeforeText[] = { "<", @@ -327,6 +330,7 @@ CViewSourceHTML::CViewSourceHTML() : mTags(), mErrors() { mDocType=eHTML3Text; mValidator=0; mHasOpenRoot=PR_FALSE; + mInCDATAContainer = PR_FALSE; //set this to 1 if you want to see errors in your HTML markup. char* theEnvString = PR_GetEnv("MOZ_VALIDATE_HTML"); @@ -445,19 +449,17 @@ nsresult CViewSourceHTML::WillBuildModel( const CParserContext& aParserContext, nsAutoString tag; tag.AssignWithConversion("HTML"); - CStartToken htmlToken(eHTMLTag_html); - htmlToken.SetStringValue(tag); + CStartToken htmlToken(tag, eHTMLTag_html); nsCParserNode htmlNode(&htmlToken,0); mSink->OpenHTML(htmlNode); tag.AssignWithConversion("BODY"); - CStartToken bodyToken(eHTMLTag_body); - bodyToken.SetStringValue(tag); + CStartToken bodyToken(tag, eHTMLTag_body); nsCParserNode bodyNode(&bodyToken,0); mSink->OpenBody(bodyNode); #else static const char* theHeader="<?xml version=\"1.0\"?>"; - CToken ssToken(theHeader); + CCommentToken ssToken(theHeader); nsCParserNode ssNode(&ssToken); result= mSink->AddCharacterData(ssNode); #endif // VIEW_SOURCE_HTML @@ -500,11 +502,10 @@ NS_IMETHODIMP CViewSourceHTML::BuildModel(nsIParser* aParser,nsITokenizer* aToke #ifdef VIEW_SOURCE_HTML nsAutoString tag; tag.AssignWithConversion("PRE"); - CStartToken theToken(eHTMLTag_pre); - theToken.SetStringValue(tag); + CStartToken theToken(tag, eHTMLTag_pre); #else //now let's automatically open the root container... - CToken theToken("viewsource"); + CStartToken theToken("viewsource"); #endif // VIEW_SOURCE_HTML nsCParserNode theNode(&theToken,0); @@ -513,12 +514,10 @@ NS_IMETHODIMP CViewSourceHTML::BuildModel(nsIParser* aParser,nsITokenizer* aToke if(theAllocator) { #ifdef VIEW_SOURCE_HTML theAttr=(CAttributeToken*)theAllocator->CreateTokenOfType(eToken_attribute,eHTMLTag_unknown,NS_ConvertToString(kPreStyle)); - nsString& theKey=theAttr->GetKey(); - theKey=NS_ConvertToString("style"); + theAttr->SetKey(NS_LITERAL_STRING("style")); #else theAttr=(CAttributeToken*)theAllocator->CreateTokenOfType(eToken_attribute,eHTMLTag_unknown,NS_ConvertToString("http://www.mozilla.org/viewsource")); - nsString& theKey=theAttr->GetKey(); - theKey=NS_ConvertToString("xmlns"); + theAttr->SetKey(NS_LITERAL_STRING("xmlns")); #endif // VIEW_SOURCE_HTML } if(theAttr) @@ -604,23 +603,15 @@ NS_IMETHODIMP CViewSourceHTML::DidBuildModel(nsresult anErrorCode,PRBool aNotify if(ePlainText!=mDocType) { #ifdef VIEW_SOURCE_HTML - nsAutoString tag; - - tag.AssignWithConversion("PRE"); CEndToken theToken(eHTMLTag_pre); - theToken.SetStringValue(tag); nsCParserNode preNode(&theToken,0); mSink->CloseContainer(preNode); - tag.AssignWithConversion("BODY"); CEndToken bodyToken(eHTMLTag_body); - bodyToken.SetStringValue(tag); nsCParserNode bodyNode(&bodyToken,0); mSink->CloseBody(bodyNode); - tag.AssignWithConversion("HTML"); CEndToken htmlToken(eHTMLTag_html); - htmlToken.SetStringValue(tag); nsCParserNode htmlNode(&htmlToken,0); mSink->CloseHTML(htmlNode); #else @@ -628,7 +619,7 @@ NS_IMETHODIMP CViewSourceHTML::DidBuildModel(nsresult anErrorCode,PRBool aNotify GenerateSummary(); - CToken theToken("viewsource"); + CEndToken theToken("viewsource"); nsCParserNode theNode(&theToken,0); mSink->CloseContainer(theNode); #endif // VIEW_SOURCE_HTML @@ -821,120 +812,6 @@ PRBool CViewSourceHTML::IsContainer(PRInt32 aTag) const{ return result; } - -/** - * This method gets called when a tag needs to be sent out - * - * @update gess 3/25/98 - * @param - * @return result status - */ -nsresult WriteText(const nsString& aTextString,nsIContentSink& aSink,PRBool aPreserveSpace,PRBool aPlainText,CSharedVSContext& aContext) { - nsresult result=NS_OK; - - nsString& temp=aContext.mTextToken.GetStringValueXXX(); - temp.Truncate(); - - PRInt32 theEnd=aTextString.Length(); - PRInt32 theTextOffset=0; - PRInt32 theOffset=-1; //aTextString.FindCharInSet("\t\n\r ",theStartOffset); - PRInt32 theSpaces=0; - PRUnichar theChar=0; - PRUnichar theNextChar=0; - - while(++theOffset<theEnd){ - //theNextChar=aTextString[theOffset-1]; - theChar=aTextString[theOffset]; - switch(theChar){ - case kSpace: - theNextChar=(theOffset+1 != theEnd) ? aTextString[theOffset+1] : '\0'; - if((!aPlainText) && aPreserveSpace) { //&& ((kSpace==theNextChar) || (0==theNextChar))) - if(theTextOffset<theOffset) { - if(kSpace==theNextChar) { - aTextString.Mid(temp,theTextOffset,theOffset-theTextOffset); - theTextOffset=theOffset--; - } - } - else{ - while((theOffset<theEnd) && (kSpace==aTextString[theOffset])){ - theOffset++; - theSpaces++; - } - theTextOffset=theOffset--; - } - } - break; - - case kTab: - if((!aPlainText) && aPreserveSpace){ - if(theTextOffset<theOffset) { - aTextString.Mid(temp,theTextOffset,theOffset-theTextOffset); - } - theSpaces+=8; - theOffset++; - theTextOffset=theOffset; - } - break; - - case kCR: - case kLF: - if(theTextOffset<theOffset) { - aTextString.Mid(temp,theTextOffset,theOffset-theTextOffset); - theTextOffset=theOffset--; //back up one on purpose... - } - else { - theNextChar=(theOffset+1 != theEnd) ? aTextString.CharAt(theOffset+1) : '\0'; - if((kCR==theChar) && (kLF==theNextChar)) { - theOffset++; - } - - CStartToken theToken(eHTMLTag_br); - aContext.mStartNode.Init(&theToken,0); - result=aSink.AddLeaf(aContext.mStartNode); - theTextOffset=theOffset+1; - } - break; - - default: - break; - } //switch - if(0<temp.Length()){ - result=aSink.AddLeaf(aContext.mTextNode); - temp.Truncate(); - } - if(0<theSpaces){ - - CEntityToken theToken( NS_ConvertToString("nbsp") ); - aContext.mStartNode.Init(&theToken,0); - int theIndex; - for(theIndex=0;theIndex<theSpaces;theIndex++) - result=aSink.AddLeaf(aContext.mStartNode); - theSpaces=0; - } - } - - if(theTextOffset<theEnd){ - temp.Truncate(); - aTextString.Mid(temp,theTextOffset,theEnd-theTextOffset); - result=aSink.AddLeaf(aContext.mTextNode); //just dump the whole string... - } - - return result; -} - -/** - * This method gets called when a tag needs to be sent out - * - * @update gess 3/25/98 - * @param - * @return result status - */ -nsresult CViewSourceHTML::WriteText(const nsString& aTextString,nsIContentSink& aSink,PRBool aPreserveSpace,PRBool aPlainText) { - CSharedVSContext& theContext=CSharedVSContext::GetSharedContext(); - return ::WriteText(aTextString,aSink,aPreserveSpace,aPlainText,theContext); -} - - /** * This method gets called when a tag needs to write it's attributes * @@ -959,16 +836,13 @@ nsresult CViewSourceHTML::WriteAttributes(PRInt32 attrCount) { theContext.mTokenNode.AddAttribute(theToken); //and add it to the node. CAttributeToken* theAttrToken=(CAttributeToken*)theToken; - nsString& theKey=theAttrToken->GetKey(); - theKey.StripChar(kCR); + const nsAReadableString& theKey=theAttrToken->GetKey(); - CToken theKeyToken(theKey); - result=WriteTag(mKey,&theKeyToken,0,PR_FALSE); - nsString& theValue=theToken->GetStringValueXXX(); - theValue.StripChar(kCR); + result=WriteTag(mKey,theKey,0,PR_FALSE); + const nsString& theValue=theAttrToken->GetValue(); if((0<theValue.Length()) || (theAttrToken->mHasEqualWithoutValue)){ - result=WriteTag(mValue,theToken,0,PR_FALSE); + result=WriteTag(mValue,theValue,0,PR_FALSE); } } } @@ -987,9 +861,9 @@ nsresult CViewSourceHTML::WriteAttributes(PRInt32 attrCount) { * @return result status */ #ifdef VIEW_SOURCE_HTML -nsresult CViewSourceHTML::WriteTag(PRInt32 aTagType,nsString & aText,PRInt32 attrCount,PRBool aNewlineRequired) { +nsresult CViewSourceHTML::WriteTag(PRInt32 aTagType,const nsAReadableString & aText,PRInt32 attrCount,PRBool aNewlineRequired) { #else -nsresult CViewSourceHTML::WriteTag(nsString &theXMLTagName,nsString & aText,PRInt32 attrCount,PRBool aNewlineRequired) { +nsresult CViewSourceHTML::WriteTag(nsString &theXMLTagName,nsAReadableString & aText,PRInt32 attrCount,PRBool aNewlineRequired) { #endif // VIEW_SOURCE_HTML static nsString theString; @@ -1014,14 +888,10 @@ nsresult CViewSourceHTML::WriteTag(nsString &theXMLTagName,nsString & aText,PRIn #ifdef VIEW_SOURCE_COLORING nsAutoString tag (NS_LITERAL_STRING("SPAN")); - CStartToken theTagToken(eHTMLTag_span); - if (syntaxHilight) - { - theTagToken.SetStringValue(tag); - } + CStartToken theTagToken(tag, eHTMLTag_span); #endif // VIEW_SOURCE_COLORING -#else // VIEW_SOURCE_HTML *UNDEFINED* - CToken theTagToken(theXMLTagName); +#else + CStartToken theTagToken(theXMLTagName); #endif // VIEW_SOURCE_HTML #ifdef VIEW_SOURCE_COLORING @@ -1032,8 +902,7 @@ nsresult CViewSourceHTML::WriteTag(nsString &theXMLTagName,nsString & aText,PRIn nsTokenAllocator* theAllocator=mTokenizer->GetTokenAllocator(); if(theAllocator) { CAttributeToken* theAttr=(CAttributeToken*)theAllocator->CreateTokenOfType(eToken_attribute,eHTMLTag_unknown,NS_ConvertToString(kElementStyles[aTagType])); - nsString& theKey=theAttr->GetKey(); - theKey=NS_ConvertToString("style"); + theAttr->SetKey(NS_LITERAL_STRING("style")); theContext.mStartNode.AddAttribute(theAttr); } #endif // VIEW_SOURCE_HTML @@ -1071,7 +940,6 @@ nsresult CViewSourceHTML::WriteTag(nsString &theXMLTagName,nsString & aText,PRIn { theContext.mStartNode.ReleaseAll(); CEndToken theEndToken(eHTMLTag_span); - theEndToken.SetStringValue(tag); theContext.mEndNode.Init(&theEndToken,mLineNumber); mSink->CloseContainer(theContext.mEndNode); //emit </starttag>... } @@ -1097,31 +965,6 @@ nsresult CViewSourceHTML::WriteTag(nsString &theXMLTagName,nsString & aText,PRIn return result; } -/** - * This method gets called when a tag needs to be sent out - * - * @update gess 6June2000 -- factored to use WriteTag(txt,txt...); - * @param - * @return result status - */ -#ifdef VIEW_SOURCE_HTML -nsresult CViewSourceHTML::WriteTag(PRInt32 aTagType,CToken* aToken,PRInt32 attrCount,PRBool aNewlineRequired) { -#else -nsresult CViewSourceHTML::WriteTag(nsString &theXMLTagName,CToken* aToken,PRInt32 attrCount,PRBool aNewlineRequired) { -#endif // VIEW_SOURCE_HTML - - nsString& theStr=aToken->GetStringValueXXX(); - theStr.StripChar(kCR); - -#ifdef VIEW_SOURCE_HTML - nsresult result=WriteTag(aTagType,theStr,attrCount,aNewlineRequired); -#else - nsresult result=WriteTag(theXMLTagName,theStr,attrCount,aNewlineRequired); -#endif // VIEW_SOURCE_HTML - - return result; -} - /** * This method gets called when a tag needs to be sent out but is known to be misplaced (error) * @@ -1130,9 +973,9 @@ nsresult CViewSourceHTML::WriteTag(nsString &theXMLTagName,CToken* aToken,PRInt3 * @return result status */ #ifdef VIEW_SOURCE_HTML -nsresult CViewSourceHTML::WriteTagWithError(PRInt32 aTagType,CToken* aToken,PRInt32 attrCount,PRBool aNewlineRequired) { +nsresult CViewSourceHTML::WriteTagWithError(PRInt32 aTagType,const nsAReadableString& aStr,PRInt32 attrCount,PRBool aNewlineRequired) { #else -nsresult CViewSourceHTML::WriteTagWithError(nsString &theXMLTagName,CToken* aToken,PRInt32 attrCount,PRBool aNewlineRequired) { +nsresult CViewSourceHTML::WriteTagWithError(nsString &theXMLTagName,const nsAReadableString& aStr,PRInt32 attrCount,PRBool aNewlineRequired) { #endif // VIEW_SOURCE_HTML STOP_TIMER(); @@ -1150,9 +993,9 @@ nsresult CViewSourceHTML::WriteTagWithError(nsString &theXMLTagName,CToken* aTok #ifdef VIEW_SOURCE_HTML //now write the tag from the source file... - result=WriteTag(aTagType,aToken,attrCount,aNewlineRequired); + result=WriteTag(aTagType,aStr,attrCount,aNewlineRequired); #else - result=WriteTag(theXMLTagName,aToken,attrCount,aNewlineRequired); + result=WriteTag(theXMLTagName,aStr,attrCount,aNewlineRequired); #endif // VIEW_SOURCE_HTML if(ePlainText!=mDocType) { @@ -1222,6 +1065,11 @@ NS_IMETHODIMP CViewSourceHTML::HandleToken(CToken* aToken,nsIParser* aParser) { { mTagCount++; + if (gHTMLElements[theChild].CanContainType(kCDATA)) { + mInCDATAContainer = PR_TRUE; + } + + const nsAReadableString& startValue = aToken->GetStringValue(); if(mShowErrors) { PRBool theChildIsValid=PR_TRUE; if(mValidator) { @@ -1231,15 +1079,15 @@ NS_IMETHODIMP CViewSourceHTML::HandleToken(CToken* aToken,nsIParser* aParser) { mTags.Append(PRUnichar(theChild)); } } - + if(theChildIsValid) - result=WriteTag(mStartTag,aToken,aToken->GetAttributeCount(),PR_TRUE); + result=WriteTag(mStartTag,startValue,aToken->GetAttributeCount(),PR_TRUE); else { AddContainmentError(theChild,theParent,mLineNumber); - result=WriteTagWithError(mStartTag,aToken,aToken->GetAttributeCount(),PR_TRUE); + result=WriteTagWithError(mStartTag,startValue,aToken->GetAttributeCount(),PR_TRUE); } } - else result=WriteTag(mStartTag,aToken,aToken->GetAttributeCount(),PR_TRUE); + else result=WriteTag(mStartTag,startValue,aToken->GetAttributeCount(),PR_TRUE); if((ePlainText!=mDocType) && mParser && (NS_OK==result)) { CObserverService* theService=mParser->GetObserverService(); @@ -1255,53 +1103,82 @@ NS_IMETHODIMP CViewSourceHTML::HandleToken(CToken* aToken,nsIParser* aParser) { break; case eToken_end: - if(theParent==theChild) { - mTags.Truncate(mTags.Length()-1); + { + if (gHTMLElements[theChild].CanContainType(kCDATA)) { + mInCDATAContainer = PR_FALSE; + } + + if(theParent==theChild) { + mTags.Truncate(mTags.Length()-1); + } + const nsAReadableString& endValue = aToken->GetStringValue(); + result=WriteTag(mEndTag,endValue,0,PR_TRUE); } - result=WriteTag(mEndTag,aToken,0,PR_TRUE); break; case eToken_cdatasection: { - nsString& theStr=aToken->GetStringValueXXX(); - theStr.InsertWithConversion("<!",0); - theStr.AppendWithConversion("]]>"); - result=WriteTag(mCDATATag,aToken,0,PR_TRUE); + nsAutoString theStr; + theStr.Assign(NS_LITERAL_STRING("<!")); + theStr.Append(aToken->GetStringValue()); + theStr.Append(NS_LITERAL_STRING("]]>")); + result=WriteTag(mCDATATag,theStr,0,PR_TRUE); } break; case eToken_comment: - result=WriteTag(mCommentTag,aToken,0,PR_TRUE); + { + const nsAReadableString& commentValue = aToken->GetStringValue(); + result=WriteTag(mCommentTag,commentValue,0,PR_TRUE); + } break; case eToken_doctypeDecl: { - result=WriteTag(mDocTypeTag,aToken,0,PR_TRUE); + const nsAReadableString& doctypeValue = aToken->GetStringValue(); + result=WriteTag(mDocTypeTag,doctypeValue,0,PR_TRUE); } break; case eToken_newline: - mLineNumber++; //now fall through... + { + const nsAReadableString& newlineValue = aToken->GetStringValue(); + mLineNumber++; + result=WriteTag(mText,newlineValue,0,PR_FALSE); + } + break; + case eToken_whitespace: - result=WriteTag(mText,aToken,0,PR_FALSE); + { + const nsAReadableString& wsValue = aToken->GetStringValue(); + result=WriteTag(mText,wsValue,0,PR_FALSE); + } break; case eToken_text: - - if(mShowErrors) { - if((0==mValidator) || mValidator->CanContain(theParent,eHTMLTag_text)) - result=WriteTag(mText,aToken,aToken->GetAttributeCount(),PR_TRUE); - else { - AddContainmentError(eHTMLTag_text,theParent,mLineNumber); - result=WriteTagWithError(mText,aToken,aToken->GetAttributeCount(),PR_FALSE); + { + if(mShowErrors) { + const nsAReadableString& str = aToken->GetStringValue(); + if((0==mValidator) || + mValidator->CanContain(theParent,eHTMLTag_text)) + result=WriteTag(mText,str,aToken->GetAttributeCount(),PR_TRUE); + else { + AddContainmentError(eHTMLTag_text,theParent,mLineNumber); + result=WriteTagWithError(mText,str,aToken->GetAttributeCount(),PR_FALSE); + } + } + else if (mInCDATAContainer) { + // Fix bug 40809 + nsAutoString theStr; + aToken->GetSource(theStr); + theStr.ReplaceSubstring(NS_ConvertASCIItoUCS2("\r\n"), NS_ConvertASCIItoUCS2("\n")); + theStr.ReplaceChar(kCR,kLF); + result=WriteTag(mText,theStr,aToken->GetAttributeCount(),PR_TRUE); + } + else { + const nsAReadableString& str = aToken->GetStringValue(); + result=WriteTag(mText,str,aToken->GetAttributeCount(),PR_TRUE); } - } - else { - // Fix bug 40809 - nsString& theStr=aToken->GetStringValueXXX(); - theStr.ReplaceSubstring(NS_ConvertASCIItoUCS2("\r\n"), NS_ConvertASCIItoUCS2("\n")); - theStr.ReplaceChar(kCR,kLF); - result=WriteTag(mText,theStr,aToken->GetAttributeCount(),PR_TRUE); } break; @@ -1309,20 +1186,19 @@ NS_IMETHODIMP CViewSourceHTML::HandleToken(CToken* aToken,nsIParser* aParser) { case eToken_entity: { nsAutoString theStr; - nsString& theEntity=aToken->GetStringValueXXX(); - if(!theEntity.EqualsWithConversion("XI",IGNORE_CASE)) { - PRUnichar theChar=theEntity.CharAt(0); + theStr.Assign(aToken->GetStringValue()); + if(!theStr.EqualsWithConversion("XI",IGNORE_CASE)) { + PRUnichar theChar=theStr.CharAt(0); if((nsCRT::IsAsciiDigit(theChar)) || ('X'==theChar) || ('x'==theChar)){ - theStr.AppendWithConversion("#"); + theStr.InsertWithConversion("#", 0); } - theStr.Append(theEntity); } result=WriteTag(mEntityTag,theStr,0,PR_FALSE); } break; case eToken_instruction: - result=WriteTag(mPITag,aToken,0,PR_TRUE); + result=WriteTag(mPITag,aToken->GetStringValue(),0,PR_TRUE); default: result=NS_OK; diff --git a/mozilla/parser/htmlparser/src/nsViewSourceHTML.h b/mozilla/parser/htmlparser/src/nsViewSourceHTML.h index 55dfb612775..9eb3421ba57 100644 --- a/mozilla/parser/htmlparser/src/nsViewSourceHTML.h +++ b/mozilla/parser/htmlparser/src/nsViewSourceHTML.h @@ -237,18 +237,13 @@ class CViewSourceHTML: public nsIDTD { virtual PRBool IsContainer(PRInt32 aTag) const; - static nsresult WriteText(const nsString& aTextString,nsIContentSink& aSink,PRBool aPreserveText,PRBool aPlainText); - - private: #ifdef VIEW_SOURCE_HTML - nsresult WriteTag(PRInt32 tagType,CToken* aTag,PRInt32 attrCount,PRBool aNewlineRequired); - nsresult WriteTag(PRInt32 tagType,nsString &aText,PRInt32 attrCount,PRBool aNewlineRequired); - nsresult WriteTagWithError(PRInt32 tagType,CToken* aToken,PRInt32 attrCount,PRBool aNewlineRequired); + nsresult WriteTag(PRInt32 tagType,const nsAReadableString &aText,PRInt32 attrCount,PRBool aNewlineRequired); + nsresult WriteTagWithError(PRInt32 tagType,const nsAReadableString& aToken,PRInt32 attrCount,PRBool aNewlineRequired); #else - nsresult WriteTag(nsString &anXMLName,CToken* aTag,PRInt32 attrCount,PRBool aNewlineRequired); - nsresult WriteTag(nsString &anXMLName,nsString &aText,PRInt32 attrCount,PRBool aNewlineRequired); - nsresult WriteTagWithError(nsString &theXMLTagName,CToken* aToken,PRInt32 attrCount,PRBool aNewlineRequired); + nsresult WriteTag(nsString &anXMLName,const nsAReadableString &aText,PRInt32 attrCount,PRBool aNewlineRequired); + nsresult WriteTagWithError(nsString &theXMLTagName,const nsAReadableString& aStr,PRInt32 attrCount,PRBool aNewlineRequired); #endif void AddContainmentError(eHTMLTags aChild,eHTMLTags aParent,PRInt32 aLineNumber); @@ -305,6 +300,7 @@ protected: nsString mErrors; PRBool mShowErrors; PRBool mHasOpenRoot; + PRBool mInCDATAContainer; }; extern NS_HTMLPARS nsresult NS_NewViewSourceHTML(nsIDTD** aInstancePtrResult); diff --git a/mozilla/parser/htmlparser/src/nsWellFormedDTD.cpp b/mozilla/parser/htmlparser/src/nsWellFormedDTD.cpp index bd0f9e6cbea..666c905f666 100644 --- a/mozilla/parser/htmlparser/src/nsWellFormedDTD.cpp +++ b/mozilla/parser/htmlparser/src/nsWellFormedDTD.cpp @@ -52,6 +52,7 @@ #include <ctype.h> // toupper() #include "nsString.h" +#include "nsReadableUtils.h" static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); static NS_DEFINE_IID(kIDTDIID, NS_IDTD_IID); @@ -249,7 +250,6 @@ NS_IMETHODIMP CWellFormedDTD::BuildModel(nsIParser* aParser,nsITokenizer* aToken if(aTokenizer) { nsHTMLTokenizer* oldTokenizer=mTokenizer; mTokenizer=(nsHTMLTokenizer*)aTokenizer; - nsTokenAllocator* theAllocator=aTokenizer->GetTokenAllocator(); while(NS_SUCCEEDED(result)){ if(mDTDState!=NS_ERROR_HTMLPARSER_STOPPARSING) { @@ -573,7 +573,9 @@ nsresult CWellFormedDTD::HandleCommentToken(CToken* aToken) { nsresult result=NS_OK; - mLineNumber += (aToken->GetStringValueXXX()).CountChar(kNewLine); + CCommentToken* theToken = (CCommentToken*)aToken; + mLineNumber += CountCharInReadable(theToken->GetStringValue(), + PRUnichar(kNewLine)); nsCParserNode theNode((CHTMLToken*)aToken,mLineNumber,mTokenizer->GetTokenAllocator()); result=(mSink)? mSink->AddComment(theNode):NS_OK; @@ -689,8 +691,6 @@ nsresult CWellFormedDTD::HandleErrorToken(CToken* aToken) { nsresult result=NS_OK; if(mTokenizer) { - nsTokenAllocator* theAllocator=mTokenizer->GetTokenAllocator(); - // Cycle through the remaining tokens in the token stream and handle them // These tokens were added so that content objects for the error message // are generated by the content sink diff --git a/mozilla/parser/htmlparser/src/nsXIFDTD.cpp b/mozilla/parser/htmlparser/src/nsXIFDTD.cpp index eb839a303af..539c81f95d8 100644 --- a/mozilla/parser/htmlparser/src/nsXIFDTD.cpp +++ b/mozilla/parser/htmlparser/src/nsXIFDTD.cpp @@ -164,17 +164,19 @@ public: * @return valid id, or user_defined. */ static -eXIFTags DetermineXIFTagType(const nsString& aString) +eXIFTags DetermineXIFTagType(const nsAReadableString& aString) { PRInt32 result=-1; PRInt32 cnt=sizeof(gXIFTagTable)/sizeof(nsXIFTagEntry); PRInt32 low=0; PRInt32 high=cnt-1; PRInt32 middle=kNotFound; - + nsCAutoString tag; + tag.AssignWithConversion(aString); + while(low<=high){ middle=(PRInt32)(low+high)/2; - result=aString.CompareWithConversion(gXIFTagTable[middle].mName, PR_TRUE); + result=tag.CompareWithConversion((const char*)gXIFTagTable[middle].mName); if (result==0) return gXIFTagTable[middle].fTagID; if (result<0) @@ -460,7 +462,7 @@ nsresult nsXIFDTD::WillHandleToken(CToken* aToken,PRInt32& aType) { eXIFTags theNewType = eXIFTag_userdefined; if((eToken_start==aType) || (eToken_end==aType)) { - nsString& name = aToken->GetStringValueXXX(); + const nsAReadableString& name = aToken->GetStringValue(); theNewType=DetermineXIFTagType(name); if (theNewType != eXIFTag_userdefined) { aToken->SetTypeID(theNewType); @@ -714,7 +716,8 @@ nsresult nsXIFDTD::HandleContainer(nsIParserNode& aNode) { theTagID=nsHTMLTags::LookupTag(theTagName); - theNode->mToken->Reinitialize(theTagID,theTagName); + CToken* theToken = mTokenAllocator->CreateTokenOfType(eToken_start,theTagID, theTagName); + theNode->SetToken(theToken); theNode->Init(theNode->mToken,0,mTokenAllocator); } mXIFContext->Push(&aNode); @@ -810,8 +813,9 @@ nsresult nsXIFDTD::HandleCommentToken(CToken* aToken, nsIParserNode& aNode) { nsAutoString fragment; PRBool done=PR_FALSE; PRBool inContent=PR_FALSE; - nsString& comment=aToken->GetStringValueXXX(); - comment.AssignWithConversion("<!--"); // overwrite comment with "<!--" + CCommentToken* theToken = (CCommentToken*)aToken; + nsAutoString comment; + comment.AssignWithConversion("<!--"); while (!done && NS_SUCCEEDED(result)) { token=mTokenizer->PopToken(); @@ -819,7 +823,7 @@ nsresult nsXIFDTD::HandleCommentToken(CToken* aToken, nsIParserNode& aNode) { if(!token) return result; type=(eHTMLTokenTypes)token->GetTokenType(); - fragment.Assign(token->GetStringValueXXX()); + fragment.Assign(token->GetStringValue()); if(fragment.EqualsWithConversion("content")) { if(type==eToken_start) inContent=PR_TRUE; @@ -827,6 +831,7 @@ nsresult nsXIFDTD::HandleCommentToken(CToken* aToken, nsIParserNode& aNode) { } else if(fragment.EqualsWithConversion("comment")) { comment.AppendWithConversion("-->"); + theToken->SetStringValue(comment); result=(mSink)? mSink->AddComment(aNode):NS_OK; done=PR_TRUE; } @@ -862,8 +867,7 @@ nsresult nsXIFDTD::HandleAttributeToken(CToken* aToken,nsIParserNode& aNode) { if(hasValue) { CToken* attribute = mTokenAllocator->CreateTokenOfType(eToken_attribute,eHTMLTag_unknown,theValue); - nsString& key=((CAttributeToken*)attribute)->GetKey(); - key=theKey; // set the new key on the attribute.. + ((CAttributeToken*)attribute)->SetKey(theKey); // set the new key on the attribute.. thePeekNode->AddAttribute(attribute); } } @@ -985,7 +989,7 @@ PRBool nsXIFDTD::GetAttribute(const nsIParserNode& aNode, const nsString& aKey, PRInt32 count = aNode.GetAttributeCount(); for (i = 0; i < count; i++) { - const nsString& key = aNode.GetKeyAt(i); + const nsAReadableString& key = aNode.GetKeyAt(i); if (key.Equals(aKey)) { const nsString& value = aNode.GetValueAt(i); @@ -1014,7 +1018,7 @@ PRBool nsXIFDTD::GetAttributePair(nsIParserNode& aNode, nsString& aKey, nsString for (i = 0; i < count; i++) { - const nsString& k = aNode.GetKeyAt(i); + const nsAReadableString& k = aNode.GetKeyAt(i); const nsString& v = aNode.GetValueAt(i); nsAutoString key; key.Assign(k); @@ -1094,8 +1098,8 @@ nsresult nsXIFDTD::AddLeaf(const nsIParserNode& aNode) break; case eXIFTag_text: if(theToken) { - nsString& temp =theToken->GetStringValueXXX(); - if (temp.EqualsWithConversion("<xml version=\"1.0\"?>")) handled=PR_TRUE; + const nsAReadableString& temp =theToken->GetStringValue(); + if (temp.Equals(NS_LITERAL_STRING("<xml version=\"1.0\"?>"))) handled=PR_TRUE; } break; default: @@ -1332,18 +1336,19 @@ nsresult nsXIFDTD::ProcessEntityTag(const nsIParserNode& aNode) // That's totally worng. if (GetAttribute(aNode,NS_ConvertToString("value"),value)) { value.AppendWithConversion(';'); - CToken* entity=((nsCParserNode&)aNode).mToken; + CToken* entity = mTokenAllocator->CreateTokenOfType(eToken_entity, eHTMLTag_entity, value); if(entity) { - entity->Reinitialize(eHTMLTag_entity,value); nsCParserNode* thePeekNode=(nsCParserNode*)mXIFContext->PeekNode(); if(thePeekNode) { eHTMLTags theTag=(eHTMLTags)thePeekNode->mToken->GetTypeID(); if(theTag==eHTMLTag_script || theTag==eHTMLTag_style) { nsAutoString scratch; ((CEntityToken*)entity)->TranslateToUnicodeStr(scratch); // Ex. > would become '<' - entity->Reinitialize(eHTMLTag_text,scratch); // Covert type to text and set the translated value. + IF_FREE(entity); + entity = mTokenAllocator->CreateTokenOfType(eToken_text, eHTMLTag_text, scratch); } } + // XXX Casting from an interface down to a class? For shame! ((nsCParserNode&)aNode).Init(entity,mLineNumber,mTokenAllocator); } result=mSink->AddLeaf(aNode); @@ -1364,10 +1369,10 @@ nsresult nsXIFDTD::BeginCSSStyleSheet(const nsIParserNode& aNode) PRInt32 error; nsAutoString value; - CToken* theToken=((nsCParserNode&)aNode).mToken; - + CToken* theToken=mTokenAllocator->CreateTokenOfType(eToken_start, eHTMLTag_style, NS_ConvertASCIItoUCS2("style")); + if(theToken) { - theToken->Reinitialize(eHTMLTag_style,NS_ConvertASCIItoUCS2("style")); + ((nsCParserNode&)aNode).SetToken(theToken); mXIFContext->Push(&aNode); } diff --git a/mozilla/parser/htmlparser/src/nsXMLTokenizer.cpp b/mozilla/parser/htmlparser/src/nsXMLTokenizer.cpp index 49a151e320c..c314c6d270b 100644 --- a/mozilla/parser/htmlparser/src/nsXMLTokenizer.cpp +++ b/mozilla/parser/htmlparser/src/nsXMLTokenizer.cpp @@ -160,26 +160,19 @@ nsTokenAllocator* nsXMLTokenizer::GetTokenAllocator(void) { static nsresult ConsumeConditional(nsScanner& aScanner,const nsString& aMatchString,PRBool& aMatch) { nsresult result=NS_OK; - PRUnichar matchChar; + nsAutoString str; + PRUint32 len = aMatchString.Length(); - PRInt32 i, count = aMatchString.Length(); - for (i=0; i < count; i++) { - result = aScanner.GetChar(matchChar); - if ((NS_OK != result) || (aMatchString.CharAt(i) != matchChar)) { - break; - } + result = aScanner.Peek(str, len); + if ((NS_OK == result) && str.Equals(aMatchString)) { + aMatch = PR_TRUE; + nsReadingIterator<PRUnichar> curPos; + aScanner.CurrentPosition(curPos); + curPos.advance(len); + aScanner.SetPosition(curPos); } - - if (NS_OK == result) { - if (i != count) { - for (; i >= 0; i--) { - aScanner.PutBack(aMatchString.CharAt(i)); - } - aMatch = PR_FALSE; - } - else { - aMatch = PR_TRUE; - } + else { + aMatch = PR_FALSE; } return result; diff --git a/mozilla/parser/htmlparser/tests/logparse/makefile.win b/mozilla/parser/htmlparser/tests/logparse/makefile.win index 020ba2b7c8a..35c79551e38 100644 --- a/mozilla/parser/htmlparser/tests/logparse/makefile.win +++ b/mozilla/parser/htmlparser/tests/logparse/makefile.win @@ -1,4 +1,4 @@ -!#!nmake +#!nmake # # The contents of this file are subject to the Netscape Public # License Version 1.1 (the "License"); you may not use this file @@ -23,10 +23,10 @@ DEPTH=..\..\.. MAKE_OBJ_TYPE = EXE -PROGRAM = .\$(OBJDIR)\logparse.exe +PROGRAM = .\$(OBJDIR)\TestParser.exe OBJS = \ - .\$(OBJDIR)\logparse.obj \ + .\$(OBJDIR)\TestParser.obj \ $(NULL) LINCS= \ @@ -52,4 +52,4 @@ install:: $(PROGRAM) $(MAKE_INSTALL) $(PROGRAM) $(DIST)\bin clobber:: - rm -f $(DIST)\bin\logparse.exe + rm -f $(DIST)\bin\TestParser.exe diff --git a/mozilla/parser/htmlparser/tests/outsinks/Convert.cpp b/mozilla/parser/htmlparser/tests/outsinks/Convert.cpp index 869e371f913..288a9e968e9 100644 --- a/mozilla/parser/htmlparser/tests/outsinks/Convert.cpp +++ b/mozilla/parser/htmlparser/tests/outsinks/Convert.cpp @@ -88,7 +88,9 @@ Compare(nsString& str, nsString& aFileName) return 0; else { - char* cstr = str.ToNewUTF8String(); + nsAutoString left; + str.Left(left, different); + char* cstr = left.ToNewUTF8String(); printf("Comparison failed at char %d:\n-----\n%s\n-----\n", different, cstr); Recycle(cstr); diff --git a/mozilla/string/obsolete/nsStr.h b/mozilla/string/obsolete/nsStr.h index 631687c8cf1..fbe62321288 100644 --- a/mozilla/string/obsolete/nsStr.h +++ b/mozilla/string/obsolete/nsStr.h @@ -484,7 +484,7 @@ inline void Recycle( PRUnichar* aBuffer) { nsMemory::Free(aBuffer); } * @param anIndex tells us where in dest to get the char from * @return the given char, or 0 if anIndex is out of range */ -inline PRUnichar GetCharAt(const nsStr& aDest,PRUint32 anIndex){ +inline PRUnichar GetCharAt(const nsStr& aDest,PRUint32 anIndex) { if(anIndex<aDest.mLength) { return (eTwoByte==aDest.mCharSize) ? aDest.mUStr[anIndex] : (PRUnichar)aDest.mStr[anIndex]; }//if diff --git a/mozilla/string/obsolete/nsString.cpp b/mozilla/string/obsolete/nsString.cpp index ff3129d4c0e..92624c14d6b 100644 --- a/mozilla/string/obsolete/nsString.cpp +++ b/mozilla/string/obsolete/nsString.cpp @@ -473,7 +473,7 @@ nsCString::ReplaceSubstring(const nsCString& aTarget,const nsCString& aNewValue) * @param * @return *this */ -PRInt32 nsCString::CountChar(PRUnichar aChar) { +PRInt32 nsCString::CountChar(PRUnichar aChar) const { PRInt32 theIndex=0; PRInt32 theCount=0; PRInt32 theLen=(PRInt32)mLength; diff --git a/mozilla/string/obsolete/nsString.h b/mozilla/string/obsolete/nsString.h index 446200f3855..4ab205c2b29 100644 --- a/mozilla/string/obsolete/nsString.h +++ b/mozilla/string/obsolete/nsString.h @@ -204,7 +204,7 @@ public: void ReplaceSubstring(const nsCString& aTarget,const nsCString& aNewValue); void ReplaceSubstring(const char* aTarget,const char* aNewValue); - PRInt32 CountChar(PRUnichar aChar); + PRInt32 CountChar(PRUnichar aChar) const; /** * This method trims characters found in aTrimSet from diff --git a/mozilla/string/obsolete/nsString2.cpp b/mozilla/string/obsolete/nsString2.cpp index ad0611f101c..6e8434be662 100644 --- a/mozilla/string/obsolete/nsString2.cpp +++ b/mozilla/string/obsolete/nsString2.cpp @@ -500,7 +500,7 @@ nsString::ReplaceSubstring(const nsString& aTarget,const nsString& aNewValue){ * @param * @return *this */ -PRInt32 nsString::CountChar(PRUnichar aChar) { +PRInt32 nsString::CountChar(PRUnichar aChar) const { PRInt32 theIndex=0; PRInt32 theCount=0; PRInt32 theLen=(PRInt32)mLength; diff --git a/mozilla/string/obsolete/nsString2.h b/mozilla/string/obsolete/nsString2.h index 1d4edabfdf7..b0fc4f310b9 100644 --- a/mozilla/string/obsolete/nsString2.h +++ b/mozilla/string/obsolete/nsString2.h @@ -242,7 +242,7 @@ public: void ReplaceSubstring( const nsString& aTarget, const nsString& aNewValue ); void ReplaceSubstring( const PRUnichar* aTarget, const PRUnichar* aNewValue ); - PRInt32 CountChar( PRUnichar aChar ); + PRInt32 CountChar( PRUnichar aChar ) const; /** * This method trims characters found in aTrimSet from diff --git a/mozilla/string/public/nsAlgorithm.h b/mozilla/string/public/nsAlgorithm.h index b5360b07aaf..9c2e5855cc1 100755 --- a/mozilla/string/public/nsAlgorithm.h +++ b/mozilla/string/public/nsAlgorithm.h @@ -109,5 +109,4 @@ copy_string_backward( const InputIterator& first, InputIterator& last, OutputIte return result; } - #endif // !defined(nsAlgorithm_h___) diff --git a/mozilla/string/public/nsBufferHandle.h b/mozilla/string/public/nsBufferHandle.h index e3004276127..b8cf0688dba 100755 --- a/mozilla/string/public/nsBufferHandle.h +++ b/mozilla/string/public/nsBufferHandle.h @@ -86,7 +86,7 @@ class nsSharedBufferHandle nsSharedBufferHandle( CharT* aDataStart, CharT* aDataEnd ) : nsBufferHandle<CharT>(aDataStart, aDataEnd) { - mFlags |= kIsShared; + mFlags = kIsShared; } ~nsSharedBufferHandle(); diff --git a/mozilla/string/public/nsReadableUtils.h b/mozilla/string/public/nsReadableUtils.h index 5a7bd9285b9..33b6c6ec254 100755 --- a/mozilla/string/public/nsReadableUtils.h +++ b/mozilla/string/public/nsReadableUtils.h @@ -35,10 +35,8 @@ #include "nsAWritableString.h" #endif -#if 0 NS_COM size_t Distance( const nsReadingIterator<PRUnichar>&, const nsReadingIterator<PRUnichar>& ); NS_COM size_t Distance( const nsReadingIterator<char>&, const nsReadingIterator<char>& ); -#endif NS_COM void CopyUCS2toASCII( const nsAReadableString& aSource, nsAWritableCString& aDest ); @@ -115,15 +113,46 @@ NS_COM PRUnichar* ToNewUnicode( const nsAReadableCString& aSource ); * After this operation |aDest| is not null terminated. * * @param aSource a 16-bit wide string + * @param aSrcOffset start offset in the source string * @param aDest a |PRUnichar| buffer * @param aLength the number of 16-bit characters to copy * @return pointer to destination buffer - identical to |aDest| */ NS_COM PRUnichar* CopyUnicodeTo( const nsAReadableString& aSource, + PRUint32 aSrcOffset, PRUnichar* aDest, PRUint32 aLength ); + /** + * Copies 16-bit characters between iterators |aSrcStart| and + * |aSrcEnd| to the writable string |aDest|. Similar to the + * |nsString::Mid| method. + * + * After this operation |aDest| is not null terminated. + * + * @param aSrcStart start source iterator + * @param aSrcEnd end source iterator + * @param aDest destination for the copy + */ +NS_COM void CopyUnicodeTo( const nsReadingIterator<PRUnichar>& aSrcStart, + const nsReadingIterator<PRUnichar>& aSrcEnd, + nsAWritableString& aDest ); + + /** + * Appends 16-bit characters between iterators |aSrcStart| and + * |aSrcEnd| to the writable string |aDest|. + * + * After this operation |aDest| is not null terminated. + * + * @param aSrcStart start source iterator + * @param aSrcEnd end source iterator + * @param aDest destination for the copy + */ +NS_COM void AppendUnicodeTo( const nsReadingIterator<PRUnichar>& aSrcStart, + const nsReadingIterator<PRUnichar>& aSrcEnd, + nsAWritableString& aDest ); + /** * Returns |PR_TRUE| if |aString| contains only ASCII characters, that is, characters in the range (0x00, 0x7F). * @@ -142,4 +171,47 @@ NS_COM void ToUpperCase( nsAWritableCString& ); NS_COM void ToLowerCase( nsAWritableString& ); NS_COM void ToLowerCase( nsAWritableCString& ); + /** + * Finds the leftmost occurance of |aPattern|, if any in the range |aSearchStart|..|aSearchEnd|. + * + * Returns |PR_TRUE| if a match was found, and adjusts |aSearchStart| and |aSearchEnd| to + * point to the match. If no match was found, returns |PR_FALSE| and makes |aSearchStart == aSearchEnd|. + * + * Currently, this is equivalent to the O(m*n) implementation previously on |ns[C]String|. + * If we need something faster; we can implement that later. + */ +NS_COM PRBool FindInReadable( const nsAReadableString& aPattern, nsReadingIterator<PRUnichar>&, nsReadingIterator<PRUnichar>& ); +NS_COM PRBool FindInReadable( const nsAReadableCString& aPattern, nsReadingIterator<char>&, nsReadingIterator<char>& ); + + + /** + * Finds the rightmost occurance of |aPattern| + * Returns |PR_TRUE| if a match was found, and adjusts |aSearchStart| and |aSearchEnd| to + * point to the match. If no match was found, returns |PR_FALSE| and makes |aSearchStart == aSearchEnd|. + * + * Currently, this is equivalent to the O(m*n) implementation previously on |ns[C]String|. + * If we need something faster; we can implement that later. + */ +NS_COM PRBool RFindInReadable( const nsAReadableString& aPattern, nsReadingIterator<PRUnichar>&, nsReadingIterator<PRUnichar>& ); +NS_COM PRBool RFindInReadable( const nsAReadableCString& aPattern, nsReadingIterator<char>&, nsReadingIterator<char>& ); + + /** + * Finds the leftmost occurance of |aChar|, if any in the range + * |aSearchStart|..|aSearchEnd|. + * + * Returns |PR_TRUE| if a match was found, and adjusts |aSearchStart| to + * point to the match. If no match was found, returns |PR_FALSE| and + * makes |aSearchStart == aSearchEnd|. + */ +NS_COM PRBool FindCharInReadable( PRUnichar aChar, nsReadingIterator<PRUnichar>&, nsReadingIterator<PRUnichar>& ); +NS_COM PRBool FindCharInReadable( char aChar, nsReadingIterator<char>&, nsReadingIterator<char>& ); + + /** + * Finds the number of occurences of |aChar| in the string |aStr| + */ +NS_COM PRUint32 CountCharInReadable( const nsAReadableString& aStr, + PRUnichar aChar ); +NS_COM PRUint32 CountCharInReadable( const nsAReadableCString& aStr, + char aChar ); + #endif // !defined(nsReadableUtils_h___) diff --git a/mozilla/string/public/nsSharedBufferList.h b/mozilla/string/public/nsSharedBufferList.h index c740d399328..38213b1190e 100755 --- a/mozilla/string/public/nsSharedBufferList.h +++ b/mozilla/string/public/nsSharedBufferList.h @@ -40,6 +40,12 @@ // for |nsReadingIterator| #endif +#ifndef nsBufferHandleUtils_h___ +#include "nsBufferHandleUtils.h" + // for |NS_AllocateContiguousHandleWithData| +#endif + + /** * This class forms the basis for several multi-fragment string classes, in * particular: |nsFragmentedString| (though not yet), and |nsSlidingString|/|nsSlidingSubstring|. @@ -63,6 +69,27 @@ class nsSharedBufferList this->mFlags |= this->kIsSingleAllocationWithBuffer; } + /** + * These buffers will be `owned' by the list, and only the + * the list itself will be allowed to delete member |Buffer|s, + * therefore, we cannot use the inherited |AcquireReference| + * and |ReleaseReference|, as they use the model that the + * buffer manages its own lifetime. + */ + void + AcquireNonOwningReference() const + { + Buffer* mutable_this = NS_CONST_CAST(Buffer*, this); + mutable_this->set_refcount( get_refcount()+1 ); + } + + void + ReleaseNonOwningReference() const + { + Buffer* mutable_this = NS_CONST_CAST(Buffer*, this); + mutable_this->set_refcount( get_refcount()-1 ); + } + Buffer* mPrev; Buffer* mNext; @@ -108,6 +135,9 @@ class nsSharedBufferList // Position( const Position& ); -- automatically generated copy-constructor is OK // Position& operator=( const Position& ); -- automatically generated copy-assignment operator is OK + + // don't want to provide this as |operator-|, since that might imply O(1) + static ptrdiff_t Distance( const Position&, const Position& ); }; @@ -137,8 +167,20 @@ class nsSharedBufferList Buffer* UnlinkBuffer( Buffer* ); void SplitBuffer( const Position& ); - static Buffer* NewSingleAllocationBuffer( const PRUnichar*, PRUint32, PRUint32 = 0 ); - static Buffer* NewWrappingBuffer( PRUnichar*, PRUnichar*, PRUnichar* ); + static + Buffer* + NewSingleAllocationBuffer( const PRUnichar* aData, PRUint32 aDataLength, PRUint32 aAdditionalCapacity = 1 ) + { + typedef Buffer* Buffer_ptr; + return NS_AllocateContiguousHandleWithData(Buffer_ptr(0), nsLiteralString(aData, aDataLength), aAdditionalCapacity); + } + + static + Buffer* + NewWrappingBuffer( PRUnichar* aDataStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd ) + { + return new Buffer(aDataStart, aDataEnd, aDataStart, aStorageEnd); + } void DiscardSuffix( PRUint32 ); // need other discards: prefix, and by iterator or pointer or something diff --git a/mozilla/string/public/nsSlidingString.h b/mozilla/string/public/nsSlidingString.h index 6dc2e55210d..af36acc39eb 100755 --- a/mozilla/string/public/nsSlidingString.h +++ b/mozilla/string/public/nsSlidingString.h @@ -45,7 +45,7 @@ * of the list. |nsSlidingString| also the client to advance its starting point. * */ -class nsSlidingSharedBufferList +class NS_COM nsSlidingSharedBufferList : public nsSharedBufferList { public: @@ -63,35 +63,86 @@ class nsSlidingSharedBufferList +class nsSlidingString; /** * a substring over a buffer list, this */ -class nsSlidingSubstring - : public nsPromiseReadable<PRUnichar> +class NS_COM nsSlidingSubstring + : virtual public nsPromiseReadable<PRUnichar> { + friend class nsSlidingString; + public: typedef nsSlidingSharedBufferList::Buffer Buffer; typedef nsSlidingSharedBufferList::Position Position; + nsSlidingSubstring() + : mStart(0,0), + mEnd(0,0), + mBufferList(0), + mLength(0) + { + // nothing else to do here + } + nsSlidingSubstring( const nsSlidingSubstring& ); // copy-constructor nsSlidingSubstring( const nsSlidingSubstring& aString, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd ); + nsSlidingSubstring( const nsSlidingString& ); + nsSlidingSubstring( const nsSlidingString& aString, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd ); + explicit nsSlidingSubstring( const nsAReadableString& ); + // copy the supplied string into a new buffer ... there will be no modifying instance over this buffer list + + void Rebind( const nsSlidingSubstring& ); + void Rebind( const nsSlidingSubstring&, const nsReadingIterator<PRUnichar>&, const nsReadingIterator<PRUnichar>& ); + void Rebind( const nsSlidingString& ); + void Rebind( const nsSlidingString&, const nsReadingIterator<PRUnichar>&, const nsReadingIterator<PRUnichar>& ); + void Rebind( const nsAReadableString& ); + ~nsSlidingSubstring(); virtual PRUint32 Length() const { return mLength; } protected: - nsSlidingSubstring( nsSlidingSharedBufferList& aBufferList ); + nsSlidingSubstring( nsSlidingSharedBufferList* aBufferList ); virtual const PRUnichar* GetReadableFragment( nsReadableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) const; private: // can't assign into me, I'm a read-only reference void operator=( const nsSlidingSubstring& ); // NOT TO BE IMPLEMENTED + void + init_range_from_buffer_list() + // used only from constructors + { + mStart.PointBefore(mBufferList->GetFirstBuffer()); + mEnd.PointAfter(mBufferList->GetLastBuffer()); + mLength = PRUint32(Position::Distance(mStart, mEnd)); + } + + void + acquire_ownership_of_buffer_list() const + // used only from constructors and |Rebind|, requires |mStart| already be initialized + { + mBufferList->AcquireReference(); + mStart.mBuffer->AcquireNonOwningReference(); + } + + void + release_ownership_of_buffer_list() + { + if ( mBufferList ) + { + mStart.mBuffer->ReleaseNonOwningReference(); + mBufferList->DiscardUnreferencedPrefix(mStart.mBuffer); + mBufferList->ReleaseReference(); + } + } + protected: Position mStart; Position mEnd; - nsSlidingSharedBufferList& mBufferList; + nsSlidingSharedBufferList* mBufferList; PRUint32 mLength; }; @@ -102,14 +153,19 @@ class nsSlidingSubstring * An |nsSlidingSharedBufferList| may be modified by zero or one instances of this class. * */ -class nsSlidingString - : public nsSlidingSubstring +class NS_COM nsSlidingString + : virtual public nsPromiseReadable<PRUnichar>, + private nsSlidingSubstring { + friend class nsSlidingSubstring; + public: nsSlidingString( PRUnichar* aStorageStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd ); // ...created by consuming ownership of a buffer ... |aStorageStart| must point to something // that it will be OK for the slidking string to call |nsMemory::Free| on + virtual PRUint32 Length() const { return mLength; } + // you are giving ownership to the string, it takes and keeps your buffer, deleting it (with |nsMemory::Free|) when done void AppendBuffer( PRUnichar* aStorageStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd ); @@ -118,18 +174,21 @@ class nsSlidingString void DiscardPrefix( const nsReadingIterator<PRUnichar>& ); // any other way you want to do this? + protected: + virtual const PRUnichar* GetReadableFragment( nsReadableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) const; + private: + + void + acquire_ownership_of_buffer_list() const + // used only from constructors and |Rebind|, requires |mStart| already be initialized + { + mBufferList->AcquireReference(); + mStart.mBuffer->AcquireNonOwningReference(); + } + nsSlidingString( const nsSlidingString& ); // NOT TO BE IMPLEMENTED void operator=( const nsSlidingString& ); // NOT TO BE IMPLEMENTED }; - -#if 0 - // this (or something similar) is what should appear in the parser, I think -#include "nsSlidingString.h" - -typedef nsSlidingString nsParserString; -typedef nsSlidingSubstring nsParserToken; -#endif - #endif // !defined(nsSlidingString_h___) diff --git a/mozilla/string/src/nsReadableUtils.cpp b/mozilla/string/src/nsReadableUtils.cpp index a2101512940..e05326fcc4b 100755 --- a/mozilla/string/src/nsReadableUtils.cpp +++ b/mozilla/string/src/nsReadableUtils.cpp @@ -229,14 +229,43 @@ ToNewUnicode( const nsAReadableCString& aSource ) NS_COM PRUnichar* -CopyUnicodeTo( const nsAReadableString& aSource, PRUnichar* aDest, PRUint32 aLength ) +CopyUnicodeTo( const nsAReadableString& aSource, PRUint32 aSrcOffset, PRUnichar* aDest, PRUint32 aLength ) { nsReadingIterator<PRUnichar> fromBegin, fromEnd; - PRUnichar* toBegin = aDest; - copy_string(aSource.BeginReading(fromBegin), aSource.BeginReading(fromEnd).advance( PRInt32(aLength) ), toBegin); + PRUnichar* toBegin = aDest; + copy_string(aSource.BeginReading(fromBegin).advance( PRInt32(aSrcOffset) ), aSource.BeginReading(fromEnd).advance( PRInt32(aSrcOffset+aLength) ), toBegin); return aDest; } +NS_COM +void +CopyUnicodeTo( const nsReadingIterator<PRUnichar>& aSrcStart, + const nsReadingIterator<PRUnichar>& aSrcEnd, + nsAWritableString& aDest ) + { + nsWritingIterator<PRUnichar> writer; + aDest.SetLength(Distance(aSrcStart, aSrcEnd)); + aDest.BeginWriting(writer); + nsReadingIterator<PRUnichar> fromBegin(aSrcStart); + + copy_string(fromBegin, aSrcEnd, writer); + } + +NS_COM +void +AppendUnicodeTo( const nsReadingIterator<PRUnichar>& aSrcStart, + const nsReadingIterator<PRUnichar>& aSrcEnd, + nsAWritableString& aDest ) + { + nsWritingIterator<PRUnichar> writer; + PRUint32 oldLength = aDest.Length(); + aDest.SetLength(oldLength + Distance(aSrcStart, aSrcEnd)); + aDest.BeginWriting(writer).advance(oldLength); + nsReadingIterator<PRUnichar> fromBegin(aSrcStart); + + copy_string(fromBegin, aSrcEnd, writer); + } + NS_COM PRBool IsASCII( const nsAReadableString& aString ) @@ -341,3 +370,224 @@ ToLowerCase( nsAWritableCString& aCString ) ConvertToLowerCase<char> converter; copy_string(aCString.BeginWriting(fromBegin), aCString.EndWriting(fromEnd), converter); } + + +template <class CharT> +inline // probably wishful thinking +PRBool +FindInReadable_Impl( const basic_nsAReadableString<CharT>& aPattern, + nsReadingIterator<CharT>& aSearchStart, + nsReadingIterator<CharT>& aSearchEnd ) + { + PRBool found_it = PR_FALSE; + + // only bother searching at all if we're given a non-empty range to search + if ( aSearchStart != aSearchEnd ) + { + nsReadingIterator<CharT> aPatternStart, aPatternEnd; + aPattern.BeginReading(aPatternStart); + aPattern.EndReading(aPatternEnd); + + // outer loop keeps searching till we find it or run out of string to search + while ( !found_it ) + { + // fast inner loop (that's what it's called, not what it is) looks for a potential match + while ( aSearchStart != aSearchEnd && *aPatternStart != *aSearchStart ) + ++aSearchStart; + + // if we broke out of the `fast' loop because we're out of string ... we're done: no match + if ( aSearchStart == aSearchEnd ) + break; + + // otherwise, we're at a potential match, let's see if we really hit one + nsReadingIterator<CharT> testPattern(aPatternStart); + nsReadingIterator<CharT> testSearch(aSearchStart); + + // slow inner loop verifies the potential match (found by the `fast' loop) at the current position + for(;;) + { + // we already compared the first character in the outer loop, + // so we'll advance before the next comparison + ++testPattern; + ++testSearch; + + // if we verified all the way to the end of the pattern, then we found it! + if ( testPattern == aPatternEnd ) + { + found_it = PR_TRUE; + aSearchEnd = testSearch; // return the exact found range through the parameters + break; + } + + // if we got to end of the string we're searching before we hit the end of the + // pattern, we'll never find what we're looking for + if ( testSearch == aSearchEnd ) + { + aSearchStart = aSearchEnd; + break; + } + + // else if we mismatched ... it's time to advance to the next search position + // and get back into the `fast' loop + if ( *testPattern != *testSearch ) + { + ++aSearchStart; + break; + } + } + } + } + + return found_it; + } + +NS_COM +PRBool +FindInReadable( const nsAReadableString& aPattern, nsReadingIterator<PRUnichar>& aSearchStart, nsReadingIterator<PRUnichar>& aSearchEnd ) + { + return FindInReadable_Impl(aPattern, aSearchStart, aSearchEnd); + } + +NS_COM +PRBool +FindInReadable( const nsAReadableCString& aPattern, nsReadingIterator<char>& aSearchStart, nsReadingIterator<char>& aSearchEnd ) + { + return FindInReadable_Impl(aPattern, aSearchStart, aSearchEnd); + } + + /** + * This implementation is simple, but does too much work. + * It searches the entire string from left to right, and returns the last match found, if any. + * This implementation will be replaced when I get |reverse_iterator|s working. + */ +template <class CharT> +inline // probably wishful thinking +PRBool +RFindInReadable_Impl( const basic_nsAReadableString<CharT>& aPattern, + nsReadingIterator<CharT>& aSearchStart, + nsReadingIterator<CharT>& aSearchEnd ) + { + PRBool found_it = PR_FALSE; + + nsReadingIterator<CharT> savedSearchEnd(aSearchEnd); + nsReadingIterator<CharT> searchStart(aSearchStart), searchEnd(aSearchEnd); + + while ( searchStart != searchEnd ) + { + if ( FindInReadable(aPattern, searchStart, searchEnd) ) + { + found_it = PR_TRUE; + + // this is the best match so far, so remember it + aSearchStart = searchStart; + aSearchEnd = searchEnd; + + // ...and get ready to search some more + // (it's tempting to set |searchStart=searchEnd| ... but that misses overlapping patterns) + ++searchStart; + searchEnd = savedSearchEnd; + } + } + + // if we never found it, return an empty range + if ( !found_it ) + aSearchStart = aSearchEnd; + + return found_it; + } + + +NS_COM +PRBool +RFindInReadable( const nsAReadableString& aPattern, nsReadingIterator<PRUnichar>& aSearchStart, nsReadingIterator<PRUnichar>& aSearchEnd ) + { + return RFindInReadable_Impl(aPattern, aSearchStart, aSearchEnd); + } + +NS_COM +PRBool +RFindInReadable( const nsAReadableCString& aPattern, nsReadingIterator<char>& aSearchStart, nsReadingIterator<char>& aSearchEnd ) + { + return RFindInReadable_Impl(aPattern, aSearchStart, aSearchEnd); + } + + + +template <class CharT> +inline // probably wishful thinking +PRBool +FindCharInReadable_Impl( CharT aChar, + nsReadingIterator<CharT>& aSearchStart, + nsReadingIterator<CharT>& aSearchEnd ) + { + while ( aSearchStart != aSearchEnd ) + { + PRInt32 fragmentLength; + if ( SameFragment(aSearchStart, aSearchEnd) ) + fragmentLength = aSearchEnd.get() - aSearchStart.get(); + else + fragmentLength = aSearchStart.size_forward(); + + const CharT* charFoundAt = nsCharTraits<CharT>::find(aSearchStart.get(), fragmentLength, aChar); + if ( charFoundAt ) { + aSearchStart.advance( charFoundAt - aSearchStart.get() ); + return PR_TRUE; + } + + aSearchStart.advance(fragmentLength); + } + + return PR_FALSE; + } + + +NS_COM +PRBool +FindCharInReadable( PRUnichar aChar, nsReadingIterator<PRUnichar>& aSearchStart, nsReadingIterator<PRUnichar>& aSearchEnd ) + { + return FindCharInReadable_Impl(aChar, aSearchStart, aSearchEnd); + } + +NS_COM +PRBool +FindCharInReadable( char aChar, nsReadingIterator<char>& aSearchStart, nsReadingIterator<char>& aSearchEnd ) + { + return FindCharInReadable_Impl(aChar, aSearchStart, aSearchEnd); + } + +template <class CharT> +PRUint32 +CountCharInReadable_Impl( const basic_nsAReadableString<CharT>& aStr, + CharT aChar ) +{ + PRUint32 count = 0; + nsReadingIterator<CharT> begin, end; + + aStr.BeginReading(begin); + aStr.EndReading(end); + + while (begin != end) { + if (*begin == aChar) { + count++; + } + begin++; + } + + return count; +} + +NS_COM +PRUint32 +CountCharInReadable( const nsAReadableString& aStr, + PRUnichar aChar ) +{ + return CountCharInReadable_Impl(aStr, aChar); +} + +NS_COM +PRUint32 +CountCharInReadable( const nsAReadableCString& aStr, + char aChar ) +{ + return CountCharInReadable_Impl(aStr, aChar); +} diff --git a/mozilla/string/src/nsSharedBufferList.cpp b/mozilla/string/src/nsSharedBufferList.cpp index 76f50aa9eaa..584890a75ec 100755 --- a/mozilla/string/src/nsSharedBufferList.cpp +++ b/mozilla/string/src/nsSharedBufferList.cpp @@ -23,9 +23,29 @@ */ #include "nsSharedBufferList.h" + +#ifndef nsAlgorithm_h___ #include "nsAlgorithm.h" // for |copy_string| -#include <new.h> +#endif + + +ptrdiff_t +nsSharedBufferList::Position::Distance( const Position& aStart, const Position& aEnd ) + { + ptrdiff_t result = 0; + if ( aStart.mBuffer == aEnd.mBuffer ) + result = aEnd.mPosInBuffer - aStart.mPosInBuffer; + else + { + result = aStart.mBuffer->DataEnd() - aStart.mPosInBuffer; + for ( Buffer* b = aStart.mBuffer->mNext; b != aEnd.mBuffer; b = b->mNext ) + result += b->DataLength(); + result += aEnd.mPosInBuffer - aEnd.mBuffer->DataStart(); + } + + return result; + } void @@ -48,36 +68,6 @@ nsSharedBufferList::~nsSharedBufferList() } -nsSharedBufferList::Buffer* -nsSharedBufferList::NewSingleAllocationBuffer( const PRUnichar* aData, PRUint32 aDataLength, PRUint32 aAdditionalSpace ) - { - size_t object_size = ((sizeof(Buffer) + sizeof(PRUnichar) - 1) / sizeof(PRUnichar)) * sizeof(PRUnichar); - PRUint32 buffer_length = aDataLength + aAdditionalSpace; - size_t buffer_size = size_t(buffer_length) * sizeof(PRUnichar); - - void* object_ptr = operator new(object_size + buffer_size); - if ( object_ptr ) - { - typedef PRUnichar* PRUnichar_ptr; - PRUnichar* buffer_ptr = PRUnichar_ptr(NS_STATIC_CAST(unsigned char*, object_ptr) + object_size); - if ( aDataLength ) - { - PRUnichar* toBegin = buffer_ptr; - copy_string(aData, aData+aDataLength, toBegin); - } - return new (object_ptr) Buffer(buffer_ptr, buffer_ptr+aDataLength, buffer_ptr, buffer_ptr+buffer_length, PR_TRUE); - } - - return 0; - } - -nsSharedBufferList::Buffer* -nsSharedBufferList::NewWrappingBuffer( PRUnichar* aDataStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd ) - { - return new Buffer(aDataStart, aDataEnd, aDataStart, aStorageEnd); - } - - void nsSharedBufferList::LinkBuffer( Buffer* aPrevBuffer, Buffer* aNewBuffer, Buffer* aNextBuffer ) diff --git a/mozilla/string/src/nsSlidingString.cpp b/mozilla/string/src/nsSlidingString.cpp index 58c7698c3d4..8b07b17256e 100755 --- a/mozilla/string/src/nsSlidingString.cpp +++ b/mozilla/string/src/nsSlidingString.cpp @@ -24,6 +24,18 @@ #include "nsSlidingString.h" +#ifndef nsBufferHandleUtils_h___ +#include "nsBufferHandleUtils.h" +#endif + +#include <new.h> + + + + /** + * |nsSlidingSharedBufferList| + */ + void nsSlidingSharedBufferList::DiscardUnreferencedPrefix( Buffer* aRecentlyReleasedBuffer ) { @@ -35,62 +47,159 @@ nsSlidingSharedBufferList::DiscardUnreferencedPrefix( Buffer* aRecentlyReleasedB } -ptrdiff_t Distance( const nsSharedBufferList::Position&, const nsSharedBufferList::Position& ); -ptrdiff_t -Distance( const nsSharedBufferList::Position& aStart, const nsSharedBufferList::Position& aEnd ) - { - ptrdiff_t result = 0; - if ( aStart.mBuffer == aEnd.mBuffer ) - result = aEnd.mPosInBuffer - aStart.mPosInBuffer; - else - { - result = aStart.mBuffer->DataEnd() - aStart.mPosInBuffer; - for ( nsSharedBufferList::Buffer* b = aStart.mBuffer->mNext; b != aEnd.mBuffer; b = b->mNext ) - result += b->DataLength(); - result += aEnd.mPosInBuffer - aEnd.mBuffer->DataStart(); - } - - return result; - } + /** + * |nsSlidingSubstring| + */ + // copy constructor nsSlidingSubstring::nsSlidingSubstring( const nsSlidingSubstring& aString ) : mStart(aString.mStart), mEnd(aString.mEnd), mBufferList(aString.mBufferList), mLength(aString.mLength) { - mBufferList.AcquireReference(); - mStart.mBuffer->AcquireReference(); + acquire_ownership_of_buffer_list(); } nsSlidingSubstring::nsSlidingSubstring( const nsSlidingSubstring& aString, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd ) : mStart(aStart), mEnd(aEnd), mBufferList(aString.mBufferList), - mLength(PRUint32(Distance(mStart, mEnd))) + mLength(PRUint32(Position::Distance(mStart, mEnd))) { - mBufferList.AcquireReference(); - mStart.mBuffer->AcquireReference(); + acquire_ownership_of_buffer_list(); } -nsSlidingSubstring::nsSlidingSubstring( nsSlidingSharedBufferList& aBufferList ) +nsSlidingSubstring::nsSlidingSubstring( const nsSlidingString& aString ) + : mStart(aString.mStart), + mEnd(aString.mEnd), + mBufferList(aString.mBufferList), + mLength(aString.mLength) + { + acquire_ownership_of_buffer_list(); + } + +nsSlidingSubstring::nsSlidingSubstring( const nsSlidingString& aString, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd ) + : mStart(aStart), + mEnd(aEnd), + mBufferList(aString.mBufferList), + mLength(PRUint32(Position::Distance(mStart, mEnd))) + { + acquire_ownership_of_buffer_list(); + } + +nsSlidingSubstring::nsSlidingSubstring( nsSlidingSharedBufferList* aBufferList ) : mBufferList(aBufferList) { - mBufferList.AcquireReference(); + init_range_from_buffer_list(); + acquire_ownership_of_buffer_list(); + } - mStart.PointBefore(mBufferList.GetFirstBuffer()); - mStart.mBuffer->AcquireReference(); +typedef const nsSharedBufferList::Buffer* Buffer_ptr; - mEnd.PointAfter(mBufferList.GetLastBuffer()); - mLength = PRUint32(Distance(mStart, mEnd)); +static nsSharedBufferList::Buffer* +AllocateContiguousHandleWithData( Buffer_ptr aDummyHandlePtr, const nsAReadableString& aDataSource ) + { + typedef const PRUnichar* PRUnichar_ptr; + + // figure out the number of bytes needed the |HandleT| part, including padding to correctly align the data part + size_t handle_size = NS_AlignedHandleSize(aDummyHandlePtr, PRUnichar_ptr(0)); + + // figure out how many |CharT|s wee need to fit in the data part + size_t string_length = aDataSource.Length(); + + // how many bytes is that (including a zero-terminator so we can claim to be flat)? + size_t string_size = (string_length+1) * sizeof(PRUnichar); + + + nsSharedBufferList::Buffer* result = 0; + void* handle_ptr = ::operator new(handle_size + string_size); + + if ( handle_ptr ) + { + typedef PRUnichar* PRUnichar_ptr; + PRUnichar* string_start_ptr = PRUnichar_ptr(NS_STATIC_CAST(unsigned char*, handle_ptr) + handle_size); + PRUnichar* string_end_ptr = string_start_ptr + string_length; + + nsReadingIterator<PRUnichar> fromBegin, fromEnd; + PRUnichar* toBegin = string_start_ptr; + copy_string(aDataSource.BeginReading(fromBegin), aDataSource.EndReading(fromEnd), toBegin); + result = new (handle_ptr) nsSharedBufferList::Buffer(string_start_ptr, string_end_ptr, string_start_ptr, string_end_ptr+1, PR_TRUE); + } + + return result; + } + +nsSlidingSubstring::nsSlidingSubstring( const nsAReadableString& aSourceString ) + : mBufferList(new nsSlidingSharedBufferList(AllocateContiguousHandleWithData(Buffer_ptr(0), aSourceString))) + { + init_range_from_buffer_list(); + acquire_ownership_of_buffer_list(); + } + +void +nsSlidingSubstring::Rebind( const nsSlidingSubstring& aString ) + { + aString.acquire_ownership_of_buffer_list(); + release_ownership_of_buffer_list(); + + mStart = aString.mStart; + mEnd = aString.mEnd; + mBufferList = aString.mBufferList; + mLength = aString.mLength; + } + +void +nsSlidingSubstring::Rebind( const nsSlidingSubstring& aString, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd ) + { + release_ownership_of_buffer_list(); + + mStart = aStart; + mEnd = aEnd; + mBufferList = aString.mBufferList; + mLength = PRUint32(Position::Distance(mStart, mEnd)); + + acquire_ownership_of_buffer_list(); + } + +void +nsSlidingSubstring::Rebind( const nsSlidingString& aString ) + { + aString.acquire_ownership_of_buffer_list(); + release_ownership_of_buffer_list(); + + mStart = aString.mStart; + mEnd = aString.mEnd; + mBufferList = aString.mBufferList; + mLength = aString.mLength; + } + +void +nsSlidingSubstring::Rebind( const nsSlidingString& aString, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd ) + { + release_ownership_of_buffer_list(); + + mStart = aStart; + mEnd = aEnd; + mBufferList = aString.mBufferList; + mLength = PRUint32(Position::Distance(mStart, mEnd)); + + acquire_ownership_of_buffer_list(); + } + +void +nsSlidingSubstring::Rebind( const nsAReadableString& aSourceString ) + { + release_ownership_of_buffer_list(); + mBufferList = new nsSlidingSharedBufferList(AllocateContiguousHandleWithData(Buffer_ptr(0), aSourceString)); + init_range_from_buffer_list(); + acquire_ownership_of_buffer_list(); } nsSlidingSubstring::~nsSlidingSubstring() { - mStart.mBuffer->ReleaseReference(); - mBufferList.DiscardUnreferencedPrefix(mStart.mBuffer); - mBufferList.ReleaseReference(); + release_ownership_of_buffer_list(); } const PRUnichar* @@ -149,8 +258,12 @@ nsSlidingSubstring::GetReadableFragment( nsReadableFragment<PRUnichar>& aFragmen + /** + * |nsSlidingString| + */ + nsSlidingString::nsSlidingString( PRUnichar* aStorageStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd ) - : nsSlidingSubstring(*(new nsSlidingSharedBufferList(nsSlidingSharedBufferList::NewWrappingBuffer(aStorageStart, aDataEnd, aStorageEnd)))) + : nsSlidingSubstring(new nsSlidingSharedBufferList(nsSlidingSharedBufferList::NewWrappingBuffer(aStorageStart, aDataEnd, aStorageEnd))) { // nothing else to do here } @@ -159,8 +272,8 @@ void nsSlidingString::AppendBuffer( PRUnichar* aStorageStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd ) { Buffer* new_buffer = new Buffer(aStorageStart, aDataEnd, aStorageStart, aStorageEnd); - Buffer* old_last_buffer = mBufferList.GetLastBuffer(); - mBufferList.LinkBuffer(old_last_buffer, new_buffer, 0); + Buffer* old_last_buffer = mBufferList->GetLastBuffer(); + mBufferList->LinkBuffer(old_last_buffer, new_buffer, 0); mLength += new_buffer->DataLength(); mEnd.PointAfter(new_buffer); @@ -171,10 +284,16 @@ nsSlidingString::DiscardPrefix( const nsReadingIterator<PRUnichar>& aIter ) { Position old_start(mStart); mStart = aIter; - mLength -= Distance(old_start, mStart); + mLength -= Position::Distance(old_start, mStart); - mStart.mBuffer->AcquireReference(); - old_start.mBuffer->ReleaseReference(); + mStart.mBuffer->AcquireNonOwningReference(); + old_start.mBuffer->ReleaseNonOwningReference(); - mBufferList.DiscardUnreferencedPrefix(old_start.mBuffer); + mBufferList->DiscardUnreferencedPrefix(old_start.mBuffer); + } + +const PRUnichar* +nsSlidingString::GetReadableFragment( nsReadableFragment<PRUnichar>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset ) const + { + return nsSlidingSubstring::GetReadableFragment(aFragment, aRequest, aOffset); } diff --git a/mozilla/xpcom/build/dlldeps.cpp b/mozilla/xpcom/build/dlldeps.cpp index a813435be4a..8e0f9ecb0d8 100644 --- a/mozilla/xpcom/build/dlldeps.cpp +++ b/mozilla/xpcom/build/dlldeps.cpp @@ -64,6 +64,7 @@ #include "nsIByteArrayInputStream.h" #include "nsReadableUtils.h" #include "nsStaticNameTable.h" +#include "nsSlidingString.h" #ifdef DEBUG #include "pure.h" #endif @@ -153,6 +154,7 @@ void XXXNeverCalled() ToNewCString(str1); ToNewCString(str2); PL_DHashTableFinish(NULL); + nsSlidingString sliding(NULL, NULL, NULL); #ifdef NS_ENABLE_LOGGING nsLog(); #endif diff --git a/mozilla/xpcom/ds/MANIFEST b/mozilla/xpcom/ds/MANIFEST index 7bc728824be..3bf55758f2a 100644 --- a/mozilla/xpcom/ds/MANIFEST +++ b/mozilla/xpcom/ds/MANIFEST @@ -2,6 +2,7 @@ nsAlgorithm.h nsAVLTree.h nsAtomService.h nsBufferHandle.h +nsBufferHandleUtils.h nsCppSharedAllocator.h nsCRT.h nsDeque.h diff --git a/mozilla/xpcom/ds/Makefile.in b/mozilla/xpcom/ds/Makefile.in index 532944a4004..c8cff1ac1a7 100644 --- a/mozilla/xpcom/ds/Makefile.in +++ b/mozilla/xpcom/ds/Makefile.in @@ -82,6 +82,7 @@ EXPORTS = \ nsAVLTree.h \ nsAtomService.h \ nsBufferHandle.h \ + nsBufferHandleUtils.h \ nsCppSharedAllocator.h \ nsCRT.h \ nsDeque.h \ diff --git a/mozilla/xpcom/ds/makefile.win b/mozilla/xpcom/ds/makefile.win index 2eada35b495..2a2ef5e336f 100644 --- a/mozilla/xpcom/ds/makefile.win +++ b/mozilla/xpcom/ds/makefile.win @@ -32,6 +32,7 @@ EXPORTS = \ nsTextFormatter.h \ nsAVLTree.h \ nsBufferHandle.h \ + nsBufferHandleUtils.h \ nsCppSharedAllocator.h \ nsCRT.h \ nsDeque.h \ diff --git a/mozilla/xpcom/ds/nsAlgorithm.h b/mozilla/xpcom/ds/nsAlgorithm.h index b5360b07aaf..9c2e5855cc1 100755 --- a/mozilla/xpcom/ds/nsAlgorithm.h +++ b/mozilla/xpcom/ds/nsAlgorithm.h @@ -109,5 +109,4 @@ copy_string_backward( const InputIterator& first, InputIterator& last, OutputIte return result; } - #endif // !defined(nsAlgorithm_h___) diff --git a/mozilla/xpcom/ds/nsBufferHandle.h b/mozilla/xpcom/ds/nsBufferHandle.h index e3004276127..b8cf0688dba 100755 --- a/mozilla/xpcom/ds/nsBufferHandle.h +++ b/mozilla/xpcom/ds/nsBufferHandle.h @@ -86,7 +86,7 @@ class nsSharedBufferHandle nsSharedBufferHandle( CharT* aDataStart, CharT* aDataEnd ) : nsBufferHandle<CharT>(aDataStart, aDataEnd) { - mFlags |= kIsShared; + mFlags = kIsShared; } ~nsSharedBufferHandle(); diff --git a/mozilla/xpcom/ds/nsReadableUtils.cpp b/mozilla/xpcom/ds/nsReadableUtils.cpp index a2101512940..e05326fcc4b 100755 --- a/mozilla/xpcom/ds/nsReadableUtils.cpp +++ b/mozilla/xpcom/ds/nsReadableUtils.cpp @@ -229,14 +229,43 @@ ToNewUnicode( const nsAReadableCString& aSource ) NS_COM PRUnichar* -CopyUnicodeTo( const nsAReadableString& aSource, PRUnichar* aDest, PRUint32 aLength ) +CopyUnicodeTo( const nsAReadableString& aSource, PRUint32 aSrcOffset, PRUnichar* aDest, PRUint32 aLength ) { nsReadingIterator<PRUnichar> fromBegin, fromEnd; - PRUnichar* toBegin = aDest; - copy_string(aSource.BeginReading(fromBegin), aSource.BeginReading(fromEnd).advance( PRInt32(aLength) ), toBegin); + PRUnichar* toBegin = aDest; + copy_string(aSource.BeginReading(fromBegin).advance( PRInt32(aSrcOffset) ), aSource.BeginReading(fromEnd).advance( PRInt32(aSrcOffset+aLength) ), toBegin); return aDest; } +NS_COM +void +CopyUnicodeTo( const nsReadingIterator<PRUnichar>& aSrcStart, + const nsReadingIterator<PRUnichar>& aSrcEnd, + nsAWritableString& aDest ) + { + nsWritingIterator<PRUnichar> writer; + aDest.SetLength(Distance(aSrcStart, aSrcEnd)); + aDest.BeginWriting(writer); + nsReadingIterator<PRUnichar> fromBegin(aSrcStart); + + copy_string(fromBegin, aSrcEnd, writer); + } + +NS_COM +void +AppendUnicodeTo( const nsReadingIterator<PRUnichar>& aSrcStart, + const nsReadingIterator<PRUnichar>& aSrcEnd, + nsAWritableString& aDest ) + { + nsWritingIterator<PRUnichar> writer; + PRUint32 oldLength = aDest.Length(); + aDest.SetLength(oldLength + Distance(aSrcStart, aSrcEnd)); + aDest.BeginWriting(writer).advance(oldLength); + nsReadingIterator<PRUnichar> fromBegin(aSrcStart); + + copy_string(fromBegin, aSrcEnd, writer); + } + NS_COM PRBool IsASCII( const nsAReadableString& aString ) @@ -341,3 +370,224 @@ ToLowerCase( nsAWritableCString& aCString ) ConvertToLowerCase<char> converter; copy_string(aCString.BeginWriting(fromBegin), aCString.EndWriting(fromEnd), converter); } + + +template <class CharT> +inline // probably wishful thinking +PRBool +FindInReadable_Impl( const basic_nsAReadableString<CharT>& aPattern, + nsReadingIterator<CharT>& aSearchStart, + nsReadingIterator<CharT>& aSearchEnd ) + { + PRBool found_it = PR_FALSE; + + // only bother searching at all if we're given a non-empty range to search + if ( aSearchStart != aSearchEnd ) + { + nsReadingIterator<CharT> aPatternStart, aPatternEnd; + aPattern.BeginReading(aPatternStart); + aPattern.EndReading(aPatternEnd); + + // outer loop keeps searching till we find it or run out of string to search + while ( !found_it ) + { + // fast inner loop (that's what it's called, not what it is) looks for a potential match + while ( aSearchStart != aSearchEnd && *aPatternStart != *aSearchStart ) + ++aSearchStart; + + // if we broke out of the `fast' loop because we're out of string ... we're done: no match + if ( aSearchStart == aSearchEnd ) + break; + + // otherwise, we're at a potential match, let's see if we really hit one + nsReadingIterator<CharT> testPattern(aPatternStart); + nsReadingIterator<CharT> testSearch(aSearchStart); + + // slow inner loop verifies the potential match (found by the `fast' loop) at the current position + for(;;) + { + // we already compared the first character in the outer loop, + // so we'll advance before the next comparison + ++testPattern; + ++testSearch; + + // if we verified all the way to the end of the pattern, then we found it! + if ( testPattern == aPatternEnd ) + { + found_it = PR_TRUE; + aSearchEnd = testSearch; // return the exact found range through the parameters + break; + } + + // if we got to end of the string we're searching before we hit the end of the + // pattern, we'll never find what we're looking for + if ( testSearch == aSearchEnd ) + { + aSearchStart = aSearchEnd; + break; + } + + // else if we mismatched ... it's time to advance to the next search position + // and get back into the `fast' loop + if ( *testPattern != *testSearch ) + { + ++aSearchStart; + break; + } + } + } + } + + return found_it; + } + +NS_COM +PRBool +FindInReadable( const nsAReadableString& aPattern, nsReadingIterator<PRUnichar>& aSearchStart, nsReadingIterator<PRUnichar>& aSearchEnd ) + { + return FindInReadable_Impl(aPattern, aSearchStart, aSearchEnd); + } + +NS_COM +PRBool +FindInReadable( const nsAReadableCString& aPattern, nsReadingIterator<char>& aSearchStart, nsReadingIterator<char>& aSearchEnd ) + { + return FindInReadable_Impl(aPattern, aSearchStart, aSearchEnd); + } + + /** + * This implementation is simple, but does too much work. + * It searches the entire string from left to right, and returns the last match found, if any. + * This implementation will be replaced when I get |reverse_iterator|s working. + */ +template <class CharT> +inline // probably wishful thinking +PRBool +RFindInReadable_Impl( const basic_nsAReadableString<CharT>& aPattern, + nsReadingIterator<CharT>& aSearchStart, + nsReadingIterator<CharT>& aSearchEnd ) + { + PRBool found_it = PR_FALSE; + + nsReadingIterator<CharT> savedSearchEnd(aSearchEnd); + nsReadingIterator<CharT> searchStart(aSearchStart), searchEnd(aSearchEnd); + + while ( searchStart != searchEnd ) + { + if ( FindInReadable(aPattern, searchStart, searchEnd) ) + { + found_it = PR_TRUE; + + // this is the best match so far, so remember it + aSearchStart = searchStart; + aSearchEnd = searchEnd; + + // ...and get ready to search some more + // (it's tempting to set |searchStart=searchEnd| ... but that misses overlapping patterns) + ++searchStart; + searchEnd = savedSearchEnd; + } + } + + // if we never found it, return an empty range + if ( !found_it ) + aSearchStart = aSearchEnd; + + return found_it; + } + + +NS_COM +PRBool +RFindInReadable( const nsAReadableString& aPattern, nsReadingIterator<PRUnichar>& aSearchStart, nsReadingIterator<PRUnichar>& aSearchEnd ) + { + return RFindInReadable_Impl(aPattern, aSearchStart, aSearchEnd); + } + +NS_COM +PRBool +RFindInReadable( const nsAReadableCString& aPattern, nsReadingIterator<char>& aSearchStart, nsReadingIterator<char>& aSearchEnd ) + { + return RFindInReadable_Impl(aPattern, aSearchStart, aSearchEnd); + } + + + +template <class CharT> +inline // probably wishful thinking +PRBool +FindCharInReadable_Impl( CharT aChar, + nsReadingIterator<CharT>& aSearchStart, + nsReadingIterator<CharT>& aSearchEnd ) + { + while ( aSearchStart != aSearchEnd ) + { + PRInt32 fragmentLength; + if ( SameFragment(aSearchStart, aSearchEnd) ) + fragmentLength = aSearchEnd.get() - aSearchStart.get(); + else + fragmentLength = aSearchStart.size_forward(); + + const CharT* charFoundAt = nsCharTraits<CharT>::find(aSearchStart.get(), fragmentLength, aChar); + if ( charFoundAt ) { + aSearchStart.advance( charFoundAt - aSearchStart.get() ); + return PR_TRUE; + } + + aSearchStart.advance(fragmentLength); + } + + return PR_FALSE; + } + + +NS_COM +PRBool +FindCharInReadable( PRUnichar aChar, nsReadingIterator<PRUnichar>& aSearchStart, nsReadingIterator<PRUnichar>& aSearchEnd ) + { + return FindCharInReadable_Impl(aChar, aSearchStart, aSearchEnd); + } + +NS_COM +PRBool +FindCharInReadable( char aChar, nsReadingIterator<char>& aSearchStart, nsReadingIterator<char>& aSearchEnd ) + { + return FindCharInReadable_Impl(aChar, aSearchStart, aSearchEnd); + } + +template <class CharT> +PRUint32 +CountCharInReadable_Impl( const basic_nsAReadableString<CharT>& aStr, + CharT aChar ) +{ + PRUint32 count = 0; + nsReadingIterator<CharT> begin, end; + + aStr.BeginReading(begin); + aStr.EndReading(end); + + while (begin != end) { + if (*begin == aChar) { + count++; + } + begin++; + } + + return count; +} + +NS_COM +PRUint32 +CountCharInReadable( const nsAReadableString& aStr, + PRUnichar aChar ) +{ + return CountCharInReadable_Impl(aStr, aChar); +} + +NS_COM +PRUint32 +CountCharInReadable( const nsAReadableCString& aStr, + char aChar ) +{ + return CountCharInReadable_Impl(aStr, aChar); +} diff --git a/mozilla/xpcom/ds/nsReadableUtils.h b/mozilla/xpcom/ds/nsReadableUtils.h index 5a7bd9285b9..33b6c6ec254 100755 --- a/mozilla/xpcom/ds/nsReadableUtils.h +++ b/mozilla/xpcom/ds/nsReadableUtils.h @@ -35,10 +35,8 @@ #include "nsAWritableString.h" #endif -#if 0 NS_COM size_t Distance( const nsReadingIterator<PRUnichar>&, const nsReadingIterator<PRUnichar>& ); NS_COM size_t Distance( const nsReadingIterator<char>&, const nsReadingIterator<char>& ); -#endif NS_COM void CopyUCS2toASCII( const nsAReadableString& aSource, nsAWritableCString& aDest ); @@ -115,15 +113,46 @@ NS_COM PRUnichar* ToNewUnicode( const nsAReadableCString& aSource ); * After this operation |aDest| is not null terminated. * * @param aSource a 16-bit wide string + * @param aSrcOffset start offset in the source string * @param aDest a |PRUnichar| buffer * @param aLength the number of 16-bit characters to copy * @return pointer to destination buffer - identical to |aDest| */ NS_COM PRUnichar* CopyUnicodeTo( const nsAReadableString& aSource, + PRUint32 aSrcOffset, PRUnichar* aDest, PRUint32 aLength ); + /** + * Copies 16-bit characters between iterators |aSrcStart| and + * |aSrcEnd| to the writable string |aDest|. Similar to the + * |nsString::Mid| method. + * + * After this operation |aDest| is not null terminated. + * + * @param aSrcStart start source iterator + * @param aSrcEnd end source iterator + * @param aDest destination for the copy + */ +NS_COM void CopyUnicodeTo( const nsReadingIterator<PRUnichar>& aSrcStart, + const nsReadingIterator<PRUnichar>& aSrcEnd, + nsAWritableString& aDest ); + + /** + * Appends 16-bit characters between iterators |aSrcStart| and + * |aSrcEnd| to the writable string |aDest|. + * + * After this operation |aDest| is not null terminated. + * + * @param aSrcStart start source iterator + * @param aSrcEnd end source iterator + * @param aDest destination for the copy + */ +NS_COM void AppendUnicodeTo( const nsReadingIterator<PRUnichar>& aSrcStart, + const nsReadingIterator<PRUnichar>& aSrcEnd, + nsAWritableString& aDest ); + /** * Returns |PR_TRUE| if |aString| contains only ASCII characters, that is, characters in the range (0x00, 0x7F). * @@ -142,4 +171,47 @@ NS_COM void ToUpperCase( nsAWritableCString& ); NS_COM void ToLowerCase( nsAWritableString& ); NS_COM void ToLowerCase( nsAWritableCString& ); + /** + * Finds the leftmost occurance of |aPattern|, if any in the range |aSearchStart|..|aSearchEnd|. + * + * Returns |PR_TRUE| if a match was found, and adjusts |aSearchStart| and |aSearchEnd| to + * point to the match. If no match was found, returns |PR_FALSE| and makes |aSearchStart == aSearchEnd|. + * + * Currently, this is equivalent to the O(m*n) implementation previously on |ns[C]String|. + * If we need something faster; we can implement that later. + */ +NS_COM PRBool FindInReadable( const nsAReadableString& aPattern, nsReadingIterator<PRUnichar>&, nsReadingIterator<PRUnichar>& ); +NS_COM PRBool FindInReadable( const nsAReadableCString& aPattern, nsReadingIterator<char>&, nsReadingIterator<char>& ); + + + /** + * Finds the rightmost occurance of |aPattern| + * Returns |PR_TRUE| if a match was found, and adjusts |aSearchStart| and |aSearchEnd| to + * point to the match. If no match was found, returns |PR_FALSE| and makes |aSearchStart == aSearchEnd|. + * + * Currently, this is equivalent to the O(m*n) implementation previously on |ns[C]String|. + * If we need something faster; we can implement that later. + */ +NS_COM PRBool RFindInReadable( const nsAReadableString& aPattern, nsReadingIterator<PRUnichar>&, nsReadingIterator<PRUnichar>& ); +NS_COM PRBool RFindInReadable( const nsAReadableCString& aPattern, nsReadingIterator<char>&, nsReadingIterator<char>& ); + + /** + * Finds the leftmost occurance of |aChar|, if any in the range + * |aSearchStart|..|aSearchEnd|. + * + * Returns |PR_TRUE| if a match was found, and adjusts |aSearchStart| to + * point to the match. If no match was found, returns |PR_FALSE| and + * makes |aSearchStart == aSearchEnd|. + */ +NS_COM PRBool FindCharInReadable( PRUnichar aChar, nsReadingIterator<PRUnichar>&, nsReadingIterator<PRUnichar>& ); +NS_COM PRBool FindCharInReadable( char aChar, nsReadingIterator<char>&, nsReadingIterator<char>& ); + + /** + * Finds the number of occurences of |aChar| in the string |aStr| + */ +NS_COM PRUint32 CountCharInReadable( const nsAReadableString& aStr, + PRUnichar aChar ); +NS_COM PRUint32 CountCharInReadable( const nsAReadableCString& aStr, + char aChar ); + #endif // !defined(nsReadableUtils_h___) diff --git a/mozilla/xpcom/ds/nsSharedBufferList.cpp b/mozilla/xpcom/ds/nsSharedBufferList.cpp index 76f50aa9eaa..584890a75ec 100755 --- a/mozilla/xpcom/ds/nsSharedBufferList.cpp +++ b/mozilla/xpcom/ds/nsSharedBufferList.cpp @@ -23,9 +23,29 @@ */ #include "nsSharedBufferList.h" + +#ifndef nsAlgorithm_h___ #include "nsAlgorithm.h" // for |copy_string| -#include <new.h> +#endif + + +ptrdiff_t +nsSharedBufferList::Position::Distance( const Position& aStart, const Position& aEnd ) + { + ptrdiff_t result = 0; + if ( aStart.mBuffer == aEnd.mBuffer ) + result = aEnd.mPosInBuffer - aStart.mPosInBuffer; + else + { + result = aStart.mBuffer->DataEnd() - aStart.mPosInBuffer; + for ( Buffer* b = aStart.mBuffer->mNext; b != aEnd.mBuffer; b = b->mNext ) + result += b->DataLength(); + result += aEnd.mPosInBuffer - aEnd.mBuffer->DataStart(); + } + + return result; + } void @@ -48,36 +68,6 @@ nsSharedBufferList::~nsSharedBufferList() } -nsSharedBufferList::Buffer* -nsSharedBufferList::NewSingleAllocationBuffer( const PRUnichar* aData, PRUint32 aDataLength, PRUint32 aAdditionalSpace ) - { - size_t object_size = ((sizeof(Buffer) + sizeof(PRUnichar) - 1) / sizeof(PRUnichar)) * sizeof(PRUnichar); - PRUint32 buffer_length = aDataLength + aAdditionalSpace; - size_t buffer_size = size_t(buffer_length) * sizeof(PRUnichar); - - void* object_ptr = operator new(object_size + buffer_size); - if ( object_ptr ) - { - typedef PRUnichar* PRUnichar_ptr; - PRUnichar* buffer_ptr = PRUnichar_ptr(NS_STATIC_CAST(unsigned char*, object_ptr) + object_size); - if ( aDataLength ) - { - PRUnichar* toBegin = buffer_ptr; - copy_string(aData, aData+aDataLength, toBegin); - } - return new (object_ptr) Buffer(buffer_ptr, buffer_ptr+aDataLength, buffer_ptr, buffer_ptr+buffer_length, PR_TRUE); - } - - return 0; - } - -nsSharedBufferList::Buffer* -nsSharedBufferList::NewWrappingBuffer( PRUnichar* aDataStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd ) - { - return new Buffer(aDataStart, aDataEnd, aDataStart, aStorageEnd); - } - - void nsSharedBufferList::LinkBuffer( Buffer* aPrevBuffer, Buffer* aNewBuffer, Buffer* aNextBuffer ) diff --git a/mozilla/xpcom/ds/nsSharedBufferList.h b/mozilla/xpcom/ds/nsSharedBufferList.h index c740d399328..38213b1190e 100755 --- a/mozilla/xpcom/ds/nsSharedBufferList.h +++ b/mozilla/xpcom/ds/nsSharedBufferList.h @@ -40,6 +40,12 @@ // for |nsReadingIterator| #endif +#ifndef nsBufferHandleUtils_h___ +#include "nsBufferHandleUtils.h" + // for |NS_AllocateContiguousHandleWithData| +#endif + + /** * This class forms the basis for several multi-fragment string classes, in * particular: |nsFragmentedString| (though not yet), and |nsSlidingString|/|nsSlidingSubstring|. @@ -63,6 +69,27 @@ class nsSharedBufferList this->mFlags |= this->kIsSingleAllocationWithBuffer; } + /** + * These buffers will be `owned' by the list, and only the + * the list itself will be allowed to delete member |Buffer|s, + * therefore, we cannot use the inherited |AcquireReference| + * and |ReleaseReference|, as they use the model that the + * buffer manages its own lifetime. + */ + void + AcquireNonOwningReference() const + { + Buffer* mutable_this = NS_CONST_CAST(Buffer*, this); + mutable_this->set_refcount( get_refcount()+1 ); + } + + void + ReleaseNonOwningReference() const + { + Buffer* mutable_this = NS_CONST_CAST(Buffer*, this); + mutable_this->set_refcount( get_refcount()-1 ); + } + Buffer* mPrev; Buffer* mNext; @@ -108,6 +135,9 @@ class nsSharedBufferList // Position( const Position& ); -- automatically generated copy-constructor is OK // Position& operator=( const Position& ); -- automatically generated copy-assignment operator is OK + + // don't want to provide this as |operator-|, since that might imply O(1) + static ptrdiff_t Distance( const Position&, const Position& ); }; @@ -137,8 +167,20 @@ class nsSharedBufferList Buffer* UnlinkBuffer( Buffer* ); void SplitBuffer( const Position& ); - static Buffer* NewSingleAllocationBuffer( const PRUnichar*, PRUint32, PRUint32 = 0 ); - static Buffer* NewWrappingBuffer( PRUnichar*, PRUnichar*, PRUnichar* ); + static + Buffer* + NewSingleAllocationBuffer( const PRUnichar* aData, PRUint32 aDataLength, PRUint32 aAdditionalCapacity = 1 ) + { + typedef Buffer* Buffer_ptr; + return NS_AllocateContiguousHandleWithData(Buffer_ptr(0), nsLiteralString(aData, aDataLength), aAdditionalCapacity); + } + + static + Buffer* + NewWrappingBuffer( PRUnichar* aDataStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd ) + { + return new Buffer(aDataStart, aDataEnd, aDataStart, aStorageEnd); + } void DiscardSuffix( PRUint32 ); // need other discards: prefix, and by iterator or pointer or something diff --git a/mozilla/xpcom/ds/nsSlidingString.cpp b/mozilla/xpcom/ds/nsSlidingString.cpp index 58c7698c3d4..8b07b17256e 100755 --- a/mozilla/xpcom/ds/nsSlidingString.cpp +++ b/mozilla/xpcom/ds/nsSlidingString.cpp @@ -24,6 +24,18 @@ #include "nsSlidingString.h" +#ifndef nsBufferHandleUtils_h___ +#include "nsBufferHandleUtils.h" +#endif + +#include <new.h> + + + + /** + * |nsSlidingSharedBufferList| + */ + void nsSlidingSharedBufferList::DiscardUnreferencedPrefix( Buffer* aRecentlyReleasedBuffer ) { @@ -35,62 +47,159 @@ nsSlidingSharedBufferList::DiscardUnreferencedPrefix( Buffer* aRecentlyReleasedB } -ptrdiff_t Distance( const nsSharedBufferList::Position&, const nsSharedBufferList::Position& ); -ptrdiff_t -Distance( const nsSharedBufferList::Position& aStart, const nsSharedBufferList::Position& aEnd ) - { - ptrdiff_t result = 0; - if ( aStart.mBuffer == aEnd.mBuffer ) - result = aEnd.mPosInBuffer - aStart.mPosInBuffer; - else - { - result = aStart.mBuffer->DataEnd() - aStart.mPosInBuffer; - for ( nsSharedBufferList::Buffer* b = aStart.mBuffer->mNext; b != aEnd.mBuffer; b = b->mNext ) - result += b->DataLength(); - result += aEnd.mPosInBuffer - aEnd.mBuffer->DataStart(); - } - - return result; - } + /** + * |nsSlidingSubstring| + */ + // copy constructor nsSlidingSubstring::nsSlidingSubstring( const nsSlidingSubstring& aString ) : mStart(aString.mStart), mEnd(aString.mEnd), mBufferList(aString.mBufferList), mLength(aString.mLength) { - mBufferList.AcquireReference(); - mStart.mBuffer->AcquireReference(); + acquire_ownership_of_buffer_list(); } nsSlidingSubstring::nsSlidingSubstring( const nsSlidingSubstring& aString, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd ) : mStart(aStart), mEnd(aEnd), mBufferList(aString.mBufferList), - mLength(PRUint32(Distance(mStart, mEnd))) + mLength(PRUint32(Position::Distance(mStart, mEnd))) { - mBufferList.AcquireReference(); - mStart.mBuffer->AcquireReference(); + acquire_ownership_of_buffer_list(); } -nsSlidingSubstring::nsSlidingSubstring( nsSlidingSharedBufferList& aBufferList ) +nsSlidingSubstring::nsSlidingSubstring( const nsSlidingString& aString ) + : mStart(aString.mStart), + mEnd(aString.mEnd), + mBufferList(aString.mBufferList), + mLength(aString.mLength) + { + acquire_ownership_of_buffer_list(); + } + +nsSlidingSubstring::nsSlidingSubstring( const nsSlidingString& aString, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd ) + : mStart(aStart), + mEnd(aEnd), + mBufferList(aString.mBufferList), + mLength(PRUint32(Position::Distance(mStart, mEnd))) + { + acquire_ownership_of_buffer_list(); + } + +nsSlidingSubstring::nsSlidingSubstring( nsSlidingSharedBufferList* aBufferList ) : mBufferList(aBufferList) { - mBufferList.AcquireReference(); + init_range_from_buffer_list(); + acquire_ownership_of_buffer_list(); + } - mStart.PointBefore(mBufferList.GetFirstBuffer()); - mStart.mBuffer->AcquireReference(); +typedef const nsSharedBufferList::Buffer* Buffer_ptr; - mEnd.PointAfter(mBufferList.GetLastBuffer()); - mLength = PRUint32(Distance(mStart, mEnd)); +static nsSharedBufferList::Buffer* +AllocateContiguousHandleWithData( Buffer_ptr aDummyHandlePtr, const nsAReadableString& aDataSource ) + { + typedef const PRUnichar* PRUnichar_ptr; + + // figure out the number of bytes needed the |HandleT| part, including padding to correctly align the data part + size_t handle_size = NS_AlignedHandleSize(aDummyHandlePtr, PRUnichar_ptr(0)); + + // figure out how many |CharT|s wee need to fit in the data part + size_t string_length = aDataSource.Length(); + + // how many bytes is that (including a zero-terminator so we can claim to be flat)? + size_t string_size = (string_length+1) * sizeof(PRUnichar); + + + nsSharedBufferList::Buffer* result = 0; + void* handle_ptr = ::operator new(handle_size + string_size); + + if ( handle_ptr ) + { + typedef PRUnichar* PRUnichar_ptr; + PRUnichar* string_start_ptr = PRUnichar_ptr(NS_STATIC_CAST(unsigned char*, handle_ptr) + handle_size); + PRUnichar* string_end_ptr = string_start_ptr + string_length; + + nsReadingIterator<PRUnichar> fromBegin, fromEnd; + PRUnichar* toBegin = string_start_ptr; + copy_string(aDataSource.BeginReading(fromBegin), aDataSource.EndReading(fromEnd), toBegin); + result = new (handle_ptr) nsSharedBufferList::Buffer(string_start_ptr, string_end_ptr, string_start_ptr, string_end_ptr+1, PR_TRUE); + } + + return result; + } + +nsSlidingSubstring::nsSlidingSubstring( const nsAReadableString& aSourceString ) + : mBufferList(new nsSlidingSharedBufferList(AllocateContiguousHandleWithData(Buffer_ptr(0), aSourceString))) + { + init_range_from_buffer_list(); + acquire_ownership_of_buffer_list(); + } + +void +nsSlidingSubstring::Rebind( const nsSlidingSubstring& aString ) + { + aString.acquire_ownership_of_buffer_list(); + release_ownership_of_buffer_list(); + + mStart = aString.mStart; + mEnd = aString.mEnd; + mBufferList = aString.mBufferList; + mLength = aString.mLength; + } + +void +nsSlidingSubstring::Rebind( const nsSlidingSubstring& aString, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd ) + { + release_ownership_of_buffer_list(); + + mStart = aStart; + mEnd = aEnd; + mBufferList = aString.mBufferList; + mLength = PRUint32(Position::Distance(mStart, mEnd)); + + acquire_ownership_of_buffer_list(); + } + +void +nsSlidingSubstring::Rebind( const nsSlidingString& aString ) + { + aString.acquire_ownership_of_buffer_list(); + release_ownership_of_buffer_list(); + + mStart = aString.mStart; + mEnd = aString.mEnd; + mBufferList = aString.mBufferList; + mLength = aString.mLength; + } + +void +nsSlidingSubstring::Rebind( const nsSlidingString& aString, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd ) + { + release_ownership_of_buffer_list(); + + mStart = aStart; + mEnd = aEnd; + mBufferList = aString.mBufferList; + mLength = PRUint32(Position::Distance(mStart, mEnd)); + + acquire_ownership_of_buffer_list(); + } + +void +nsSlidingSubstring::Rebind( const nsAReadableString& aSourceString ) + { + release_ownership_of_buffer_list(); + mBufferList = new nsSlidingSharedBufferList(AllocateContiguousHandleWithData(Buffer_ptr(0), aSourceString)); + init_range_from_buffer_list(); + acquire_ownership_of_buffer_list(); } nsSlidingSubstring::~nsSlidingSubstring() { - mStart.mBuffer->ReleaseReference(); - mBufferList.DiscardUnreferencedPrefix(mStart.mBuffer); - mBufferList.ReleaseReference(); + release_ownership_of_buffer_list(); } const PRUnichar* @@ -149,8 +258,12 @@ nsSlidingSubstring::GetReadableFragment( nsReadableFragment<PRUnichar>& aFragmen + /** + * |nsSlidingString| + */ + nsSlidingString::nsSlidingString( PRUnichar* aStorageStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd ) - : nsSlidingSubstring(*(new nsSlidingSharedBufferList(nsSlidingSharedBufferList::NewWrappingBuffer(aStorageStart, aDataEnd, aStorageEnd)))) + : nsSlidingSubstring(new nsSlidingSharedBufferList(nsSlidingSharedBufferList::NewWrappingBuffer(aStorageStart, aDataEnd, aStorageEnd))) { // nothing else to do here } @@ -159,8 +272,8 @@ void nsSlidingString::AppendBuffer( PRUnichar* aStorageStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd ) { Buffer* new_buffer = new Buffer(aStorageStart, aDataEnd, aStorageStart, aStorageEnd); - Buffer* old_last_buffer = mBufferList.GetLastBuffer(); - mBufferList.LinkBuffer(old_last_buffer, new_buffer, 0); + Buffer* old_last_buffer = mBufferList->GetLastBuffer(); + mBufferList->LinkBuffer(old_last_buffer, new_buffer, 0); mLength += new_buffer->DataLength(); mEnd.PointAfter(new_buffer); @@ -171,10 +284,16 @@ nsSlidingString::DiscardPrefix( const nsReadingIterator<PRUnichar>& aIter ) { Position old_start(mStart); mStart = aIter; - mLength -= Distance(old_start, mStart); + mLength -= Position::Distance(old_start, mStart); - mStart.mBuffer->AcquireReference(); - old_start.mBuffer->ReleaseReference(); + mStart.mBuffer->AcquireNonOwningReference(); + old_start.mBuffer->ReleaseNonOwningReference(); - mBufferList.DiscardUnreferencedPrefix(old_start.mBuffer); + mBufferList->DiscardUnreferencedPrefix(old_start.mBuffer); + } + +const PRUnichar* +nsSlidingString::GetReadableFragment( nsReadableFragment<PRUnichar>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset ) const + { + return nsSlidingSubstring::GetReadableFragment(aFragment, aRequest, aOffset); } diff --git a/mozilla/xpcom/ds/nsSlidingString.h b/mozilla/xpcom/ds/nsSlidingString.h index 6dc2e55210d..af36acc39eb 100755 --- a/mozilla/xpcom/ds/nsSlidingString.h +++ b/mozilla/xpcom/ds/nsSlidingString.h @@ -45,7 +45,7 @@ * of the list. |nsSlidingString| also the client to advance its starting point. * */ -class nsSlidingSharedBufferList +class NS_COM nsSlidingSharedBufferList : public nsSharedBufferList { public: @@ -63,35 +63,86 @@ class nsSlidingSharedBufferList +class nsSlidingString; /** * a substring over a buffer list, this */ -class nsSlidingSubstring - : public nsPromiseReadable<PRUnichar> +class NS_COM nsSlidingSubstring + : virtual public nsPromiseReadable<PRUnichar> { + friend class nsSlidingString; + public: typedef nsSlidingSharedBufferList::Buffer Buffer; typedef nsSlidingSharedBufferList::Position Position; + nsSlidingSubstring() + : mStart(0,0), + mEnd(0,0), + mBufferList(0), + mLength(0) + { + // nothing else to do here + } + nsSlidingSubstring( const nsSlidingSubstring& ); // copy-constructor nsSlidingSubstring( const nsSlidingSubstring& aString, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd ); + nsSlidingSubstring( const nsSlidingString& ); + nsSlidingSubstring( const nsSlidingString& aString, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd ); + explicit nsSlidingSubstring( const nsAReadableString& ); + // copy the supplied string into a new buffer ... there will be no modifying instance over this buffer list + + void Rebind( const nsSlidingSubstring& ); + void Rebind( const nsSlidingSubstring&, const nsReadingIterator<PRUnichar>&, const nsReadingIterator<PRUnichar>& ); + void Rebind( const nsSlidingString& ); + void Rebind( const nsSlidingString&, const nsReadingIterator<PRUnichar>&, const nsReadingIterator<PRUnichar>& ); + void Rebind( const nsAReadableString& ); + ~nsSlidingSubstring(); virtual PRUint32 Length() const { return mLength; } protected: - nsSlidingSubstring( nsSlidingSharedBufferList& aBufferList ); + nsSlidingSubstring( nsSlidingSharedBufferList* aBufferList ); virtual const PRUnichar* GetReadableFragment( nsReadableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) const; private: // can't assign into me, I'm a read-only reference void operator=( const nsSlidingSubstring& ); // NOT TO BE IMPLEMENTED + void + init_range_from_buffer_list() + // used only from constructors + { + mStart.PointBefore(mBufferList->GetFirstBuffer()); + mEnd.PointAfter(mBufferList->GetLastBuffer()); + mLength = PRUint32(Position::Distance(mStart, mEnd)); + } + + void + acquire_ownership_of_buffer_list() const + // used only from constructors and |Rebind|, requires |mStart| already be initialized + { + mBufferList->AcquireReference(); + mStart.mBuffer->AcquireNonOwningReference(); + } + + void + release_ownership_of_buffer_list() + { + if ( mBufferList ) + { + mStart.mBuffer->ReleaseNonOwningReference(); + mBufferList->DiscardUnreferencedPrefix(mStart.mBuffer); + mBufferList->ReleaseReference(); + } + } + protected: Position mStart; Position mEnd; - nsSlidingSharedBufferList& mBufferList; + nsSlidingSharedBufferList* mBufferList; PRUint32 mLength; }; @@ -102,14 +153,19 @@ class nsSlidingSubstring * An |nsSlidingSharedBufferList| may be modified by zero or one instances of this class. * */ -class nsSlidingString - : public nsSlidingSubstring +class NS_COM nsSlidingString + : virtual public nsPromiseReadable<PRUnichar>, + private nsSlidingSubstring { + friend class nsSlidingSubstring; + public: nsSlidingString( PRUnichar* aStorageStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd ); // ...created by consuming ownership of a buffer ... |aStorageStart| must point to something // that it will be OK for the slidking string to call |nsMemory::Free| on + virtual PRUint32 Length() const { return mLength; } + // you are giving ownership to the string, it takes and keeps your buffer, deleting it (with |nsMemory::Free|) when done void AppendBuffer( PRUnichar* aStorageStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd ); @@ -118,18 +174,21 @@ class nsSlidingString void DiscardPrefix( const nsReadingIterator<PRUnichar>& ); // any other way you want to do this? + protected: + virtual const PRUnichar* GetReadableFragment( nsReadableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) const; + private: + + void + acquire_ownership_of_buffer_list() const + // used only from constructors and |Rebind|, requires |mStart| already be initialized + { + mBufferList->AcquireReference(); + mStart.mBuffer->AcquireNonOwningReference(); + } + nsSlidingString( const nsSlidingString& ); // NOT TO BE IMPLEMENTED void operator=( const nsSlidingString& ); // NOT TO BE IMPLEMENTED }; - -#if 0 - // this (or something similar) is what should appear in the parser, I think -#include "nsSlidingString.h" - -typedef nsSlidingString nsParserString; -typedef nsSlidingSubstring nsParserToken; -#endif - #endif // !defined(nsSlidingString_h___) diff --git a/mozilla/xpcom/ds/nsStr.h b/mozilla/xpcom/ds/nsStr.h index 631687c8cf1..fbe62321288 100644 --- a/mozilla/xpcom/ds/nsStr.h +++ b/mozilla/xpcom/ds/nsStr.h @@ -484,7 +484,7 @@ inline void Recycle( PRUnichar* aBuffer) { nsMemory::Free(aBuffer); } * @param anIndex tells us where in dest to get the char from * @return the given char, or 0 if anIndex is out of range */ -inline PRUnichar GetCharAt(const nsStr& aDest,PRUint32 anIndex){ +inline PRUnichar GetCharAt(const nsStr& aDest,PRUint32 anIndex) { if(anIndex<aDest.mLength) { return (eTwoByte==aDest.mCharSize) ? aDest.mUStr[anIndex] : (PRUnichar)aDest.mStr[anIndex]; }//if diff --git a/mozilla/xpcom/ds/nsString.cpp b/mozilla/xpcom/ds/nsString.cpp index ff3129d4c0e..92624c14d6b 100644 --- a/mozilla/xpcom/ds/nsString.cpp +++ b/mozilla/xpcom/ds/nsString.cpp @@ -473,7 +473,7 @@ nsCString::ReplaceSubstring(const nsCString& aTarget,const nsCString& aNewValue) * @param * @return *this */ -PRInt32 nsCString::CountChar(PRUnichar aChar) { +PRInt32 nsCString::CountChar(PRUnichar aChar) const { PRInt32 theIndex=0; PRInt32 theCount=0; PRInt32 theLen=(PRInt32)mLength; diff --git a/mozilla/xpcom/ds/nsString.h b/mozilla/xpcom/ds/nsString.h index 446200f3855..4ab205c2b29 100644 --- a/mozilla/xpcom/ds/nsString.h +++ b/mozilla/xpcom/ds/nsString.h @@ -204,7 +204,7 @@ public: void ReplaceSubstring(const nsCString& aTarget,const nsCString& aNewValue); void ReplaceSubstring(const char* aTarget,const char* aNewValue); - PRInt32 CountChar(PRUnichar aChar); + PRInt32 CountChar(PRUnichar aChar) const; /** * This method trims characters found in aTrimSet from diff --git a/mozilla/xpcom/ds/nsString2.cpp b/mozilla/xpcom/ds/nsString2.cpp index ad0611f101c..6e8434be662 100644 --- a/mozilla/xpcom/ds/nsString2.cpp +++ b/mozilla/xpcom/ds/nsString2.cpp @@ -500,7 +500,7 @@ nsString::ReplaceSubstring(const nsString& aTarget,const nsString& aNewValue){ * @param * @return *this */ -PRInt32 nsString::CountChar(PRUnichar aChar) { +PRInt32 nsString::CountChar(PRUnichar aChar) const { PRInt32 theIndex=0; PRInt32 theCount=0; PRInt32 theLen=(PRInt32)mLength; diff --git a/mozilla/xpcom/ds/nsString2.h b/mozilla/xpcom/ds/nsString2.h index 1d4edabfdf7..b0fc4f310b9 100644 --- a/mozilla/xpcom/ds/nsString2.h +++ b/mozilla/xpcom/ds/nsString2.h @@ -242,7 +242,7 @@ public: void ReplaceSubstring( const nsString& aTarget, const nsString& aNewValue ); void ReplaceSubstring( const PRUnichar* aTarget, const PRUnichar* aNewValue ); - PRInt32 CountChar( PRUnichar aChar ); + PRInt32 CountChar( PRUnichar aChar ) const; /** * This method trims characters found in aTrimSet from diff --git a/mozilla/xpcom/string/obsolete/nsStr.h b/mozilla/xpcom/string/obsolete/nsStr.h index 631687c8cf1..fbe62321288 100644 --- a/mozilla/xpcom/string/obsolete/nsStr.h +++ b/mozilla/xpcom/string/obsolete/nsStr.h @@ -484,7 +484,7 @@ inline void Recycle( PRUnichar* aBuffer) { nsMemory::Free(aBuffer); } * @param anIndex tells us where in dest to get the char from * @return the given char, or 0 if anIndex is out of range */ -inline PRUnichar GetCharAt(const nsStr& aDest,PRUint32 anIndex){ +inline PRUnichar GetCharAt(const nsStr& aDest,PRUint32 anIndex) { if(anIndex<aDest.mLength) { return (eTwoByte==aDest.mCharSize) ? aDest.mUStr[anIndex] : (PRUnichar)aDest.mStr[anIndex]; }//if diff --git a/mozilla/xpcom/string/obsolete/nsString.cpp b/mozilla/xpcom/string/obsolete/nsString.cpp index ff3129d4c0e..92624c14d6b 100644 --- a/mozilla/xpcom/string/obsolete/nsString.cpp +++ b/mozilla/xpcom/string/obsolete/nsString.cpp @@ -473,7 +473,7 @@ nsCString::ReplaceSubstring(const nsCString& aTarget,const nsCString& aNewValue) * @param * @return *this */ -PRInt32 nsCString::CountChar(PRUnichar aChar) { +PRInt32 nsCString::CountChar(PRUnichar aChar) const { PRInt32 theIndex=0; PRInt32 theCount=0; PRInt32 theLen=(PRInt32)mLength; diff --git a/mozilla/xpcom/string/obsolete/nsString.h b/mozilla/xpcom/string/obsolete/nsString.h index 446200f3855..4ab205c2b29 100644 --- a/mozilla/xpcom/string/obsolete/nsString.h +++ b/mozilla/xpcom/string/obsolete/nsString.h @@ -204,7 +204,7 @@ public: void ReplaceSubstring(const nsCString& aTarget,const nsCString& aNewValue); void ReplaceSubstring(const char* aTarget,const char* aNewValue); - PRInt32 CountChar(PRUnichar aChar); + PRInt32 CountChar(PRUnichar aChar) const; /** * This method trims characters found in aTrimSet from diff --git a/mozilla/xpcom/string/obsolete/nsString2.cpp b/mozilla/xpcom/string/obsolete/nsString2.cpp index ad0611f101c..6e8434be662 100644 --- a/mozilla/xpcom/string/obsolete/nsString2.cpp +++ b/mozilla/xpcom/string/obsolete/nsString2.cpp @@ -500,7 +500,7 @@ nsString::ReplaceSubstring(const nsString& aTarget,const nsString& aNewValue){ * @param * @return *this */ -PRInt32 nsString::CountChar(PRUnichar aChar) { +PRInt32 nsString::CountChar(PRUnichar aChar) const { PRInt32 theIndex=0; PRInt32 theCount=0; PRInt32 theLen=(PRInt32)mLength; diff --git a/mozilla/xpcom/string/obsolete/nsString2.h b/mozilla/xpcom/string/obsolete/nsString2.h index 1d4edabfdf7..b0fc4f310b9 100644 --- a/mozilla/xpcom/string/obsolete/nsString2.h +++ b/mozilla/xpcom/string/obsolete/nsString2.h @@ -242,7 +242,7 @@ public: void ReplaceSubstring( const nsString& aTarget, const nsString& aNewValue ); void ReplaceSubstring( const PRUnichar* aTarget, const PRUnichar* aNewValue ); - PRInt32 CountChar( PRUnichar aChar ); + PRInt32 CountChar( PRUnichar aChar ) const; /** * This method trims characters found in aTrimSet from diff --git a/mozilla/xpcom/string/public/nsAlgorithm.h b/mozilla/xpcom/string/public/nsAlgorithm.h index b5360b07aaf..9c2e5855cc1 100755 --- a/mozilla/xpcom/string/public/nsAlgorithm.h +++ b/mozilla/xpcom/string/public/nsAlgorithm.h @@ -109,5 +109,4 @@ copy_string_backward( const InputIterator& first, InputIterator& last, OutputIte return result; } - #endif // !defined(nsAlgorithm_h___) diff --git a/mozilla/xpcom/string/public/nsBufferHandle.h b/mozilla/xpcom/string/public/nsBufferHandle.h index e3004276127..b8cf0688dba 100755 --- a/mozilla/xpcom/string/public/nsBufferHandle.h +++ b/mozilla/xpcom/string/public/nsBufferHandle.h @@ -86,7 +86,7 @@ class nsSharedBufferHandle nsSharedBufferHandle( CharT* aDataStart, CharT* aDataEnd ) : nsBufferHandle<CharT>(aDataStart, aDataEnd) { - mFlags |= kIsShared; + mFlags = kIsShared; } ~nsSharedBufferHandle(); diff --git a/mozilla/xpcom/string/public/nsReadableUtils.h b/mozilla/xpcom/string/public/nsReadableUtils.h index 5a7bd9285b9..33b6c6ec254 100755 --- a/mozilla/xpcom/string/public/nsReadableUtils.h +++ b/mozilla/xpcom/string/public/nsReadableUtils.h @@ -35,10 +35,8 @@ #include "nsAWritableString.h" #endif -#if 0 NS_COM size_t Distance( const nsReadingIterator<PRUnichar>&, const nsReadingIterator<PRUnichar>& ); NS_COM size_t Distance( const nsReadingIterator<char>&, const nsReadingIterator<char>& ); -#endif NS_COM void CopyUCS2toASCII( const nsAReadableString& aSource, nsAWritableCString& aDest ); @@ -115,15 +113,46 @@ NS_COM PRUnichar* ToNewUnicode( const nsAReadableCString& aSource ); * After this operation |aDest| is not null terminated. * * @param aSource a 16-bit wide string + * @param aSrcOffset start offset in the source string * @param aDest a |PRUnichar| buffer * @param aLength the number of 16-bit characters to copy * @return pointer to destination buffer - identical to |aDest| */ NS_COM PRUnichar* CopyUnicodeTo( const nsAReadableString& aSource, + PRUint32 aSrcOffset, PRUnichar* aDest, PRUint32 aLength ); + /** + * Copies 16-bit characters between iterators |aSrcStart| and + * |aSrcEnd| to the writable string |aDest|. Similar to the + * |nsString::Mid| method. + * + * After this operation |aDest| is not null terminated. + * + * @param aSrcStart start source iterator + * @param aSrcEnd end source iterator + * @param aDest destination for the copy + */ +NS_COM void CopyUnicodeTo( const nsReadingIterator<PRUnichar>& aSrcStart, + const nsReadingIterator<PRUnichar>& aSrcEnd, + nsAWritableString& aDest ); + + /** + * Appends 16-bit characters between iterators |aSrcStart| and + * |aSrcEnd| to the writable string |aDest|. + * + * After this operation |aDest| is not null terminated. + * + * @param aSrcStart start source iterator + * @param aSrcEnd end source iterator + * @param aDest destination for the copy + */ +NS_COM void AppendUnicodeTo( const nsReadingIterator<PRUnichar>& aSrcStart, + const nsReadingIterator<PRUnichar>& aSrcEnd, + nsAWritableString& aDest ); + /** * Returns |PR_TRUE| if |aString| contains only ASCII characters, that is, characters in the range (0x00, 0x7F). * @@ -142,4 +171,47 @@ NS_COM void ToUpperCase( nsAWritableCString& ); NS_COM void ToLowerCase( nsAWritableString& ); NS_COM void ToLowerCase( nsAWritableCString& ); + /** + * Finds the leftmost occurance of |aPattern|, if any in the range |aSearchStart|..|aSearchEnd|. + * + * Returns |PR_TRUE| if a match was found, and adjusts |aSearchStart| and |aSearchEnd| to + * point to the match. If no match was found, returns |PR_FALSE| and makes |aSearchStart == aSearchEnd|. + * + * Currently, this is equivalent to the O(m*n) implementation previously on |ns[C]String|. + * If we need something faster; we can implement that later. + */ +NS_COM PRBool FindInReadable( const nsAReadableString& aPattern, nsReadingIterator<PRUnichar>&, nsReadingIterator<PRUnichar>& ); +NS_COM PRBool FindInReadable( const nsAReadableCString& aPattern, nsReadingIterator<char>&, nsReadingIterator<char>& ); + + + /** + * Finds the rightmost occurance of |aPattern| + * Returns |PR_TRUE| if a match was found, and adjusts |aSearchStart| and |aSearchEnd| to + * point to the match. If no match was found, returns |PR_FALSE| and makes |aSearchStart == aSearchEnd|. + * + * Currently, this is equivalent to the O(m*n) implementation previously on |ns[C]String|. + * If we need something faster; we can implement that later. + */ +NS_COM PRBool RFindInReadable( const nsAReadableString& aPattern, nsReadingIterator<PRUnichar>&, nsReadingIterator<PRUnichar>& ); +NS_COM PRBool RFindInReadable( const nsAReadableCString& aPattern, nsReadingIterator<char>&, nsReadingIterator<char>& ); + + /** + * Finds the leftmost occurance of |aChar|, if any in the range + * |aSearchStart|..|aSearchEnd|. + * + * Returns |PR_TRUE| if a match was found, and adjusts |aSearchStart| to + * point to the match. If no match was found, returns |PR_FALSE| and + * makes |aSearchStart == aSearchEnd|. + */ +NS_COM PRBool FindCharInReadable( PRUnichar aChar, nsReadingIterator<PRUnichar>&, nsReadingIterator<PRUnichar>& ); +NS_COM PRBool FindCharInReadable( char aChar, nsReadingIterator<char>&, nsReadingIterator<char>& ); + + /** + * Finds the number of occurences of |aChar| in the string |aStr| + */ +NS_COM PRUint32 CountCharInReadable( const nsAReadableString& aStr, + PRUnichar aChar ); +NS_COM PRUint32 CountCharInReadable( const nsAReadableCString& aStr, + char aChar ); + #endif // !defined(nsReadableUtils_h___) diff --git a/mozilla/xpcom/string/public/nsSharedBufferList.h b/mozilla/xpcom/string/public/nsSharedBufferList.h index c740d399328..38213b1190e 100755 --- a/mozilla/xpcom/string/public/nsSharedBufferList.h +++ b/mozilla/xpcom/string/public/nsSharedBufferList.h @@ -40,6 +40,12 @@ // for |nsReadingIterator| #endif +#ifndef nsBufferHandleUtils_h___ +#include "nsBufferHandleUtils.h" + // for |NS_AllocateContiguousHandleWithData| +#endif + + /** * This class forms the basis for several multi-fragment string classes, in * particular: |nsFragmentedString| (though not yet), and |nsSlidingString|/|nsSlidingSubstring|. @@ -63,6 +69,27 @@ class nsSharedBufferList this->mFlags |= this->kIsSingleAllocationWithBuffer; } + /** + * These buffers will be `owned' by the list, and only the + * the list itself will be allowed to delete member |Buffer|s, + * therefore, we cannot use the inherited |AcquireReference| + * and |ReleaseReference|, as they use the model that the + * buffer manages its own lifetime. + */ + void + AcquireNonOwningReference() const + { + Buffer* mutable_this = NS_CONST_CAST(Buffer*, this); + mutable_this->set_refcount( get_refcount()+1 ); + } + + void + ReleaseNonOwningReference() const + { + Buffer* mutable_this = NS_CONST_CAST(Buffer*, this); + mutable_this->set_refcount( get_refcount()-1 ); + } + Buffer* mPrev; Buffer* mNext; @@ -108,6 +135,9 @@ class nsSharedBufferList // Position( const Position& ); -- automatically generated copy-constructor is OK // Position& operator=( const Position& ); -- automatically generated copy-assignment operator is OK + + // don't want to provide this as |operator-|, since that might imply O(1) + static ptrdiff_t Distance( const Position&, const Position& ); }; @@ -137,8 +167,20 @@ class nsSharedBufferList Buffer* UnlinkBuffer( Buffer* ); void SplitBuffer( const Position& ); - static Buffer* NewSingleAllocationBuffer( const PRUnichar*, PRUint32, PRUint32 = 0 ); - static Buffer* NewWrappingBuffer( PRUnichar*, PRUnichar*, PRUnichar* ); + static + Buffer* + NewSingleAllocationBuffer( const PRUnichar* aData, PRUint32 aDataLength, PRUint32 aAdditionalCapacity = 1 ) + { + typedef Buffer* Buffer_ptr; + return NS_AllocateContiguousHandleWithData(Buffer_ptr(0), nsLiteralString(aData, aDataLength), aAdditionalCapacity); + } + + static + Buffer* + NewWrappingBuffer( PRUnichar* aDataStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd ) + { + return new Buffer(aDataStart, aDataEnd, aDataStart, aStorageEnd); + } void DiscardSuffix( PRUint32 ); // need other discards: prefix, and by iterator or pointer or something diff --git a/mozilla/xpcom/string/public/nsSlidingString.h b/mozilla/xpcom/string/public/nsSlidingString.h index 6dc2e55210d..af36acc39eb 100755 --- a/mozilla/xpcom/string/public/nsSlidingString.h +++ b/mozilla/xpcom/string/public/nsSlidingString.h @@ -45,7 +45,7 @@ * of the list. |nsSlidingString| also the client to advance its starting point. * */ -class nsSlidingSharedBufferList +class NS_COM nsSlidingSharedBufferList : public nsSharedBufferList { public: @@ -63,35 +63,86 @@ class nsSlidingSharedBufferList +class nsSlidingString; /** * a substring over a buffer list, this */ -class nsSlidingSubstring - : public nsPromiseReadable<PRUnichar> +class NS_COM nsSlidingSubstring + : virtual public nsPromiseReadable<PRUnichar> { + friend class nsSlidingString; + public: typedef nsSlidingSharedBufferList::Buffer Buffer; typedef nsSlidingSharedBufferList::Position Position; + nsSlidingSubstring() + : mStart(0,0), + mEnd(0,0), + mBufferList(0), + mLength(0) + { + // nothing else to do here + } + nsSlidingSubstring( const nsSlidingSubstring& ); // copy-constructor nsSlidingSubstring( const nsSlidingSubstring& aString, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd ); + nsSlidingSubstring( const nsSlidingString& ); + nsSlidingSubstring( const nsSlidingString& aString, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd ); + explicit nsSlidingSubstring( const nsAReadableString& ); + // copy the supplied string into a new buffer ... there will be no modifying instance over this buffer list + + void Rebind( const nsSlidingSubstring& ); + void Rebind( const nsSlidingSubstring&, const nsReadingIterator<PRUnichar>&, const nsReadingIterator<PRUnichar>& ); + void Rebind( const nsSlidingString& ); + void Rebind( const nsSlidingString&, const nsReadingIterator<PRUnichar>&, const nsReadingIterator<PRUnichar>& ); + void Rebind( const nsAReadableString& ); + ~nsSlidingSubstring(); virtual PRUint32 Length() const { return mLength; } protected: - nsSlidingSubstring( nsSlidingSharedBufferList& aBufferList ); + nsSlidingSubstring( nsSlidingSharedBufferList* aBufferList ); virtual const PRUnichar* GetReadableFragment( nsReadableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) const; private: // can't assign into me, I'm a read-only reference void operator=( const nsSlidingSubstring& ); // NOT TO BE IMPLEMENTED + void + init_range_from_buffer_list() + // used only from constructors + { + mStart.PointBefore(mBufferList->GetFirstBuffer()); + mEnd.PointAfter(mBufferList->GetLastBuffer()); + mLength = PRUint32(Position::Distance(mStart, mEnd)); + } + + void + acquire_ownership_of_buffer_list() const + // used only from constructors and |Rebind|, requires |mStart| already be initialized + { + mBufferList->AcquireReference(); + mStart.mBuffer->AcquireNonOwningReference(); + } + + void + release_ownership_of_buffer_list() + { + if ( mBufferList ) + { + mStart.mBuffer->ReleaseNonOwningReference(); + mBufferList->DiscardUnreferencedPrefix(mStart.mBuffer); + mBufferList->ReleaseReference(); + } + } + protected: Position mStart; Position mEnd; - nsSlidingSharedBufferList& mBufferList; + nsSlidingSharedBufferList* mBufferList; PRUint32 mLength; }; @@ -102,14 +153,19 @@ class nsSlidingSubstring * An |nsSlidingSharedBufferList| may be modified by zero or one instances of this class. * */ -class nsSlidingString - : public nsSlidingSubstring +class NS_COM nsSlidingString + : virtual public nsPromiseReadable<PRUnichar>, + private nsSlidingSubstring { + friend class nsSlidingSubstring; + public: nsSlidingString( PRUnichar* aStorageStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd ); // ...created by consuming ownership of a buffer ... |aStorageStart| must point to something // that it will be OK for the slidking string to call |nsMemory::Free| on + virtual PRUint32 Length() const { return mLength; } + // you are giving ownership to the string, it takes and keeps your buffer, deleting it (with |nsMemory::Free|) when done void AppendBuffer( PRUnichar* aStorageStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd ); @@ -118,18 +174,21 @@ class nsSlidingString void DiscardPrefix( const nsReadingIterator<PRUnichar>& ); // any other way you want to do this? + protected: + virtual const PRUnichar* GetReadableFragment( nsReadableFragment<PRUnichar>&, nsFragmentRequest, PRUint32 ) const; + private: + + void + acquire_ownership_of_buffer_list() const + // used only from constructors and |Rebind|, requires |mStart| already be initialized + { + mBufferList->AcquireReference(); + mStart.mBuffer->AcquireNonOwningReference(); + } + nsSlidingString( const nsSlidingString& ); // NOT TO BE IMPLEMENTED void operator=( const nsSlidingString& ); // NOT TO BE IMPLEMENTED }; - -#if 0 - // this (or something similar) is what should appear in the parser, I think -#include "nsSlidingString.h" - -typedef nsSlidingString nsParserString; -typedef nsSlidingSubstring nsParserToken; -#endif - #endif // !defined(nsSlidingString_h___) diff --git a/mozilla/xpcom/string/src/nsReadableUtils.cpp b/mozilla/xpcom/string/src/nsReadableUtils.cpp index a2101512940..e05326fcc4b 100755 --- a/mozilla/xpcom/string/src/nsReadableUtils.cpp +++ b/mozilla/xpcom/string/src/nsReadableUtils.cpp @@ -229,14 +229,43 @@ ToNewUnicode( const nsAReadableCString& aSource ) NS_COM PRUnichar* -CopyUnicodeTo( const nsAReadableString& aSource, PRUnichar* aDest, PRUint32 aLength ) +CopyUnicodeTo( const nsAReadableString& aSource, PRUint32 aSrcOffset, PRUnichar* aDest, PRUint32 aLength ) { nsReadingIterator<PRUnichar> fromBegin, fromEnd; - PRUnichar* toBegin = aDest; - copy_string(aSource.BeginReading(fromBegin), aSource.BeginReading(fromEnd).advance( PRInt32(aLength) ), toBegin); + PRUnichar* toBegin = aDest; + copy_string(aSource.BeginReading(fromBegin).advance( PRInt32(aSrcOffset) ), aSource.BeginReading(fromEnd).advance( PRInt32(aSrcOffset+aLength) ), toBegin); return aDest; } +NS_COM +void +CopyUnicodeTo( const nsReadingIterator<PRUnichar>& aSrcStart, + const nsReadingIterator<PRUnichar>& aSrcEnd, + nsAWritableString& aDest ) + { + nsWritingIterator<PRUnichar> writer; + aDest.SetLength(Distance(aSrcStart, aSrcEnd)); + aDest.BeginWriting(writer); + nsReadingIterator<PRUnichar> fromBegin(aSrcStart); + + copy_string(fromBegin, aSrcEnd, writer); + } + +NS_COM +void +AppendUnicodeTo( const nsReadingIterator<PRUnichar>& aSrcStart, + const nsReadingIterator<PRUnichar>& aSrcEnd, + nsAWritableString& aDest ) + { + nsWritingIterator<PRUnichar> writer; + PRUint32 oldLength = aDest.Length(); + aDest.SetLength(oldLength + Distance(aSrcStart, aSrcEnd)); + aDest.BeginWriting(writer).advance(oldLength); + nsReadingIterator<PRUnichar> fromBegin(aSrcStart); + + copy_string(fromBegin, aSrcEnd, writer); + } + NS_COM PRBool IsASCII( const nsAReadableString& aString ) @@ -341,3 +370,224 @@ ToLowerCase( nsAWritableCString& aCString ) ConvertToLowerCase<char> converter; copy_string(aCString.BeginWriting(fromBegin), aCString.EndWriting(fromEnd), converter); } + + +template <class CharT> +inline // probably wishful thinking +PRBool +FindInReadable_Impl( const basic_nsAReadableString<CharT>& aPattern, + nsReadingIterator<CharT>& aSearchStart, + nsReadingIterator<CharT>& aSearchEnd ) + { + PRBool found_it = PR_FALSE; + + // only bother searching at all if we're given a non-empty range to search + if ( aSearchStart != aSearchEnd ) + { + nsReadingIterator<CharT> aPatternStart, aPatternEnd; + aPattern.BeginReading(aPatternStart); + aPattern.EndReading(aPatternEnd); + + // outer loop keeps searching till we find it or run out of string to search + while ( !found_it ) + { + // fast inner loop (that's what it's called, not what it is) looks for a potential match + while ( aSearchStart != aSearchEnd && *aPatternStart != *aSearchStart ) + ++aSearchStart; + + // if we broke out of the `fast' loop because we're out of string ... we're done: no match + if ( aSearchStart == aSearchEnd ) + break; + + // otherwise, we're at a potential match, let's see if we really hit one + nsReadingIterator<CharT> testPattern(aPatternStart); + nsReadingIterator<CharT> testSearch(aSearchStart); + + // slow inner loop verifies the potential match (found by the `fast' loop) at the current position + for(;;) + { + // we already compared the first character in the outer loop, + // so we'll advance before the next comparison + ++testPattern; + ++testSearch; + + // if we verified all the way to the end of the pattern, then we found it! + if ( testPattern == aPatternEnd ) + { + found_it = PR_TRUE; + aSearchEnd = testSearch; // return the exact found range through the parameters + break; + } + + // if we got to end of the string we're searching before we hit the end of the + // pattern, we'll never find what we're looking for + if ( testSearch == aSearchEnd ) + { + aSearchStart = aSearchEnd; + break; + } + + // else if we mismatched ... it's time to advance to the next search position + // and get back into the `fast' loop + if ( *testPattern != *testSearch ) + { + ++aSearchStart; + break; + } + } + } + } + + return found_it; + } + +NS_COM +PRBool +FindInReadable( const nsAReadableString& aPattern, nsReadingIterator<PRUnichar>& aSearchStart, nsReadingIterator<PRUnichar>& aSearchEnd ) + { + return FindInReadable_Impl(aPattern, aSearchStart, aSearchEnd); + } + +NS_COM +PRBool +FindInReadable( const nsAReadableCString& aPattern, nsReadingIterator<char>& aSearchStart, nsReadingIterator<char>& aSearchEnd ) + { + return FindInReadable_Impl(aPattern, aSearchStart, aSearchEnd); + } + + /** + * This implementation is simple, but does too much work. + * It searches the entire string from left to right, and returns the last match found, if any. + * This implementation will be replaced when I get |reverse_iterator|s working. + */ +template <class CharT> +inline // probably wishful thinking +PRBool +RFindInReadable_Impl( const basic_nsAReadableString<CharT>& aPattern, + nsReadingIterator<CharT>& aSearchStart, + nsReadingIterator<CharT>& aSearchEnd ) + { + PRBool found_it = PR_FALSE; + + nsReadingIterator<CharT> savedSearchEnd(aSearchEnd); + nsReadingIterator<CharT> searchStart(aSearchStart), searchEnd(aSearchEnd); + + while ( searchStart != searchEnd ) + { + if ( FindInReadable(aPattern, searchStart, searchEnd) ) + { + found_it = PR_TRUE; + + // this is the best match so far, so remember it + aSearchStart = searchStart; + aSearchEnd = searchEnd; + + // ...and get ready to search some more + // (it's tempting to set |searchStart=searchEnd| ... but that misses overlapping patterns) + ++searchStart; + searchEnd = savedSearchEnd; + } + } + + // if we never found it, return an empty range + if ( !found_it ) + aSearchStart = aSearchEnd; + + return found_it; + } + + +NS_COM +PRBool +RFindInReadable( const nsAReadableString& aPattern, nsReadingIterator<PRUnichar>& aSearchStart, nsReadingIterator<PRUnichar>& aSearchEnd ) + { + return RFindInReadable_Impl(aPattern, aSearchStart, aSearchEnd); + } + +NS_COM +PRBool +RFindInReadable( const nsAReadableCString& aPattern, nsReadingIterator<char>& aSearchStart, nsReadingIterator<char>& aSearchEnd ) + { + return RFindInReadable_Impl(aPattern, aSearchStart, aSearchEnd); + } + + + +template <class CharT> +inline // probably wishful thinking +PRBool +FindCharInReadable_Impl( CharT aChar, + nsReadingIterator<CharT>& aSearchStart, + nsReadingIterator<CharT>& aSearchEnd ) + { + while ( aSearchStart != aSearchEnd ) + { + PRInt32 fragmentLength; + if ( SameFragment(aSearchStart, aSearchEnd) ) + fragmentLength = aSearchEnd.get() - aSearchStart.get(); + else + fragmentLength = aSearchStart.size_forward(); + + const CharT* charFoundAt = nsCharTraits<CharT>::find(aSearchStart.get(), fragmentLength, aChar); + if ( charFoundAt ) { + aSearchStart.advance( charFoundAt - aSearchStart.get() ); + return PR_TRUE; + } + + aSearchStart.advance(fragmentLength); + } + + return PR_FALSE; + } + + +NS_COM +PRBool +FindCharInReadable( PRUnichar aChar, nsReadingIterator<PRUnichar>& aSearchStart, nsReadingIterator<PRUnichar>& aSearchEnd ) + { + return FindCharInReadable_Impl(aChar, aSearchStart, aSearchEnd); + } + +NS_COM +PRBool +FindCharInReadable( char aChar, nsReadingIterator<char>& aSearchStart, nsReadingIterator<char>& aSearchEnd ) + { + return FindCharInReadable_Impl(aChar, aSearchStart, aSearchEnd); + } + +template <class CharT> +PRUint32 +CountCharInReadable_Impl( const basic_nsAReadableString<CharT>& aStr, + CharT aChar ) +{ + PRUint32 count = 0; + nsReadingIterator<CharT> begin, end; + + aStr.BeginReading(begin); + aStr.EndReading(end); + + while (begin != end) { + if (*begin == aChar) { + count++; + } + begin++; + } + + return count; +} + +NS_COM +PRUint32 +CountCharInReadable( const nsAReadableString& aStr, + PRUnichar aChar ) +{ + return CountCharInReadable_Impl(aStr, aChar); +} + +NS_COM +PRUint32 +CountCharInReadable( const nsAReadableCString& aStr, + char aChar ) +{ + return CountCharInReadable_Impl(aStr, aChar); +} diff --git a/mozilla/xpcom/string/src/nsSharedBufferList.cpp b/mozilla/xpcom/string/src/nsSharedBufferList.cpp index 76f50aa9eaa..584890a75ec 100755 --- a/mozilla/xpcom/string/src/nsSharedBufferList.cpp +++ b/mozilla/xpcom/string/src/nsSharedBufferList.cpp @@ -23,9 +23,29 @@ */ #include "nsSharedBufferList.h" + +#ifndef nsAlgorithm_h___ #include "nsAlgorithm.h" // for |copy_string| -#include <new.h> +#endif + + +ptrdiff_t +nsSharedBufferList::Position::Distance( const Position& aStart, const Position& aEnd ) + { + ptrdiff_t result = 0; + if ( aStart.mBuffer == aEnd.mBuffer ) + result = aEnd.mPosInBuffer - aStart.mPosInBuffer; + else + { + result = aStart.mBuffer->DataEnd() - aStart.mPosInBuffer; + for ( Buffer* b = aStart.mBuffer->mNext; b != aEnd.mBuffer; b = b->mNext ) + result += b->DataLength(); + result += aEnd.mPosInBuffer - aEnd.mBuffer->DataStart(); + } + + return result; + } void @@ -48,36 +68,6 @@ nsSharedBufferList::~nsSharedBufferList() } -nsSharedBufferList::Buffer* -nsSharedBufferList::NewSingleAllocationBuffer( const PRUnichar* aData, PRUint32 aDataLength, PRUint32 aAdditionalSpace ) - { - size_t object_size = ((sizeof(Buffer) + sizeof(PRUnichar) - 1) / sizeof(PRUnichar)) * sizeof(PRUnichar); - PRUint32 buffer_length = aDataLength + aAdditionalSpace; - size_t buffer_size = size_t(buffer_length) * sizeof(PRUnichar); - - void* object_ptr = operator new(object_size + buffer_size); - if ( object_ptr ) - { - typedef PRUnichar* PRUnichar_ptr; - PRUnichar* buffer_ptr = PRUnichar_ptr(NS_STATIC_CAST(unsigned char*, object_ptr) + object_size); - if ( aDataLength ) - { - PRUnichar* toBegin = buffer_ptr; - copy_string(aData, aData+aDataLength, toBegin); - } - return new (object_ptr) Buffer(buffer_ptr, buffer_ptr+aDataLength, buffer_ptr, buffer_ptr+buffer_length, PR_TRUE); - } - - return 0; - } - -nsSharedBufferList::Buffer* -nsSharedBufferList::NewWrappingBuffer( PRUnichar* aDataStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd ) - { - return new Buffer(aDataStart, aDataEnd, aDataStart, aStorageEnd); - } - - void nsSharedBufferList::LinkBuffer( Buffer* aPrevBuffer, Buffer* aNewBuffer, Buffer* aNextBuffer ) diff --git a/mozilla/xpcom/string/src/nsSlidingString.cpp b/mozilla/xpcom/string/src/nsSlidingString.cpp index 58c7698c3d4..8b07b17256e 100755 --- a/mozilla/xpcom/string/src/nsSlidingString.cpp +++ b/mozilla/xpcom/string/src/nsSlidingString.cpp @@ -24,6 +24,18 @@ #include "nsSlidingString.h" +#ifndef nsBufferHandleUtils_h___ +#include "nsBufferHandleUtils.h" +#endif + +#include <new.h> + + + + /** + * |nsSlidingSharedBufferList| + */ + void nsSlidingSharedBufferList::DiscardUnreferencedPrefix( Buffer* aRecentlyReleasedBuffer ) { @@ -35,62 +47,159 @@ nsSlidingSharedBufferList::DiscardUnreferencedPrefix( Buffer* aRecentlyReleasedB } -ptrdiff_t Distance( const nsSharedBufferList::Position&, const nsSharedBufferList::Position& ); -ptrdiff_t -Distance( const nsSharedBufferList::Position& aStart, const nsSharedBufferList::Position& aEnd ) - { - ptrdiff_t result = 0; - if ( aStart.mBuffer == aEnd.mBuffer ) - result = aEnd.mPosInBuffer - aStart.mPosInBuffer; - else - { - result = aStart.mBuffer->DataEnd() - aStart.mPosInBuffer; - for ( nsSharedBufferList::Buffer* b = aStart.mBuffer->mNext; b != aEnd.mBuffer; b = b->mNext ) - result += b->DataLength(); - result += aEnd.mPosInBuffer - aEnd.mBuffer->DataStart(); - } - - return result; - } + /** + * |nsSlidingSubstring| + */ + // copy constructor nsSlidingSubstring::nsSlidingSubstring( const nsSlidingSubstring& aString ) : mStart(aString.mStart), mEnd(aString.mEnd), mBufferList(aString.mBufferList), mLength(aString.mLength) { - mBufferList.AcquireReference(); - mStart.mBuffer->AcquireReference(); + acquire_ownership_of_buffer_list(); } nsSlidingSubstring::nsSlidingSubstring( const nsSlidingSubstring& aString, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd ) : mStart(aStart), mEnd(aEnd), mBufferList(aString.mBufferList), - mLength(PRUint32(Distance(mStart, mEnd))) + mLength(PRUint32(Position::Distance(mStart, mEnd))) { - mBufferList.AcquireReference(); - mStart.mBuffer->AcquireReference(); + acquire_ownership_of_buffer_list(); } -nsSlidingSubstring::nsSlidingSubstring( nsSlidingSharedBufferList& aBufferList ) +nsSlidingSubstring::nsSlidingSubstring( const nsSlidingString& aString ) + : mStart(aString.mStart), + mEnd(aString.mEnd), + mBufferList(aString.mBufferList), + mLength(aString.mLength) + { + acquire_ownership_of_buffer_list(); + } + +nsSlidingSubstring::nsSlidingSubstring( const nsSlidingString& aString, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd ) + : mStart(aStart), + mEnd(aEnd), + mBufferList(aString.mBufferList), + mLength(PRUint32(Position::Distance(mStart, mEnd))) + { + acquire_ownership_of_buffer_list(); + } + +nsSlidingSubstring::nsSlidingSubstring( nsSlidingSharedBufferList* aBufferList ) : mBufferList(aBufferList) { - mBufferList.AcquireReference(); + init_range_from_buffer_list(); + acquire_ownership_of_buffer_list(); + } - mStart.PointBefore(mBufferList.GetFirstBuffer()); - mStart.mBuffer->AcquireReference(); +typedef const nsSharedBufferList::Buffer* Buffer_ptr; - mEnd.PointAfter(mBufferList.GetLastBuffer()); - mLength = PRUint32(Distance(mStart, mEnd)); +static nsSharedBufferList::Buffer* +AllocateContiguousHandleWithData( Buffer_ptr aDummyHandlePtr, const nsAReadableString& aDataSource ) + { + typedef const PRUnichar* PRUnichar_ptr; + + // figure out the number of bytes needed the |HandleT| part, including padding to correctly align the data part + size_t handle_size = NS_AlignedHandleSize(aDummyHandlePtr, PRUnichar_ptr(0)); + + // figure out how many |CharT|s wee need to fit in the data part + size_t string_length = aDataSource.Length(); + + // how many bytes is that (including a zero-terminator so we can claim to be flat)? + size_t string_size = (string_length+1) * sizeof(PRUnichar); + + + nsSharedBufferList::Buffer* result = 0; + void* handle_ptr = ::operator new(handle_size + string_size); + + if ( handle_ptr ) + { + typedef PRUnichar* PRUnichar_ptr; + PRUnichar* string_start_ptr = PRUnichar_ptr(NS_STATIC_CAST(unsigned char*, handle_ptr) + handle_size); + PRUnichar* string_end_ptr = string_start_ptr + string_length; + + nsReadingIterator<PRUnichar> fromBegin, fromEnd; + PRUnichar* toBegin = string_start_ptr; + copy_string(aDataSource.BeginReading(fromBegin), aDataSource.EndReading(fromEnd), toBegin); + result = new (handle_ptr) nsSharedBufferList::Buffer(string_start_ptr, string_end_ptr, string_start_ptr, string_end_ptr+1, PR_TRUE); + } + + return result; + } + +nsSlidingSubstring::nsSlidingSubstring( const nsAReadableString& aSourceString ) + : mBufferList(new nsSlidingSharedBufferList(AllocateContiguousHandleWithData(Buffer_ptr(0), aSourceString))) + { + init_range_from_buffer_list(); + acquire_ownership_of_buffer_list(); + } + +void +nsSlidingSubstring::Rebind( const nsSlidingSubstring& aString ) + { + aString.acquire_ownership_of_buffer_list(); + release_ownership_of_buffer_list(); + + mStart = aString.mStart; + mEnd = aString.mEnd; + mBufferList = aString.mBufferList; + mLength = aString.mLength; + } + +void +nsSlidingSubstring::Rebind( const nsSlidingSubstring& aString, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd ) + { + release_ownership_of_buffer_list(); + + mStart = aStart; + mEnd = aEnd; + mBufferList = aString.mBufferList; + mLength = PRUint32(Position::Distance(mStart, mEnd)); + + acquire_ownership_of_buffer_list(); + } + +void +nsSlidingSubstring::Rebind( const nsSlidingString& aString ) + { + aString.acquire_ownership_of_buffer_list(); + release_ownership_of_buffer_list(); + + mStart = aString.mStart; + mEnd = aString.mEnd; + mBufferList = aString.mBufferList; + mLength = aString.mLength; + } + +void +nsSlidingSubstring::Rebind( const nsSlidingString& aString, const nsReadingIterator<PRUnichar>& aStart, const nsReadingIterator<PRUnichar>& aEnd ) + { + release_ownership_of_buffer_list(); + + mStart = aStart; + mEnd = aEnd; + mBufferList = aString.mBufferList; + mLength = PRUint32(Position::Distance(mStart, mEnd)); + + acquire_ownership_of_buffer_list(); + } + +void +nsSlidingSubstring::Rebind( const nsAReadableString& aSourceString ) + { + release_ownership_of_buffer_list(); + mBufferList = new nsSlidingSharedBufferList(AllocateContiguousHandleWithData(Buffer_ptr(0), aSourceString)); + init_range_from_buffer_list(); + acquire_ownership_of_buffer_list(); } nsSlidingSubstring::~nsSlidingSubstring() { - mStart.mBuffer->ReleaseReference(); - mBufferList.DiscardUnreferencedPrefix(mStart.mBuffer); - mBufferList.ReleaseReference(); + release_ownership_of_buffer_list(); } const PRUnichar* @@ -149,8 +258,12 @@ nsSlidingSubstring::GetReadableFragment( nsReadableFragment<PRUnichar>& aFragmen + /** + * |nsSlidingString| + */ + nsSlidingString::nsSlidingString( PRUnichar* aStorageStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd ) - : nsSlidingSubstring(*(new nsSlidingSharedBufferList(nsSlidingSharedBufferList::NewWrappingBuffer(aStorageStart, aDataEnd, aStorageEnd)))) + : nsSlidingSubstring(new nsSlidingSharedBufferList(nsSlidingSharedBufferList::NewWrappingBuffer(aStorageStart, aDataEnd, aStorageEnd))) { // nothing else to do here } @@ -159,8 +272,8 @@ void nsSlidingString::AppendBuffer( PRUnichar* aStorageStart, PRUnichar* aDataEnd, PRUnichar* aStorageEnd ) { Buffer* new_buffer = new Buffer(aStorageStart, aDataEnd, aStorageStart, aStorageEnd); - Buffer* old_last_buffer = mBufferList.GetLastBuffer(); - mBufferList.LinkBuffer(old_last_buffer, new_buffer, 0); + Buffer* old_last_buffer = mBufferList->GetLastBuffer(); + mBufferList->LinkBuffer(old_last_buffer, new_buffer, 0); mLength += new_buffer->DataLength(); mEnd.PointAfter(new_buffer); @@ -171,10 +284,16 @@ nsSlidingString::DiscardPrefix( const nsReadingIterator<PRUnichar>& aIter ) { Position old_start(mStart); mStart = aIter; - mLength -= Distance(old_start, mStart); + mLength -= Position::Distance(old_start, mStart); - mStart.mBuffer->AcquireReference(); - old_start.mBuffer->ReleaseReference(); + mStart.mBuffer->AcquireNonOwningReference(); + old_start.mBuffer->ReleaseNonOwningReference(); - mBufferList.DiscardUnreferencedPrefix(old_start.mBuffer); + mBufferList->DiscardUnreferencedPrefix(old_start.mBuffer); + } + +const PRUnichar* +nsSlidingString::GetReadableFragment( nsReadableFragment<PRUnichar>& aFragment, nsFragmentRequest aRequest, PRUint32 aOffset ) const + { + return nsSlidingSubstring::GetReadableFragment(aFragment, aRequest, aOffset); }