diff --git a/htmlparser/src/CNavDTD.cpp b/htmlparser/src/CNavDTD.cpp index a20c8c59367..3400ef36e19 100644 --- a/htmlparser/src/CNavDTD.cpp +++ b/htmlparser/src/CNavDTD.cpp @@ -91,6 +91,115 @@ static char gWhitespaceTags[]={ 0}; +/************************************************************************ + CTagStack class implementation. + The reason we use this class is so that we can view the stack state + in the usual way via the debugger. + ************************************************************************/ + + +CTagStack::CTagStack(int aDefaultSize) { +#ifdef _dynstack + mSize=aDefaultSize; + mTags =new eHTMLTags[mSize]; + mBits =new PRBool[mSize]; +#else + mSize=eStackSize; +#endif + mCount=0; + nsCRT::zero(mTags,mSize*sizeof(eHTMLTag_html)); + nsCRT::zero(mBits,mSize*sizeof(PRBool)); +} + +/** + * Default constructor + * @update gess7/9/98 + * @param aDefaultsize tells the stack what size to start out. + * however, we'll autosize as needed. + */ +CTagStack::~CTagStack() { +#ifdef _dynstack + delete mTags; + delete mBits; + mTags=0; + mBits=0; +#endif + mSize=mCount=0; + } + +/** + * + * @update gess7/9/98 + * @param + * @return + */ +void CTagStack::Push(eHTMLTags aTag) { + + if(mCount>=mSize) { + +#ifdef _dynstack + eHTMLTags* tmp=new eHTMLTags[2*mSize]; + nsCRT::zero(tmp,2*mSize*sizeof(eHTMLTag_html)); + nsCRT::memcpy(tmp,mTags,mSize*sizeof(eHTMLTag_html)); + delete mTags; + mTags=tmp; + + PRBool* tmp2=new PRBool[2*mSize]; + nsCRT::zero(tmp2,2*mSize*sizeof(PRBool)); + nsCRT::memcpy(tmp2,mBits,mSize*sizeof(PRBool)); + delete mBits; + mBits=tmp2; + mSize*=2; +#endif + } + mTags[mCount++]=aTag; +} + +/** + * + * @update gess7/9/98 + * @param + * @return + */ +eHTMLTags CTagStack::Pop() { + eHTMLTags result=eHTMLTag_unknown; + if(mCount>0) { + result=mTags[--mCount]; + mTags[mCount]=eHTMLTag_unknown; + mBits[mCount]=PR_FALSE; + } + return result; +} + +/** + * + * @update gess7/9/98 + * @param + * @return + */ +eHTMLTags CTagStack::First() const { + if(mCount>0) + return mTags[0]; + return eHTMLTag_unknown; +} + +/** + * + * @update gess7/9/98 + * @param + * @return + */ +eHTMLTags CTagStack::Last() const { + if(mCount>0) + return mTags[mCount-1]; + return eHTMLTag_unknown; +} + + +/************************************************************************ + And now for the main class -- CNavDTD... + ************************************************************************/ + /** * This method gets called as part of our COM-like interfaces. * Its purpose is to create an interface to parser object @@ -124,6 +233,7 @@ nsresult CNavDTD::QueryInterface(const nsIID& aIID, void** aInstancePtr) return NS_OK; } + /** * This method is defined in nsIParser. It is used to * cause the COM-like construction of an nsParser. @@ -234,15 +344,13 @@ static CNavTokenDeallocator gTokenKiller; * @param * @return */ -CNavDTD::CNavDTD() : nsIDTD(), mTokenDeque(gTokenKiller) { +CNavDTD::CNavDTD() : nsIDTD(), mTokenDeque(gTokenKiller), + mContextStack(), mStyleStack() { NS_INIT_REFCNT(); mParser=0; - mFilename=0; mSink = nsnull; mDTDDebug=0; nsCRT::zero(mTokenHandlers,sizeof(mTokenHandlers)); - mContextStackPos=0; - mStyleStackPos=0; mHasOpenForm=PR_FALSE; mHasOpenMap=PR_FALSE; InitializeDefaultTokenHandlers(); @@ -257,8 +365,6 @@ CNavDTD::CNavDTD() : nsIDTD(), mTokenDeque(gTokenKiller) { */ CNavDTD::~CNavDTD(){ DeleteTokenHandlers(); - if (mFilename) - PL_strfree(mFilename); if (mDTDDebug) NS_RELEASE(mDTDDebug); @@ -281,6 +387,7 @@ void CNavDTD::SetDTDDebug(nsIDTDDebug * aDTDDebug) NS_ADDREF(mDTDDebug); } + /** * This method is called to determine if the given DTD can parse * a document in a given source-type. @@ -308,24 +415,16 @@ eAutoDetectResult CNavDTD::AutoDetectContentType(nsString& aBuffer,nsString& aTy return result; } - - /** * * @update gess5/18/98 * @param * @return */ -PRInt32 CNavDTD::WillBuildModel(const char* aFilename){ +PRInt32 CNavDTD::WillBuildModel(nsString& aFilename){ PRInt32 result=0; - if (mFilename) { - PL_strfree(mFilename); - mFilename=0; - } - if(aFilename) { - mFilename = PL_strdup(aFilename); - } + mFilename=aFilename; if(mSink) mSink->WillBuildModel(); @@ -342,7 +441,7 @@ PRInt32 CNavDTD::WillBuildModel(const char* aFilename){ PRInt32 CNavDTD::DidBuildModel(PRInt32 anErrorCode){ PRInt32 result=0; - if((kNoError==anErrorCode) && (mContextStackPos>0)) { + if((kNoError==anErrorCode) && (mContextStack.mCount>0)) { CloseContainersTo(0,eHTMLTag_unknown,PR_FALSE); } if(mSink) { @@ -375,7 +474,7 @@ PRInt32 CNavDTD::HandleToken(CToken* aToken){ if(theHandler) { result=(*theHandler)(theToken,this); if (mDTDDebug) - mDTDDebug->Verify(this, mParser, mContextStackPos, mContextStack, mFilename); + mDTDDebug->Verify(this, mParser, mContextStack.mCount, mContextStack.mTags, mFilename); } }//if @@ -420,13 +519,13 @@ PRInt32 CNavDTD::HandleDefaultStartToken(CToken* aToken,eHTMLTags aChildTag,nsIP } if(IsContainer(aChildTag)){ - if(PR_TRUE==(PRBool)mLeafBits[mContextStackPos-1]) { + if(PR_TRUE==mContextStack.mBits[mContextStack.mCount-1]) { CloseTransientStyles(aChildTag); } result=OpenContainer(aNode,PR_TRUE); } else { - if(PR_FALSE==(PRBool)mLeafBits[mContextStackPos-1]) { + if(PR_FALSE==mContextStack.mBits[mContextStack.mCount-1]) { OpenTransientStyles(aChildTag); } result=AddLeaf(aNode); @@ -576,16 +675,8 @@ PRInt32 CNavDTD::HandleEndToken(CToken* aToken) { // we have to handle explicit styles the way it does. That means // that we keep an internal style stack.When an EndToken occurs, // we should see if it is an explicit style tag. If so, we can - // close AND explicit style tag (goofy, huh?) + // close the explicit style tag (goofy, huh?) -/* - if(0!=strchr(gStyleTags,tokenTagType)){ - eHTMLTags topTag=GetTopNode(); - if(0!=strchr(gStyleTags,topTag)){ - tokenTagType=topTag; - } - } -*/ //now check to see if this token should be omitted... if(PR_TRUE==CanOmitEndTag(GetTopNode(),tokenTagType)) { @@ -622,7 +713,7 @@ PRInt32 CNavDTD::HandleEndToken(CToken* aToken) { // Empty the transient style stack (we just closed any extra // ones off so it's safe to do it now) because they don't carry // forward across table cell boundaries. - mStyleStackPos = 0; + mStyleStack.mCount=0; break; default: @@ -1148,8 +1239,8 @@ PRBool CNavDTD::CanContain(PRInt32 aParent,PRInt32 aChild) { break; //singletons can't contain anything... case eHTMLTag_li: - if ((eHTMLTag_li == aChild) || - (eHTMLTag_ul == aChild) || // XXX this is temporary!!! + if ((eHTMLTag_li == aChild) || //XXX this is temporary!!! + (eHTMLTag_ul == aChild) || (eHTMLTag_ol == aChild) || (eHTMLTag_menu == aChild) || (eHTMLTag_dir == aChild)) { @@ -1620,29 +1711,6 @@ PRBool CNavDTD::BackwardPropagate(nsString& aVector,eHTMLTags aParentTag,eHTMLTa return PRBool(aParentTag==theParentTag); } -/** - * - * @update gess6/4/98 - * @param aTag is the id of the html container being opened - * @return 0 if all is well. - */ -PRInt32 CNavDTD::DidOpenContainer(eHTMLTags aTag,PRBool /*anExplicitOpen*/){ - PRInt32 result=0; - return result; -} - -/** - * - * @update gess6/4/98 - * @param - * @return - */ -PRInt32 CNavDTD::DidCloseContainer(eHTMLTags aTag,PRBool/*anExplicitClosure*/){ - PRInt32 result=0; - return result; -} - - /** * This method allows the caller to determine if a form * element is currently open. @@ -1672,9 +1740,7 @@ PRBool CNavDTD::HasOpenContainer(eHTMLTags aContainer) const { * @return tag id of topmost node in contextstack */ eHTMLTags CNavDTD::GetTopNode() const { - if(mContextStackPos) - return (eHTMLTags)(int)mContextStack[mContextStackPos-1]; - return eHTMLTag_unknown; + return mContextStack.Last(); } @@ -1688,8 +1754,8 @@ eHTMLTags CNavDTD::GetTopNode() const { */ PRInt32 CNavDTD::GetTopmostIndexOf(eHTMLTags aTag) const { int i=0; - for(i=mContextStackPos-1;i>=0;i--){ - if((eHTMLTags)(int)mContextStack[i]==aTag) + for(i=mContextStack.mCount-1;i>=0;i--){ + if(mContextStack.mTags[i]==aTag) return i; } return kNotFound; @@ -1720,8 +1786,8 @@ PRInt32 CNavDTD::OpenTransientStyles(eHTMLTags aTag){ eHTMLTags parentTag=GetTopNode(); if(CanContainStyles(parentTag)) { - for(pos=0;pos0) && (mLeafBits[mContextStackPos-1])) { + if((mStyleStack.mCount>0) && (mContextStack.mBits[mContextStack.mCount-1])) { if(0==strchr(gWhitespaceTags,aTag)){ - result=CloseContainersTo((eHTMLTags)(int)mStyleStack[0],PR_FALSE); - mLeafBits.ReplaceElementAt((void*)PR_FALSE,mContextStackPos-1); + result=CloseContainersTo(mStyleStack.mTags[0],PR_FALSE); + mContextStack.mBits[mContextStack.mCount-1]=PR_FALSE; }//if }//if @@ -1782,10 +1848,10 @@ PRInt32 CNavDTD::CloseTransientStyles(eHTMLTags aTag){ * @return TRUE if ok, FALSE if error */ PRInt32 CNavDTD::OpenHTML(const nsIParserNode& aNode){ - NS_PRECONDITION(mContextStackPos >= 0, kInvalidTagStackPos); + NS_PRECONDITION(mContextStack.mCount >= 0, kInvalidTagStackPos); PRInt32 result=mSink->OpenHTML(aNode); - mContextStack.ReplaceElementAt((void*)aNode.GetNodeType(),mContextStackPos++); + mContextStack.Push((eHTMLTags)aNode.GetNodeType()); return result; } @@ -1799,9 +1865,9 @@ PRInt32 CNavDTD::OpenHTML(const nsIParserNode& aNode){ * @return TRUE if ok, FALSE if error */ PRInt32 CNavDTD::CloseHTML(const nsIParserNode& aNode){ - NS_PRECONDITION(mContextStackPos > 0, kInvalidTagStackPos); + NS_PRECONDITION(mContextStack.mCount > 0, kInvalidTagStackPos); PRInt32 result=mSink->CloseHTML(aNode); - mContextStack.ReplaceElementAt((void*)eHTMLTag_unknown,--mContextStackPos); + mContextStack.Pop(); return result; } @@ -1815,7 +1881,7 @@ PRInt32 CNavDTD::CloseHTML(const nsIParserNode& aNode){ * @return TRUE if ok, FALSE if error */ PRInt32 CNavDTD::OpenHead(const nsIParserNode& aNode){ - mContextStack.ReplaceElementAt((void*)eHTMLTag_head,++mContextStackPos); + mContextStack.Push(eHTMLTag_head); PRInt32 result=mSink->OpenHead(aNode); return result; } @@ -1830,7 +1896,7 @@ PRInt32 CNavDTD::OpenHead(const nsIParserNode& aNode){ */ PRInt32 CNavDTD::CloseHead(const nsIParserNode& aNode){ PRInt32 result=mSink->CloseHead(aNode); - mContextStack.ReplaceElementAt((void*)eHTMLTag_unknown,--mContextStackPos); + mContextStack.Pop(); return result; } @@ -1843,7 +1909,7 @@ PRInt32 CNavDTD::CloseHead(const nsIParserNode& aNode){ * @return TRUE if ok, FALSE if error */ PRInt32 CNavDTD::OpenBody(const nsIParserNode& aNode){ - NS_PRECONDITION(mContextStackPos >= 0, kInvalidTagStackPos); + NS_PRECONDITION(mContextStack.mCount >= 0, kInvalidTagStackPos); PRInt32 result=kNoError; eHTMLTags topTag=GetTopNode(); @@ -1875,7 +1941,7 @@ PRInt32 CNavDTD::OpenBody(const nsIParserNode& aNode){ if(kNoError==result) { result=mSink->OpenBody(aNode); - mContextStack.ReplaceElementAt((void*)aNode.GetNodeType(),mContextStackPos++); + mContextStack.Push((eHTMLTags)aNode.GetNodeType()); } return result; } @@ -1889,9 +1955,9 @@ PRInt32 CNavDTD::OpenBody(const nsIParserNode& aNode){ * @return TRUE if ok, FALSE if error */ PRInt32 CNavDTD::CloseBody(const nsIParserNode& aNode){ - NS_PRECONDITION(mContextStackPos >= 0, kInvalidTagStackPos); + NS_PRECONDITION(mContextStack.mCount >= 0, kInvalidTagStackPos); PRInt32 result=mSink->CloseBody(aNode); - mContextStack.ReplaceElementAt((void*)eHTMLTag_unknown,--mContextStackPos); + mContextStack.Pop(); return result; } @@ -1980,9 +2046,9 @@ PRInt32 CNavDTD::CloseMap(const nsIParserNode& aNode){ * @return TRUE if ok, FALSE if error */ PRInt32 CNavDTD::OpenFrameset(const nsIParserNode& aNode){ - NS_PRECONDITION(mContextStackPos >= 0, kInvalidTagStackPos); + NS_PRECONDITION(mContextStack.mCount >= 0, kInvalidTagStackPos); PRInt32 result=mSink->OpenFrameset(aNode); - mContextStack.ReplaceElementAt((void*)aNode.GetNodeType(),mContextStackPos++); + mContextStack.Push((eHTMLTags)aNode.GetNodeType()); return result; } @@ -1995,9 +2061,9 @@ PRInt32 CNavDTD::OpenFrameset(const nsIParserNode& aNode){ * @return TRUE if ok, FALSE if error */ PRInt32 CNavDTD::CloseFrameset(const nsIParserNode& aNode){ - NS_PRECONDITION(mContextStackPos > 0, kInvalidTagStackPos); + NS_PRECONDITION(mContextStack.mCount > 0, kInvalidTagStackPos); PRInt32 result=mSink->CloseFrameset(aNode); - mContextStack.ReplaceElementAt((void*)eHTMLTag_unknown,--mContextStackPos); + mContextStack.Pop(); return result; } @@ -2011,7 +2077,7 @@ PRInt32 CNavDTD::CloseFrameset(const nsIParserNode& aNode){ * @return TRUE if ok, FALSE if error */ PRInt32 CNavDTD::OpenContainer(const nsIParserNode& aNode,PRBool aUpdateStyleStack){ - NS_PRECONDITION(mContextStackPos > 0, kInvalidTagStackPos); + NS_PRECONDITION(mContextStack.mCount > 0, kInvalidTagStackPos); PRInt32 result=kNoError; eHTMLTags nodeType=(eHTMLTags)aNode.GetNodeType(); @@ -2037,7 +2103,7 @@ PRInt32 CNavDTD::OpenContainer(const nsIParserNode& aNode,PRBool aUpdateStyleSta default: result=mSink->OpenContainer(aNode); - mContextStack.ReplaceElementAt((void*)nodeType,mContextStackPos++); + mContextStack.Push((eHTMLTags)aNode.GetNodeType()); break; } @@ -2057,7 +2123,7 @@ PRInt32 CNavDTD::OpenContainer(const nsIParserNode& aNode,PRBool aUpdateStyleSta * @return TRUE if ok, FALSE if error */ PRInt32 CNavDTD::CloseContainer(const nsIParserNode& aNode,eHTMLTags aTag,PRBool aUpdateStyles){ - NS_PRECONDITION(mContextStackPos > 0, kInvalidTagStackPos); + NS_PRECONDITION(mContextStack.mCount > 0, kInvalidTagStackPos); PRInt32 result=kNoError; //was false eHTMLTags nodeType=(eHTMLTags)aNode.GetNodeType(); @@ -2085,11 +2151,11 @@ PRInt32 CNavDTD::CloseContainer(const nsIParserNode& aNode,eHTMLTags aTag,PRBool case eHTMLTag_title: default: result=mSink->CloseContainer(aNode); - mContextStack.ReplaceElementAt((void*)eHTMLTag_unknown,--mContextStackPos); + mContextStack.Pop(); break; } - mLeafBits.ReplaceElementAt((void*)PR_FALSE, mContextStackPos); + mContextStack.mBits[mContextStack.mCount]=PR_FALSE; if((kNoError==result) && (PR_TRUE==aUpdateStyles)){ UpdateStyleStackForCloseTag(nodeType,aTag); } @@ -2106,15 +2172,15 @@ PRInt32 CNavDTD::CloseContainer(const nsIParserNode& aNode,eHTMLTags aTag,PRBool * @return TRUE if ok, FALSE if error */ PRInt32 CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTag,PRBool aUpdateStyles){ - NS_PRECONDITION(mContextStackPos > 0, kInvalidTagStackPos); + NS_PRECONDITION(mContextStack.mCount > 0, kInvalidTagStackPos); PRInt32 result=kNoError; CEndToken aToken(gEmpty); nsCParserNode theNode(&aToken); - if((anIndex=0)) { - while(mContextStackPos>anIndex) { - eHTMLTags theTag=(eHTMLTags)(int)mContextStack[mContextStackPos-1]; + if((anIndex=0)) { + while(mContextStack.mCount>anIndex) { + eHTMLTags theTag=mContextStack.Last(); aToken.SetTypeID(theTag); result=CloseContainer(theNode,aTag,aUpdateStyles); } @@ -2131,7 +2197,7 @@ PRInt32 CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTag,PRBool aUpdate * @return TRUE if ok, FALSE if error */ PRInt32 CNavDTD::CloseContainersTo(eHTMLTags aTag,PRBool aUpdateStyles){ - NS_PRECONDITION(mContextStackPos > 0, kInvalidTagStackPos); + NS_PRECONDITION(mContextStack.mCount > 0, kInvalidTagStackPos); PRInt32 pos=GetTopmostIndexOf(aTag); @@ -2172,10 +2238,10 @@ PRInt32 CNavDTD::CloseContainersTo(eHTMLTags aTag,PRBool aUpdateStyles){ * @return TRUE if ok, FALSE if error */ PRInt32 CNavDTD::CloseTopmostContainer(){ - NS_PRECONDITION(mContextStackPos > 0, kInvalidTagStackPos); + NS_PRECONDITION(mContextStack.mCount > 0, kInvalidTagStackPos); CEndToken aToken(gEmpty); - eHTMLTags theTag=(eHTMLTags)(int)mContextStack[mContextStackPos-1]; + eHTMLTags theTag=mContextStack.Last(); aToken.SetTypeID(theTag); nsCParserNode theNode(&aToken); return CloseContainer(theNode,theTag,PR_TRUE); @@ -2217,7 +2283,7 @@ PRInt32 CNavDTD::CreateContextStackFor(eHTMLTags aChildTag){ //add code here to build up context stack based on forward propagated context vector... pos=0; cnt=theVector.Length()-1; - if(mContextStack[mContextStackPos-1]==(void*)theVector[cnt]) + if(mContextStack.Last()==(eHTMLTags)theVector[cnt]) result=kNoError; else result=kContextMismatch; } @@ -2236,8 +2302,8 @@ PRInt32 CNavDTD::CreateContextStackFor(eHTMLTags aChildTag){ pos=0; cnt=theVector.Length(); result=kNoError; - while(pos0) { + if(mStyleStack.mCount>0) { switch (aTag) { case eHTMLTag_a: @@ -2369,7 +2435,7 @@ PRInt32 CNavDTD::UpdateStyleStackForCloseTag(eHTMLTags aTag,eHTMLTags anActualTa case eHTMLTag_u: case eHTMLTag_var: if(aTag==anActualTag) - mStyleStack.ReplaceElementAt((void*)eHTMLTag_unknown,--mStyleStackPos); + mStyleStack.Pop(); break; case eHTMLTag_h1: case eHTMLTag_h2: @@ -2716,8 +2782,8 @@ PRInt32 CNavDTD::ConsumeToken(CToken*& aToken){ CScanner* theScanner=mParser->GetScanner(); if(kNoError==result){ - PRUnichar aChar; - result=theScanner->GetChar(aChar); + PRUnichar theChar; + result=theScanner->GetChar(theChar); switch(result) { case kEOF: break; @@ -2728,25 +2794,25 @@ PRInt32 CNavDTD::ConsumeToken(CToken*& aToken){ case kNoError: default: - switch(aChar) { + switch(theChar) { case kLessThan: - return ConsumeTag(aChar,*theScanner,aToken); + return ConsumeTag(theChar,*theScanner,aToken); case kAmpersand: - return ConsumeEntity(aChar,*theScanner,aToken); + return ConsumeEntity(theChar,*theScanner,aToken); case kCR: case kLF: - return ConsumeNewline(aChar,*theScanner,aToken); + return ConsumeNewline(theChar,*theScanner,aToken); case kNotFound: break; default: - if(!nsString::IsSpace(aChar)) { - nsAutoString temp(aChar); + if(!nsString::IsSpace(theChar)) { + nsAutoString temp(theChar); return ConsumeText(temp,*theScanner,aToken); } - return ConsumeWhitespace(aChar,*theScanner,aToken); + return ConsumeWhitespace(theChar,*theScanner,aToken); } //switch break; } //switch diff --git a/htmlparser/src/CNavDTD.h b/htmlparser/src/CNavDTD.h index 2ea700f9ec7..063874781d3 100644 --- a/htmlparser/src/CNavDTD.h +++ b/htmlparser/src/CNavDTD.h @@ -45,6 +45,54 @@ class nsIParserNode; class CITokenHandler; class nsParser; + + +/*************************************************************** + First define a helper class called CTagStack. + + Simple, we've built ourselves a little data structure that + serves as a stack for htmltags (and associated bits). + What's special is that if you #define _dynstack 1, the stack + size can grow dynamically (like you'ld want in a release build.) + If you don't #define _dynstack 1, then the stack is a fixed size, + equal to the eStackSize enum. This makes debugging easier, because + you can see the htmltags on the stack if its not dynamic. + ***************************************************************/ + +//#define _dynstack 1 +class CTagStack { + enum {eStackSize=200}; + +public: + + CTagStack(int aDefaultSize=50); + ~CTagStack(); + void Push(eHTMLTags aTag); + eHTMLTags Pop(); + eHTMLTags First() const; + eHTMLTags Last() const; + + int mSize; + int mCount; + +#ifdef _dynstack + eHTMLTags* mTags; + PRBool* mBits; +#else + eHTMLTags mTags[200]; + PRBool mBits[200]; +#endif +}; + +/*************************************************************** + Now the main event: CNavDTD. + + This not so simple class performs all the duties of token + construction and model building. It works in conjunction with + an nsParser. + ***************************************************************/ + + class CNavDTD : public nsIDTD { public: @@ -103,7 +151,7 @@ class CNavDTD : public nsIDTD { * @param * @return */ - virtual PRInt32 WillBuildModel(const char* aFilename=0); + virtual PRInt32 WillBuildModel(nsString& aFilename); /** * @@ -251,14 +299,6 @@ class CNavDTD : public nsIDTD { */ virtual PRBool BackwardPropagate(nsString& aVector,eHTMLTags aParentTag,eHTMLTags aChildTag) const; - /** - * - * @update gess6/4/98 - * @param - * @return - */ - virtual PRInt32 DidOpenContainer(eHTMLTags aTag,PRBool anExplicitOpen); - /** * Ask parser if a given container is open ANYWHERE on stack * @update gess5/11/98 @@ -283,129 +323,36 @@ class CNavDTD : public nsIDTD { */ virtual PRInt32 GetTopmostIndexOf(eHTMLTags aTag) const; - /** - * - * @update gess6/4/98 - * @param - * @return - */ - virtual PRInt32 DidCloseContainer(eHTMLTags aTag,PRBool anExplicitClosure); /** - * This method gets called when a start token has been consumed and needs - * to be handled (possibly added to content model via sink). + * The following set of methods are used to partially construct + * the content model (via the sink) according to the type of token. * @update gess5/11/98 * @param aToken is the start token to be handled * @return TRUE if the token was handled. */ PRInt32 HandleStartToken(CToken* aToken); - - /** - * This method gets called when a start token has been consumed, and - * we want to use default start token handling behavior. - * This method gets called automatically by handleStartToken. - * - * @update gess5/11/98 - * @param aToken is the start token to be handled - * @param aChildTag is the tag-type of given token - * @param aNode is a node be updated with info from given token - * @return TRUE if the token was handled. - */ PRInt32 HandleDefaultStartToken(CToken* aToken,eHTMLTags aChildTag,nsIParserNode& aNode); - - /** - * This method gets called when an end token has been consumed and needs - * to be handled (possibly added to content model via sink). - * @update gess5/11/98 - * @param aToken is the end token to be handled - * @return TRUE if the token was handled. - */ PRInt32 HandleEndToken(CToken* aToken); - - /** - * This method gets called when an entity token has been consumed and needs - * to be handled (possibly added to content model via sink). - * @update gess5/11/98 - * @param aToken is the entity token to be handled - * @return TRUE if the token was handled. - */ PRInt32 HandleEntityToken(CToken* aToken); - - /** - * This method gets called when a comment token has been consumed and needs - * to be handled (possibly added to content model via sink). - * @update gess5/11/98 - * @param aToken is the comment token to be handled - * @return TRUE if the token was handled. - */ PRInt32 HandleCommentToken(CToken* aToken); - - /** - * This method gets called when a skipped-content token has been consumed and needs - * to be handled (possibly added to content model via sink). - * @update gess5/11/98 - * @param aToken is the skipped-content token to be handled - * @return TRUE if the token was handled. - */ PRInt32 HandleSkippedContentToken(CToken* aToken); - - /** - * This method gets called when an attribute token has been consumed and needs - * to be handled (possibly added to content model via sink). - * @update gess5/11/98 - * @param aToken is the attribute token to be handled - * @return TRUE if the token was handled. - */ PRInt32 HandleAttributeToken(CToken* aToken); - - /** - * This method gets called when a script token has been consumed and needs - * to be handled (possibly added to content model via sink). - * @update gess5/11/98 - * @param aToken is the script token to be handled - * @return TRUE if the token was handled. - */ PRInt32 HandleScriptToken(CToken* aToken); - - /** - * This method gets called when a style token has been consumed and needs - * to be handled (possibly added to content model via sink). - * @update gess5/11/98 - * @param aToken is the style token to be handled - * @return TRUE if the token was handled. - */ PRInt32 HandleStyleToken(CToken* aToken); - protected: /** - * Causes token handlers to be registered for this parser. - * DO NOT CALL THIS! IT'S DEPRECATED! - * @update gess5/11/98 - */ - void InitializeDefaultTokenHandlers(); - - - /** - * DEPRECATED + * The following methods are use to create and manage + * the dynamic set of token handlers. * @update gess5/11/98 */ + void InitializeDefaultTokenHandlers(); CITokenHandler* GetTokenHandler(eHTMLTokenTypes aType) const; - - /** - * DEPRECATED - * @update gess5/11/98 - */ CITokenHandler* AddTokenHandler(CITokenHandler* aHandler); - - /** - * DEPRECATED - * @update gess5/11/98 - */ - void DeleteTokenHandlers(void); - + void DeleteTokenHandlers(void); //************************************************* @@ -414,145 +361,43 @@ protected: //************************************************* /** - * This cover method opens the given node as a HTML item in - * content sink. + * The next set of method open given HTML element. + * * @update gess5/11/98 * @param HTML (node) to be opened in content sink. * @return TRUE if all went well. */ PRInt32 OpenHTML(const nsIParserNode& aNode); - - /** - * - * @update gess5/11/98 - * @param - * @return - */ - PRInt32 CloseHTML(const nsIParserNode& aNode); - - /** - * This cover method opens the given node as a head item in - * content sink. - * @update gess5/11/98 - * @param HEAD (node) to be opened in content sink. - * @return TRUE if all went well. - */ PRInt32 OpenHead(const nsIParserNode& aNode); - - /** - * This cover method causes the content-sink head to be closed - * @update gess5/11/98 - * @param aNode is the node to be closed in sink (usually ignored) - * @return TRUE if all went well. - */ - PRInt32 CloseHead(const nsIParserNode& aNode); - - /** - * This cover method opens the given node as a body item in - * content sink. - * @update gess5/11/98 - * @param BODY (node) to be opened in content sink. - * @return TRUE if all went well. - */ PRInt32 OpenBody(const nsIParserNode& aNode); - - /** - * This cover method causes the content-sink body to be closed - * @update gess5/11/98 - * @param aNode is the body node to be closed in sink (usually ignored) - * @return TRUE if all went well. - */ - PRInt32 CloseBody(const nsIParserNode& aNode); - - /** - * This cover method opens the given node as a form item in - * content sink. - * @update gess5/11/98 - * @param FORM (node) to be opened in content sink. - * @return TRUE if all went well. - */ PRInt32 OpenForm(const nsIParserNode& aNode); - - /** - * This cover method causes the content-sink form to be closed - * @update gess5/11/98 - * @param aNode is the form node to be closed in sink (usually ignored) - * @return TRUE if all went well. - */ - PRInt32 CloseForm(const nsIParserNode& aNode); - - /** - * This cover method opens the given node as a form item in - * content sink. - * @update gess5/11/98 - * @param FORM (node) to be opened in content sink. - * @return TRUE if all went well. - */ PRInt32 OpenMap(const nsIParserNode& aNode); - - /** - * This cover method causes the content-sink form to be closed - * @update gess5/11/98 - * @param aNode is the form node to be closed in sink (usually ignored) - * @return TRUE if all went well. - */ - PRInt32 CloseMap(const nsIParserNode& aNode); - - /** - * This cover method opens the given node as a frameset item in - * content sink. - * @update gess5/11/98 - * @param FRAMESET (node) to be opened in content sink. - * @return TRUE if all went well. - */ PRInt32 OpenFrameset(const nsIParserNode& aNode); - - /** - * This cover method causes the content-sink frameset to be closed - * @update gess5/11/98 - * @param aNode is the frameeset node to be closed in sink (usually ignored) - * @return TRUE if all went well. - */ - PRInt32 CloseFrameset(const nsIParserNode& aNode); - - /** - * This cover method opens the given node as a generic container in - * content sink. - * @update gess5/11/98 - * @param generic container (node) to be opened in content sink. - * @return TRUE if all went well. - */ PRInt32 OpenContainer(const nsIParserNode& aNode,PRBool aUpdateStyleStack); /** - * This cover method causes a generic containre in the content-sink to be closed + * The next set of methods close the given HTML element. + * * @update gess5/11/98 - * @param aNode is the node to be closed in sink (usually ignored) + * @param HTML (node) to be opened in content sink. * @return TRUE if all went well. */ + PRInt32 CloseHTML(const nsIParserNode& aNode); + PRInt32 CloseHead(const nsIParserNode& aNode); + PRInt32 CloseBody(const nsIParserNode& aNode); + PRInt32 CloseForm(const nsIParserNode& aNode); + PRInt32 CloseMap(const nsIParserNode& aNode); + PRInt32 CloseFrameset(const nsIParserNode& aNode); PRInt32 CloseContainer(const nsIParserNode& aNode,eHTMLTags anActualTag,PRBool aUpdateStyles); /** - * This cover method causes the topmost container to be closed in sink + * The special purpose methods automatically close + * one or more open containers. * @update gess5/11/98 * @return TRUE if all went well. */ PRInt32 CloseTopmostContainer(); - - /** - * Cause all containers down to topmost given tag to be closed - * @update gess5/11/98 - * @param aTag is the tag at which auto-closure should stop (inclusive) - * @return TRUE if all went well -- otherwise FALSE - */ PRInt32 CloseContainersTo(eHTMLTags aTag,PRBool aUpdateStyles); - - /** - * Cause all containers down to given position to be closed - * @update gess5/11/98 - * @param anIndex is the stack pos at which auto-closure should stop (inclusive) - * @return TRUE if all went well -- otherwise FALSE - */ PRInt32 CloseContainersTo(PRInt32 anIndex,eHTMLTags aTag,PRBool aUpdateStyles); /** @@ -603,81 +448,22 @@ protected: CToken* CreateTokenOfType(eHTMLTokenTypes aType); /** - * Retrieve the next TAG from the given scanner. + * The following methods consume a particular type + * of HTML token. + * * @update gess 5/11/98 * @param aScanner is the input source * @param aToken is the next token (or null) * @return error code */ PRInt32 ConsumeTag(PRUnichar aChar,CScanner& aScanner,CToken*& aToken); - - /** - * Retrieve next START tag from given scanner. - * @update gess 5/11/98 - * @param aScanner is the input source - * @param aToken is the next token (or null) - * @return error code - */ PRInt32 ConsumeStartTag(PRUnichar aChar,CScanner& aScanner,CToken*& aToken); - - /** - * Retrieve collection of HTML/XML attributes from given scanner - * @update gess 5/11/98 - * @param aScanner is the input source - * @param aToken is the next token (or null) - * @return error code - */ PRInt32 ConsumeAttributes(PRUnichar aChar,CScanner& aScanner,CStartToken* aToken); - - /** - * Retrieve a sequence of text from given scanner. - * @update gess 5/11/98 - * @param aString will contain retrieved text. - * @param aScanner is the input source - * @param aToken is the next token (or null) - * @return error code - */ - PRInt32 ConsumeText(const nsString& aString,CScanner& aScanner,CToken*& aToken); - - /** - * Retrieve an entity from given scanner - * @update gess 5/11/98 - * @param aChar last char read from scanner - * @param aScanner is the input source - * @param aToken is the next token (or null) - * @return error code - */ PRInt32 ConsumeEntity(PRUnichar aChar,CScanner& aScanner,CToken*& aToken); - - /** - * Retrieve a whitespace sequence from the given scanner - * @update gess 5/11/98 - * @param aChar last char read from scanner - * @param aScanner is the input source - * @param aToken is the next token (or null) - * @return error code - */ PRInt32 ConsumeWhitespace(PRUnichar aChar,CScanner& aScanner,CToken*& aToken); - - /** - * Retrieve a comment from the given scanner - * @update gess 5/11/98 - * @param aChar last char read from scanner - * @param aScanner is the input source - * @param aToken is the next token (or null) - * @return error code - */ PRInt32 ConsumeComment(PRUnichar aChar,CScanner& aScanner,CToken*& aToken); - - /** - * Retrieve newlines from given scanner - * @update gess 5/11/98 - * @param aChar last char read from scanner - * @param aScanner is the input source - * @param aToken is the next token (or null) - * @return error code - */ PRInt32 ConsumeNewline(PRUnichar aChar,CScanner& aScanner,CToken*& aToken); + PRInt32 ConsumeText(const nsString& aString,CScanner& aScanner,CToken*& aToken); /** * Causes content to be skipped up to sequence contained in aString. @@ -700,16 +486,13 @@ protected: CITokenHandler* mTokenHandlers[eToken_last]; - nsVoidArray mLeafBits; - nsVoidArray mContextStack; - PRInt32 mContextStackPos; - nsVoidArray mStyleStack; - PRInt32 mStyleStackPos; + CTagStack mContextStack; + CTagStack mStyleStack; PRBool mHasOpenForm; PRBool mHasOpenMap; nsDeque mTokenDeque; - char* mFilename; + nsString mFilename; nsIDTDDebug* mDTDDebug; }; diff --git a/htmlparser/src/COtherDTD.cpp b/htmlparser/src/COtherDTD.cpp index 886dc88c047..a3b2b0cd572 100644 --- a/htmlparser/src/COtherDTD.cpp +++ b/htmlparser/src/COtherDTD.cpp @@ -178,7 +178,7 @@ eAutoDetectResult COtherDTD::AutoDetectContentType(nsString& aBuffer,nsString& a * @param * @return */ -PRInt32 COtherDTD::WillBuildModel(const char* aFilename) { +PRInt32 COtherDTD::WillBuildModel(nsString& aFilename) { return CNavDTD::WillBuildModel(aFilename); } @@ -464,25 +464,6 @@ PRBool COtherDTD::BackwardPropagate(nsString& aVector,eHTMLTags aParentTag,eHTML return CNavDTD::BackwardPropagate(aVector,aParentTag,aChildTag); } -/** - * - * @update gess6/4/98 - * @param aTag is the id of the html container being opened - * @return 0 if all is well. - */ -PRInt32 COtherDTD::DidOpenContainer(eHTMLTags aTag,PRBool anExplicitOpen){ - return CNavDTD::DidOpenContainer(aTag,anExplicitOpen); -} - -/** - * - * @update gess6/4/98 - * @param - * @return - */ -PRInt32 COtherDTD::DidCloseContainer(eHTMLTags aTag,PRBool anExplicitClosure){ - return CNavDTD::DidOpenContainer(aTag,anExplicitClosure); -} /********************************************* Here comes code that handles the interface diff --git a/htmlparser/src/COtherDTD.h b/htmlparser/src/COtherDTD.h index 10813045aba..488b2f26886 100644 --- a/htmlparser/src/COtherDTD.h +++ b/htmlparser/src/COtherDTD.h @@ -87,7 +87,7 @@ class COtherDTD : public CNavDTD { * @param * @return */ - virtual PRInt32 WillBuildModel(const char* aFilename=0); + virtual PRInt32 WillBuildModel(nsString& aString); /** * @@ -218,22 +218,6 @@ class COtherDTD : public CNavDTD { */ virtual PRBool BackwardPropagate(nsString& aVector,eHTMLTags aParentTag,eHTMLTags aChildTag) const; - /** - * - * @update gess6/4/98 - * @param - * @return - */ - virtual PRInt32 DidOpenContainer(eHTMLTags aTag,PRBool anExplicitOpen); - - /** - * - * @update gess6/4/98 - * @param - * @return - */ - virtual PRInt32 DidCloseContainer(eHTMLTags aTag,PRBool anExplicitClosure); - /** * This method gets called when a start token has been consumed and needs * to be handled (possibly added to content model via sink). diff --git a/htmlparser/src/CParserContext.cpp b/htmlparser/src/CParserContext.cpp new file mode 100644 index 00000000000..fae66a3d063 --- /dev/null +++ b/htmlparser/src/CParserContext.cpp @@ -0,0 +1,85 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +/** + * MODULE NOTES: + * @update gess 4/1/98 + * + */ + + +#include "CParserContext.h" +#include "nsToken.h" + + +class CTokenDeallocator: public nsDequeFunctor{ +public: + virtual void* operator()(void* anObject) { + CToken* aToken = (CToken*)anObject; + delete aToken; + return 0; + } +}; + +CTokenDeallocator gTokenDeallocator; + + +CParserContext::CParserContext(CScanner* aScanner, + CParserContext* aPreviousContext, + nsIStreamObserver* aListener) : + mTokenDeque(gTokenDeallocator), + mSourceType() +{ + mScanner=aScanner; + mPrevContext=aPreviousContext; + mListener=aListener; + NS_IF_ADDREF(mListener); + mMajorIteration=mMinorIteration=-1; + mParseMode=eParseMode_unknown; + mAutoDetectStatus=eUnknownDetect; + mTransferBuffer=new char[eTransferBufferSize+1]; + mCurrentPos=0; + mMarkPos=0; + mDTD=0; +} + + +/** + * Destructor for parser context + * NOTE: DO NOT destroy the dtd here. + * @update gess7/11/98 + */ +CParserContext::~CParserContext(){ + + if(mCurrentPos) + delete mCurrentPos; + if(mMarkPos) + delete mMarkPos; + + if(mScanner) + delete mScanner; + + if(mTransferBuffer) + delete [] mTransferBuffer; + + //Remember that it's ok to simply + //ignore the DTD and the prevcontext. + +} + + diff --git a/htmlparser/src/CParserContext.h b/htmlparser/src/CParserContext.h new file mode 100644 index 00000000000..41da84f49f9 --- /dev/null +++ b/htmlparser/src/CParserContext.h @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +/** + * MODULE NOTES: + * @update gess 4/1/98 + * + */ + +#ifndef __CParserContext +#define __CParserContext + +#include "nsIParser.h" +#include "nsDeque.h" +#include "nsParserTypes.h" +#include "nsIURL.h" +#include "nsIDTD.h" +#include "nsScanner.h" +#include "nsIStreamListener.h" + + +/** + * Note that the parser is given FULL access to all + * data in a parsercontext. Hey, that what it's for! + */ + +class CParserContext { + +public: + + enum {eTransferBufferSize=4096}; + + CParserContext( CScanner* aScanner, + CParserContext* aPreviousContext=0, + nsIStreamObserver* aListener=0); + + + ~CParserContext(); + + + PRInt32 mMajorIteration; + PRInt32 mMinorIteration; + + nsString mSourceType; + eAutoDetectResult mAutoDetectStatus; + + nsDequeIterator* mCurrentPos; + nsDequeIterator* mMarkPos; + nsDeque mTokenDeque; + CScanner* mScanner; + nsIDTD* mDTD; + + eParseMode mParseMode; + char* mTransferBuffer; + nsIStreamObserver* mListener; + + CParserContext* mPrevContext; + +}; + + + +#endif + + diff --git a/htmlparser/src/CRtfDTD.cpp b/htmlparser/src/CRtfDTD.cpp index 51add7383a1..8bc844274e8 100644 --- a/htmlparser/src/CRtfDTD.cpp +++ b/htmlparser/src/CRtfDTD.cpp @@ -251,7 +251,7 @@ eAutoDetectResult CRtfDTD::AutoDetectContentType(nsString& aBuffer,nsString& aTy * @param * @return */ -PRInt32 CRtfDTD::WillBuildModel(const char* aFilename){ +PRInt32 CRtfDTD::WillBuildModel(nsString& aFilename){ PRInt32 result=0; return result; } diff --git a/htmlparser/src/CRtfDTD.h b/htmlparser/src/CRtfDTD.h index dff562561a7..4f40b2f2eba 100644 --- a/htmlparser/src/CRtfDTD.h +++ b/htmlparser/src/CRtfDTD.h @@ -190,7 +190,7 @@ class CRtfDTD : public nsIDTD { * @param * @return */ - virtual PRInt32 WillBuildModel(const char* aFilename=0); + virtual PRInt32 WillBuildModel(nsString& aFilename); /** * diff --git a/htmlparser/src/Makefile b/htmlparser/src/Makefile index 8a09a69ba9d..616e7f6f6b1 100644 --- a/htmlparser/src/Makefile +++ b/htmlparser/src/Makefile @@ -34,6 +34,7 @@ CPPSRCS = \ nsValidDTD.cpp \ nsWellFormedDTD.cpp \ nsParser.cpp \ + CParserContext.cpp \ nsHTMLTokens.cpp \ nsHTMLTags.cpp \ prstrm.cpp \ diff --git a/htmlparser/src/makefile.win b/htmlparser/src/makefile.win index 68b1598facb..0b786802cb6 100644 --- a/htmlparser/src/makefile.win +++ b/htmlparser/src/makefile.win @@ -34,6 +34,7 @@ CPPSRCS= \ nsHTMLTags.obj \ nsHTMLTokens.obj \ nsParser.obj \ + CParserContext.obj \ nsParserNode.obj \ nsScanner.obj \ nsToken.obj \ @@ -53,6 +54,7 @@ CPP_OBJS= \ .\$(OBJDIR)\nsHTMLTags.obj \ .\$(OBJDIR)\nsHTMLTokens.obj \ .\$(OBJDIR)\nsParser.obj \ + .\$(OBJDIR)\CParserContext.obj \ .\$(OBJDIR)\nsParserNode.obj \ .\$(OBJDIR)\nsScanner.obj \ .\$(OBJDIR)\nsToken.obj \ diff --git a/htmlparser/src/nsDTDDebug.cpp b/htmlparser/src/nsDTDDebug.cpp index a67ad7ac475..17166904c7f 100644 --- a/htmlparser/src/nsDTDDebug.cpp +++ b/htmlparser/src/nsDTDDebug.cpp @@ -67,7 +67,7 @@ public: void SetVerificationDirectory(char * verify_dir); void SetRecordStatistics(PRBool bval); - PRBool Verify(nsIDTD * aDTD, nsParser * aParser, int ContextStackPos, nsVoidArray &aContextStack, char * aURLRef); + PRBool Verify(nsIDTD * aDTD, nsParser * aParser, int ContextStackPos, eHTMLTags aContextStack[], nsString& aURLRef); void DumpVectorRecord(void); // global table for storing vector statistics and the size @@ -78,8 +78,8 @@ private: char * mVerificationDir; PRBool mRecordingStatistics; - PRBool DebugRecord(char * path, char * pURLRef, char * filename); - void NoteVector(nsVoidArray & aTags,PRInt32 count, PRBool good_vector); + PRBool DebugRecord(char * path, nsString& pURLRef, char * filename); + void NoteVector(eHTMLTags aTags[],PRInt32 count, PRBool good_vector); void MakeVectorString(char * vector_string, VectorInfo * pInfo); }; @@ -188,7 +188,7 @@ void CDTDDebug::SetRecordStatistics(PRBool bval) * @return TRUE if it is already record (dont rerecord) */ -PRBool CDTDDebug::DebugRecord(char * path, char * pURLRef, char * filename) +PRBool CDTDDebug::DebugRecord(char * path, nsString& aURLRef, char * filename) { char recordPath[2048]; PRIntn oflags = 0; @@ -215,7 +215,9 @@ PRBool CDTDDebug::DebugRecord(char * path, char * pURLRef, char * filename) // vectors are stored on the format iof "URL vector filename" // where the vector contains the verification path and // the filename contains the debug source dump - sprintf(string,"%s %s %s\r\n", pURLRef, path, filename); + char buffer[513]; + aURLRef.ToCString(buffer,sizeof(buffer)-1); + sprintf(string,"%s %s %s\r\n", buffer, path, filename); // get the file size, read in the file and parse it line at // a time to check to see if we have already recorded this @@ -310,7 +312,7 @@ static int compare( const void *arg1, const void *arg2 ) * @return */ -void CDTDDebug::NoteVector(nsVoidArray & aTags,PRInt32 count, PRBool good_vector) +void CDTDDebug::NoteVector(eHTMLTags aTags[],PRInt32 count, PRBool good_vector) { // if the table doesn't exist, create it if (!mVectorInfoArray) { @@ -327,7 +329,7 @@ void CDTDDebug::NoteVector(nsVoidArray & aTags,PRInt32 count, PRBool good_vector PRBool match = PR_TRUE; for (PRInt32 j = 0; j < count; j++) - if (mVectorInfoArray[i]->vector[j] != (eHTMLTags)(int)aTags[j]) { + if (mVectorInfoArray[i]->vector[j] != aTags[j]) { match = PR_FALSE; break; } @@ -348,7 +350,7 @@ void CDTDDebug::NoteVector(nsVoidArray & aTags,PRInt32 count, PRBool good_vector pVectorInfo->good_vector = good_vector; pVectorInfo->vector = (eHTMLTags*)PR_Malloc(count*sizeof(eHTMLTags)); for (PRInt32 i = 0; i < count; i++) - pVectorInfo->vector[i] = (eHTMLTags)(int)aTags[i]; + pVectorInfo->vector[i] = aTags[i]; mVectorInfoArray[mVectorCount++] = pVectorInfo; // have we maxed out the table? grow it.. sort it.. love it. @@ -467,7 +469,7 @@ void CDTDDebug::DumpVectorRecord(void) * @return TRUE if we know how to handle it, else false */ -PRBool CDTDDebug::Verify(nsIDTD * aDTD, nsParser * aParser, int aContextStackPos, nsVoidArray &aContextStack, char * aURLRef) +PRBool CDTDDebug::Verify(nsIDTD * aDTD, nsParser * aParser, int aContextStackPos, eHTMLTags aContextStack[], nsString& aURLRef) { PRBool result=PR_TRUE; @@ -477,7 +479,7 @@ PRBool CDTDDebug::Verify(nsIDTD * aDTD, nsParser * aParser, int aContextStackPo if(aDTD && aContextStackPos>1) { for (int i = 0; i < aContextStackPos-1; i++) - if (!aDTD->CanContain((eHTMLTags)(int)aContextStack[i],(eHTMLTags)(int)aContextStack[i+1])) { + if (!aDTD->CanContain(aContextStack[i],aContextStack[i+1])) { result = PR_FALSE; break; } @@ -495,7 +497,7 @@ PRBool CDTDDebug::Verify(nsIDTD * aDTD, nsParser * aParser, int aContextStackPo int i=0; for(i=0;i -#include "nsString.h" +#include "nsstring.h" #include "nsParserTypes.h" static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); @@ -89,8 +89,8 @@ NS_IMPL_RELEASE(CHTMLContentSinkStream) * @param nsIParser** ptr to newly instantiated parser * @return NS_xxx error result */ -NS_HTMLPARS nsresult NS_New_HTML_ContentSinkStream(CHTMLContentSinkStream** aInstancePtrResult) { - CHTMLContentSinkStream* it = new CHTMLContentSinkStream(); +NS_HTMLPARS nsresult NS_New_HTML_ContentSinkStream(CHTMLContentSinkStream** aInstancePtrResult,ostream* aStream) { + CHTMLContentSinkStream* it = new CHTMLContentSinkStream(aStream); if (it == 0) { return NS_ERROR_OUT_OF_MEMORY; @@ -99,25 +99,14 @@ NS_HTMLPARS nsresult NS_New_HTML_ContentSinkStream(CHTMLContentSinkStream** aIns return it->QueryInterface(kClassIID, (void **) aInstancePtrResult); } - /** * Construct a content sink stream. * @update gess7/7/98 * @param * @return */ -CHTMLContentSinkStream::CHTMLContentSinkStream() { - mOutput=&cout; -} - -/** - * Construct a content sink stream. - * @update gess7/7/98 - * @param - * @return - */ -CHTMLContentSinkStream::CHTMLContentSinkStream(ostream& aStream) { - mOutput=&aStream; +CHTMLContentSinkStream::CHTMLContentSinkStream(ostream* aStream) { + mOutput=(0==aStream) ? &cout : aStream; } @@ -132,17 +121,6 @@ CHTMLContentSinkStream::~CHTMLContentSinkStream() { } -/** - * - * @update gess7/7/98 - * @param - * @return - */ -void CHTMLContentSinkStream::SetOutputStream(ostream& aStream) { - mOutput=&aStream; -} - - /** * * @update gess7/7/98 @@ -171,7 +149,7 @@ void WriteAttributes(const nsIParserNode& aNode,ostream& aStream) { * @param * @return */ -void OpenTagWithAttributes(const char* theTag,const nsIParserNode& aNode,int tab,ostream& aStream,PRBool aNewline) { +void OpenTagWithAttributes(const char* theTag,const nsIParserNode& aNode,int tab,ostream& aStream,bool aNewline) { int i=0; for(i=0;i -#include "nsIInputStream.h" #include "nsIParserFilter.h" #include "nsIDTDDebug.h" #include "nshtmlpars.h" @@ -47,13 +46,10 @@ static const char* kNullURL = "Error: Null URL given"; static const char* kNullFilename= "Error: Null filename given"; static const char* kNullTokenizer = "Error: Unable to construct tokenizer"; static const char* kHTMLTextContentType = "text/html"; +static nsString kUnknownFilename("unknown"); static const int gTransferBufferSize=4096; //size of the buffer used in moving data from iistream -#define DEBUG_SAVE_SOURCE_DOC 1 -#ifdef DEBUG_SAVE_SOURCE_DOC -fstream* gTempStream=0; -#endif /** @@ -84,7 +80,7 @@ public: } }; -CTokenDeallocator gTokenDeallocator; +CTokenDeallocator gTokenDeallocator2; class CDTDDeallocator: public nsDequeFunctor{ public: @@ -114,6 +110,7 @@ public: CSharedParserObjects() : mDeallocator(), mDTDDeque(mDeallocator) { } + ~CSharedParserObjects() { } @@ -141,25 +138,13 @@ CSharedParserObjects gSharedParserObjects; * @param * @return */ -nsParser::nsParser() : - mTokenDeque(gTokenDeallocator), - mSourceType(), - mTargetType() -{ +nsParser::nsParser() { NS_INIT_REFCNT(); mDTDDebug = 0; mParserFilter = 0; mObserver = 0; - mTransferBuffer=0; mSink=0; - mCurrentPos=0; - mMarkPos=0; - mParseMode=eParseMode_unknown; - mURL=0; - mDTD=0; - mScanner=0; - mTransferBuffer=new char[gTransferBufferSize+1]; - mAutoDetectStatus=eUnknownDetect; + mParserContext=0; } @@ -172,20 +157,12 @@ nsParser::nsParser() : */ nsParser::~nsParser() { NS_IF_RELEASE(mObserver); - NS_IF_RELEASE(mDTDDebug); - if(mTransferBuffer) - delete [] mTransferBuffer; - mTransferBuffer=0; +// NS_IF_RELEASE(mDTDDebug); NS_RELEASE(mSink); - if(mCurrentPos) - delete mCurrentPos; - mCurrentPos=0; - if(mScanner) - delete mScanner; - mScanner=0; - - NS_IF_RELEASE(mURL); + //don't forget to add code here to delete + //what may be several contexts... + delete mParserContext; } @@ -298,7 +275,9 @@ void nsParser::RegisterDTD(nsIDTD* aDTD){ * @return */ CScanner* nsParser::GetScanner(void){ - return mScanner; + if(mParserContext) + return mParserContext->mScanner; + return 0; } /** @@ -311,6 +290,7 @@ CScanner* nsParser::GetScanner(void){ eParseMode DetermineParseMode() { const char* theModeStr= PR_GetEnv("PARSE_MODE"); const char* other="other"; + eParseMode result=eParseMode_navigator; if(theModeStr) @@ -326,25 +306,23 @@ eParseMode DetermineParseMode() { * @param * @return */ -PRBool FindSuitableDTD( eParseMode aMode, - nsString& aSourceType, - nsString& aTargetType, - nsIDTD*& aDefaultDTD) { +PRBool FindSuitableDTD( CParserContext& aParserContext) { //Let's start by tring the defaultDTD, if one exists... - if(aDefaultDTD && (aDefaultDTD->CanParse(aSourceType,0))) + if(aParserContext.mDTD && (aParserContext.mDTD->CanParse(aParserContext.mSourceType,0))) return PR_TRUE; PRBool result=PR_FALSE; + nsDequeIterator b=gSharedParserObjects.mDTDDeque.Begin(); nsDequeIterator e=gSharedParserObjects.mDTDDeque.End(); while(bCanParse(aSourceType,0); + result=theDTD->CanParse(aParserContext.mSourceType,0); if(result){ - aDefaultDTD=theDTD; + aParserContext.mDTD=theDTD; break; } } @@ -371,22 +349,22 @@ eAutoDetectResult nsParser::AutoDetectContentType(nsString& aBuffer,nsString& aT // recognize the content in the scanner. // Somebody should say yes, or we can't continue. - //This method may change mSourceType and mDTD. - //It absolutely changes mAutoDetectStatus + //This method may change mSourceType and mParserContext->mDTD. + //It absolutely changes mParserContext->mAutoDetectStatus nsDequeIterator b=gSharedParserObjects.mDTDDeque.Begin(); nsDequeIterator e=gSharedParserObjects.mDTDDeque.End(); - mAutoDetectStatus=eUnknownDetect; - while((bmAutoDetectStatus=eUnknownDetect; + while((bmAutoDetectStatus)){ nsIDTD* theDTD=(nsIDTD*)b.GetCurrent(); if(theDTD) { - mAutoDetectStatus=theDTD->AutoDetectContentType(aBuffer,aType); + mParserContext->mAutoDetectStatus=theDTD->AutoDetectContentType(aBuffer,aType); } b++; } - return mAutoDetectStatus; + return mParserContext->mAutoDetectStatus; } @@ -401,27 +379,18 @@ eAutoDetectResult nsParser::AutoDetectContentType(nsString& aBuffer,nsString& aT * @param * @return */ -PRInt32 nsParser::WillBuildModel(const char* aFilename){ +PRInt32 nsParser::WillBuildModel(nsString& aFilename){ - mMajorIteration=-1; - mMinorIteration=-1; + mParserContext->mMajorIteration=-1; + mParserContext->mMinorIteration=-1; - mParseMode=DetermineParseMode(); - if(PR_TRUE==FindSuitableDTD(mParseMode,mSourceType,mTargetType,mDTD)) { - mDTD->SetParser(this); - mDTD->SetContentSink(mSink); - mDTD->WillBuildModel(aFilename); + mParserContext->mParseMode=DetermineParseMode(); + if(PR_TRUE==FindSuitableDTD(*mParserContext)) { + mParserContext->mDTD->SetParser(this); + mParserContext->mDTD->SetContentSink(mSink); + mParserContext->mDTD->WillBuildModel(aFilename); } -#ifdef DEBUG_SAVE_SOURCE_DOC -#if defined(XP_UNIX) && (defined(IRIX) || defined(MKLINUX)) - /* XXX: IRIX does not support ios::binary */ - gTempStream =new fstream("/tmp/out.html",ios::out); -#else - gTempStream = new fstream("c:/temp/out.html",ios::out|ios::binary); -#endif -#endif - return kNoError; } @@ -434,18 +403,10 @@ PRInt32 nsParser::WillBuildModel(const char* aFilename){ PRInt32 nsParser::DidBuildModel(PRInt32 anErrorCode) { //One last thing...close any open containers. PRInt32 result=anErrorCode; - if(mDTD) { - result=mDTD->DidBuildModel(anErrorCode); + if(mParserContext->mDTD) { + result=mParserContext->mDTD->DidBuildModel(anErrorCode); } -#ifdef DEBUG_SAVE_SOURCE_DOC - if(gTempStream) { - gTempStream->close(); - delete gTempStream; - gTempStream=0; - } -#endif - return result; } @@ -460,22 +421,21 @@ PRInt32 nsParser::DidBuildModel(PRInt32 anErrorCode) { * @param aFilename -- const char* containing file to be parsed. * @return PR_TRUE if parse succeeded, PR_FALSE otherwise. */ -PRBool nsParser::Parse(const char* aFilename){ - NS_PRECONDITION(0!=aFilename,kNullFilename); +PRInt32 nsParser::Parse(nsString& aFilename){ PRInt32 status=kBadFilename; if(aFilename) { //ok, time to create our tokenizer and begin the process - mTargetType=kHTMLTextContentType; - mScanner=new CScanner(aFilename,mParseMode); - if(mScanner) { - mScanner->Eof(); - if(eValidDetect==AutoDetectContentType(mScanner->GetBuffer(),mSourceType)) { - WillBuildModel(aFilename); - status=ResumeParse(); - DidBuildModel(status); - } + + mParserContext = new CParserContext(new CScanner(aFilename),mParserContext); + mParserContext->mScanner->Eof(); + if(eValidDetect==AutoDetectContentType(mParserContext->mScanner->GetBuffer(), + mParserContext->mSourceType)) + { + WillBuildModel(aFilename); + status=ResumeParse(); + DidBuildModel(status); } //if } return status; @@ -488,11 +448,35 @@ PRBool nsParser::Parse(const char* aFilename){ * @return TRUE if all went well -- FALSE otherwise */ PRInt32 nsParser::Parse(fstream& aStream){ - PRInt32 result=0; - return result; + + PRInt32 status=kNoError; + + //ok, time to create our tokenizer and begin the process + mParserContext = new CParserContext(new CScanner(kUnknownFilename,aStream,PR_FALSE),mParserContext); + + mParserContext->mScanner->Eof(); + if(eValidDetect==AutoDetectContentType(mParserContext->mScanner->GetBuffer(), + mParserContext->mSourceType)) { + WillBuildModel(mParserContext->mScanner->GetFilename()); + status=ResumeParse(); + DidBuildModel(status); + } //if + + return status; } +/** + * + * @update gess7/13/98 + * @param + * @return + */ +PRInt32 nsParser::Parse(nsIInputStream* pIStream,nsIStreamObserver* aListener,nsIDTDDebug* aDTDDebug){ + PRInt32 result=kNoError; + return result; +} + /** * This is the main controlling routine in the parsing process. * Note that it may get called multiple times for the same scanner, @@ -512,19 +496,14 @@ PRInt32 nsParser::Parse(nsIURL* aURL,nsIStreamObserver* aListener, nsIDTDDebug * PRInt32 status=kBadURL; +/* Disable DTD Debug for now... mDTDDebug = aDTDDebug; NS_IF_ADDREF(mDTDDebug); - - NS_IF_RELEASE(mURL); - mURL = aURL; - NS_IF_ADDREF(mURL); - - NS_IF_RELEASE(mObserver); - mObserver = aListener; - NS_IF_ADDREF(mObserver); +*/ - if(mURL) { - mScanner=new CScanner(mParseMode); + if(aURL) { + nsAutoString theName(aURL->GetSpec()); + mParserContext=new CParserContext(new CScanner(theName,PR_FALSE),mParserContext,aListener); status=NS_OK; } return status; @@ -533,6 +512,8 @@ PRInt32 nsParser::Parse(nsIURL* aURL,nsIStreamObserver* aListener, nsIDTDDebug * /** * Call this method if all you want to do is parse 1 string full of HTML text. + * In particular, this method should be called by the DOM when it has an HTML + * string to feed to the parser in real-time. * * @update gess5/11/98 * @param anHTMLString contains a string-full of real HTML @@ -542,11 +523,10 @@ PRInt32 nsParser::Parse(nsIURL* aURL,nsIStreamObserver* aListener, nsIDTDDebug * PRInt32 nsParser::Parse(nsString& aSourceBuffer,PRBool appendTokens){ PRInt32 result=kNoError; - mTargetType=kHTMLTextContentType; - mScanner=new CScanner(); - mScanner->Append(aSourceBuffer); - if(eValidDetect==AutoDetectContentType(aSourceBuffer,mSourceType)) { - WillBuildModel(""); + mParserContext = new CParserContext(new CScanner(kUnknownFilename),mParserContext,0); + mParserContext->mScanner->Append(aSourceBuffer); + if(eValidDetect==AutoDetectContentType(aSourceBuffer,mParserContext->mSourceType)) { + WillBuildModel(mParserContext->mScanner->GetFilename()); result=ResumeParse(); DidBuildModel(result); } @@ -567,12 +547,12 @@ PRInt32 nsParser::Parse(nsString& aSourceBuffer,PRBool appendTokens){ PRInt32 nsParser::ResumeParse() { PRInt32 result=kNoError; - mDTD->WillResumeParse(); + mParserContext->mDTD->WillResumeParse(); if(kNoError==result) { result=Tokenize(); if(kInterrupted==result) - mDTD->WillInterruptParse(); - IterateTokens(); + mParserContext->mDTD->WillInterruptParse(); + BuildModel(); } return result; } @@ -585,26 +565,28 @@ PRInt32 nsParser::ResumeParse() { * @param * @return PR_TRUE if parse succeeded, PR_FALSE otherwise. */ -PRInt32 nsParser::IterateTokens() { - nsDequeIterator e=mTokenDeque.End(); +PRInt32 nsParser::BuildModel() { + + nsDequeIterator e=mParserContext->mTokenDeque.End(); nsDequeIterator theMarkPos(e); - mMajorIteration++; - if(!mCurrentPos) - mCurrentPos=new nsDequeIterator(mTokenDeque.Begin()); +// mParserContext->mMajorIteration++; + + if(!mParserContext->mCurrentPos) + mParserContext->mCurrentPos=new nsDequeIterator(mParserContext->mTokenDeque.Begin()); PRInt32 result=kNoError; - while((kNoError==result) && ((*mCurrentPosGetCurrent(); + while((kNoError==result) && ((*mParserContext->mCurrentPosmMinorIteration++; + CToken* theToken=(CToken*)mParserContext->mCurrentPos->GetCurrent(); - theMarkPos=*mCurrentPos; - result=mDTD->HandleToken(theToken); - ++(*mCurrentPos); + theMarkPos=*mParserContext->mCurrentPos; + result=mParserContext->mDTD->HandleToken(theToken); + ++(*mParserContext->mCurrentPos); } if(kInterrupted==result) - *mCurrentPos=theMarkPos; + *mParserContext->mCurrentPos=theMarkPos; return result; } @@ -619,17 +601,17 @@ PRInt32 nsParser::IterateTokens() { * @return error code (should be 0) */ PRInt32 nsParser::CollectAttributes(nsCParserNode& aNode,PRInt32 aCount){ - nsDequeIterator end=mTokenDeque.End(); + nsDequeIterator end=mParserContext->mTokenDeque.End(); int attr=0; for(attr=0;attrmCurrentPosmCurrentPos)); if(tkn){ if(eToken_attribute==eHTMLTokenTypes(tkn->GetTokenType())){ aNode.AddAttribute(tkn); } - else (*mCurrentPos)--; + else (*mParserContext->mCurrentPos)--; } else return kInterrupted; } @@ -649,18 +631,18 @@ PRInt32 nsParser::CollectAttributes(nsCParserNode& aNode,PRInt32 aCount){ */ PRInt32 nsParser::CollectSkippedContent(nsCParserNode& aNode,PRInt32& aCount) { eHTMLTokenTypes subtype=eToken_attribute; - nsDequeIterator end=mTokenDeque.End(); + nsDequeIterator end=mParserContext->mTokenDeque.End(); PRInt32 result=kNoError; aCount=0; - while((*mCurrentPos!=end) && (eToken_attribute==subtype)) { - CToken* tkn=(CToken*)(++(*mCurrentPos)); + while((*mParserContext->mCurrentPos!=end) && (eToken_attribute==subtype)) { + CToken* tkn=(CToken*)(++(*mParserContext->mCurrentPos)); subtype=eHTMLTokenTypes(tkn->GetTokenType()); if(eToken_skippedcontent==subtype) { aNode.SetSkippedContent(tkn); aCount++; } - else (*mCurrentPos)--; + else (*mParserContext->mCurrentPos)--; } return result; } @@ -710,10 +692,9 @@ nsresult nsParser::OnStartBinding(const char *aSourceType){ if (nsnull != mObserver) { mObserver->OnStartBinding(aSourceType); } - mAutoDetectStatus=eUnknownDetect; - mDTD=0; - - mSourceType=aSourceType; + mParserContext->mAutoDetectStatus=eUnknownDetect; + mParserContext->mDTD=0; + mParserContext->mSourceType=aSourceType; return kNoError; } @@ -732,37 +713,33 @@ nsresult nsParser::OnDataAvailable(nsIInputStream *pIStream, PRInt32 length){ mListener->OnDataAvailable(pIStream, length); } */ - int len=0; - int offset=0; - if(eInvalidDetect==mAutoDetectStatus) { - if(mScanner) { - mScanner->GetBuffer().Truncate(); + if(eInvalidDetect==mParserContext->mAutoDetectStatus) { + if(mParserContext->mScanner) { + mParserContext->mScanner->GetBuffer().Truncate(); } } - do { - PRInt32 err; - len = pIStream->Read(&err, mTransferBuffer, 0, gTransferBufferSize); - if(len>0) { + int len=1; //init to a non-zero value + int err; + int offset=0; - #ifdef DEBUG_SAVE_SOURCE_DOC - if(gTempStream) { - gTempStream->write(mTransferBuffer,len); - } - #endif + while (len > 0) { + len = pIStream->Read(&err, mParserContext->mTransferBuffer, 0, mParserContext->eTransferBufferSize); + if(len>0) { - if (mParserFilter) - mParserFilter->RawBuffer(mTransferBuffer, &len); - mScanner->Append(mTransferBuffer,len); + if(mParserFilter) + mParserFilter->RawBuffer(mParserContext->mTransferBuffer, &len); - if(eUnknownDetect==mAutoDetectStatus) { - if(eValidDetect==AutoDetectContentType(mScanner->GetBuffer(),mSourceType)) { - nsresult result=WillBuildModel(mURL->GetSpec()); - } //if - } - } //if - } while (len > 0); + mParserContext->mScanner->Append(mParserContext->mTransferBuffer,len); + + if(eUnknownDetect==mParserContext->mAutoDetectStatus) { + if(eValidDetect==AutoDetectContentType(mParserContext->mScanner->GetBuffer(),mParserContext->mSourceType)) { + nsresult result=WillBuildModel(mParserContext->mScanner->GetFilename()); + } //if + } + } //if + } nsresult result=ResumeParse(); return result; @@ -797,7 +774,7 @@ nsresult nsParser::OnStopBinding(PRInt32 status, const nsString& aMsg){ * @return new token or null */ PRInt32 nsParser::ConsumeToken(CToken*& aToken) { - PRInt32 result=mDTD->ConsumeToken(aToken); + PRInt32 result=mParserContext->mDTD->ConsumeToken(aToken); return result; } @@ -811,39 +788,11 @@ PRInt32 nsParser::ConsumeToken(CToken*& aToken) { * @param * @return TRUE if it's ok to proceed */ -PRBool nsParser::WillTokenize(void){ +PRBool nsParser::WillTokenize(){ PRBool result=PR_TRUE; return result; } -/** - * - * @update gess 3/25/98 - * @return TRUE if it's ok to proceed - */ -PRInt32 nsParser::Tokenize(nsString& aSourceBuffer,PRBool appendTokens){ - CToken* theToken=0; - PRInt32 result=kNoError; - PRInt32 debugCounter=0; //this can be removed. It's only for debugging... - - WillTokenize(); - - while(kNoError==result) { - debugCounter++; - result=ConsumeToken(theToken); - if(theToken && (kNoError==result)) { - -#ifdef VERBOSE_DEBUG - theToken->DebugDumpToken(cout); -#endif - mTokenDeque.Push(theToken); - } - } - if(kEOF==result) - result=kNoError; - DidTokenize(); - return result; -} /** * This is the primary control routine. It iteratively @@ -853,14 +802,14 @@ PRInt32 nsParser::Tokenize(nsString& aSourceBuffer,PRBool appendTokens){ * @update gess 3/25/98 * @return error code */ -PRInt32 nsParser::Tokenize(void) { +PRInt32 nsParser::Tokenize(){ CToken* theToken=0; PRInt32 result=kNoError; - PRBool done=(0==mMajorIteration) ? (!WillTokenize()) : PR_FALSE; + PRBool done=(0==++mParserContext->mMajorIteration) ? (!WillTokenize()) : PR_FALSE; while((PR_FALSE==done) && (kNoError==result)) { - mScanner->Mark(); + mParserContext->mScanner->Mark(); result=ConsumeToken(theToken); if(kNoError==result) { if(theToken) { @@ -868,14 +817,14 @@ PRInt32 nsParser::Tokenize(void) { #ifdef VERBOSE_DEBUG theToken->DebugDumpToken(cout); #endif - mTokenDeque.Push(theToken); + mParserContext->mTokenDeque.Push(theToken); } } else { if(theToken) delete theToken; - mScanner->RewindToMark(); + mParserContext->mScanner->RewindToMark(); } } if((PR_TRUE==done) && (kInterrupted!=result)) @@ -892,7 +841,7 @@ PRInt32 nsParser::Tokenize(void) { * @param * @return TRUE if all went well */ -PRBool nsParser::DidTokenize(void) { +PRBool nsParser::DidTokenize(){ PRBool result=PR_TRUE; #ifdef VERBOSE_DEBUG @@ -912,8 +861,8 @@ PRBool nsParser::DidTokenize(void) { * @return */ void nsParser::DebugDumpTokens(ostream& out) { - nsDequeIterator b=mTokenDeque.Begin(); - nsDequeIterator e=mTokenDeque.End(); + nsDequeIterator b=mParserContext->mTokenDeque.Begin(); + nsDequeIterator e=mParserContext->mTokenDeque.End(); CToken* theToken; while(b!=e) { @@ -933,8 +882,8 @@ void nsParser::DebugDumpTokens(ostream& out) { * @return */ void nsParser::DebugDumpSource(ostream& out) { - nsDequeIterator b=mTokenDeque.Begin(); - nsDequeIterator e=mTokenDeque.End(); + nsDequeIterator b=mParserContext->mTokenDeque.Begin(); + nsDequeIterator e=mParserContext->mTokenDeque.End(); CToken* theToken; while(b!=e) { diff --git a/htmlparser/src/nsParser.h b/htmlparser/src/nsParser.h index 8fdf384dba1..2f59c0b3abc 100644 --- a/htmlparser/src/nsParser.h +++ b/htmlparser/src/nsParser.h @@ -60,7 +60,7 @@ #include "nsParserNode.h" #include "nsParserTypes.h" #include "nsIURL.h" - +#include "CParserContext.h" #define NS_PARSER_IID \ {0x2ce606b0, 0xbee6, 0x11d1, \ @@ -69,7 +69,6 @@ class IContentSink; class nsIHTMLContentSink; -class nsIURL; class nsIDTD; class nsIDTDDebug; class CScanner; @@ -119,14 +118,26 @@ friend class CTokenHandler; virtual CScanner* GetScanner(void); /** - * Cause parser to parse input from given URL in given mode + * Cause parser to parse input from given URL * @update gess5/11/98 * @param aURL is a descriptor for source document * @param aListener is a listener to forward notifications to * @return TRUE if all went well -- FALSE otherwise */ virtual PRInt32 Parse(nsIURL* aURL, - nsIStreamObserver* aListener, nsIDTDDebug * aDTDDebug = 0); + nsIStreamObserver* aListener, + nsIDTDDebug* aDTDDebug = 0); + + /** + * Cause parser to parse input from given nsIInputStream + * @update gess5/11/98 + * @param pIStream is an nsIInputStream + * @param aListener is a listener to forward notifications to + * @return TRUE if all went well -- FALSE otherwise + */ + virtual PRInt32 Parse(nsIInputStream* pIStream, + nsIStreamObserver* aListener, + nsIDTDDebug* aDTDDebug = 0); /** * Cause parser to parse input from given file in given mode @@ -134,7 +145,7 @@ friend class CTokenHandler; * @param aFilename is a path for file document * @return TRUE if all went well -- FALSE otherwise */ - virtual PRInt32 Parse(const char* aFilename); + virtual PRInt32 Parse(nsString& aFilename); /** * Cause parser to parse input from given stream @@ -157,7 +168,7 @@ friend class CTokenHandler; * @update gess5/11/98 * @return TRUE if all went well, otherwise FALSE */ - virtual PRInt32 ResumeParse(void); + virtual PRInt32 ResumeParse(); /** * Causes the parser to scan foward, collecting nearby (sequential) @@ -208,7 +219,7 @@ protected: * @param * @return */ - PRInt32 WillBuildModel(const char* aFilename=0); + PRInt32 WillBuildModel(nsString& aFilename); /** * @@ -224,7 +235,7 @@ protected: * @update gess5/11/98 * @return YES if model building went well -- NO otherwise. */ - virtual PRInt32 IterateTokens(void); + virtual PRInt32 BuildModel(void); private: @@ -251,15 +262,9 @@ private: * @param * @return TRUE if it's ok to proceed */ - PRBool WillTokenize(void); - - /** - * - * @update gess 3/25/98 - * @return TRUE if it's ok to proceed - */ - PRInt32 Tokenize(nsString& aSourceBuffer,PRBool appendTokens); + PRBool WillTokenize(); + /** * This is the primary control routine. It iteratively * consumes tokens until an error occurs or you run out @@ -268,7 +273,7 @@ private: * @update gess 3/25/98 * @return error code */ - PRInt32 Tokenize(void); + PRInt32 Tokenize(); /** * This is the tail-end of the code sandwich for the @@ -279,7 +284,7 @@ private: * @param * @return TRUE if all went well */ - PRBool DidTokenize(void); + PRBool DidTokenize(); /** * This debug routine is used to cause the tokenizer to @@ -311,27 +316,42 @@ protected: // And now, some data members... //********************************************* - nsIStreamObserver* mObserver; - nsIContentSink* mSink; - nsIParserFilter* mParserFilter; - - nsDequeIterator* mCurrentPos; - nsDequeIterator* mMarkPos; - - nsIDTD* mDTD; - eParseMode mParseMode; - char* mTransferBuffer; + /***************************************************** + All of these moved into the parse-context object: PRInt32 mMajorIteration; PRInt32 mMinorIteration; - nsDeque mTokenDeque; - CScanner* mScanner; nsIURL* mURL; - nsIDTDDebug* mDTDDebug; nsString mSourceType; nsString mTargetType; eAutoDetectResult mAutoDetectStatus; + + nsDequeIterator* mCurrentPos; + nsDequeIterator* mMarkPos; + nsDeque mTokenDeque; + CScanner* mScanner; + nsIDTD* mDTD; + + eParseMode mParseMode; + char* mTransferBuffer; + *****************************************************/ + + CParserContext* mParserContext; + + /***************************************************** + The above fields are moving into parse-context + *****************************************************/ + + + nsIStreamObserver* mObserver; + nsIContentSink* mSink; + nsIParserFilter* mParserFilter; + + + nsIDTDDebug* mDTDDebug; + + }; diff --git a/htmlparser/src/nsScanner.cpp b/htmlparser/src/nsScanner.cpp index 6e38c26f645..7a9118a1fbc 100644 --- a/htmlparser/src/nsScanner.cpp +++ b/htmlparser/src/nsScanner.cpp @@ -19,10 +19,8 @@ //#define __INCREMENTAL 1 #include "nsScanner.h" -#include "nsIURL.h" #include "nsDebug.h" -const char* gURLRef=0; const char* kBadHTMLText="

Oops...

You just tried to read a non-existent document:
"; #ifdef __INCREMENTAL @@ -31,89 +29,55 @@ const int kBufsize=1; const int kBufsize=64; #endif + /** - * Use this constructor if you want an incremental (callback) - * based input stream. + * Use this constructor if you want i/o to be based on an + * incremental netstream. If you pass a null filename, you + * can still provide data to the scanner via append. * * @update gess 5/12/98 - * @param aMode represents the parser mode (nav, other) + * @param aFilename -- * @return */ -CScanner::CScanner(eParseMode aMode) : mBuffer("") { +CScanner::CScanner(nsString& aFilename,PRBool aCreateStream) : + mBuffer(""), mFilename(aFilename) +{ mOffset=0; mMarkPos=-1; mTotalRead=0; - mParseMode=aMode; - mNetStream=0; + mOwnsStream=aCreateStream; mFileStream=0; - mIncremental=PR_TRUE; - mOwnsStream=PR_TRUE; + if(aCreateStream) { + char buffer[513]; + aFilename.ToCString(buffer,sizeof(buffer)-1); + #if defined(XP_UNIX) && (defined(IRIX) || defined(MKLINUX)) + /* XXX: IRIX does not support ios::binary */ + mFileStream=new fstream(buffer,ios::in); + #else + mFileStream=new fstream(buffer,ios::in|ios::binary); + #endif + } //if } /** - * Use this constructor if you want i/o to be file based. + * Use this constructor if you want i/o to be stream based. * * @update gess 5/12/98 - * @param aMode represents the parser mode (nav, other) + * @param aStream -- + * @param assumeOwnership -- + * @param aFilename -- * @return */ -CScanner::CScanner(const char* aFilename,eParseMode aMode) : mBuffer("") { - NS_ASSERTION(0!=aFilename,"Error: Null filename!"); +CScanner::CScanner(nsString& aFilename,fstream& aStream,PRBool assumeOwnership) : + mBuffer(""), mFilename(aFilename) +{ mOffset=0; mMarkPos=-1; mTotalRead=0; - mParseMode=aMode; - mNetStream=0; - mIncremental=PR_FALSE; - mOwnsStream=PR_TRUE; -#if defined(XP_UNIX) && (defined(IRIX) || defined(MKLINUX)) - /* XXX: IRIX does not support ios::binary */ - mFileStream=new fstream(aFilename,ios::in); -#else - mFileStream=new fstream(aFilename,ios::in|ios::binary); -#endif -} - -/** - * Use this constructor if you want i/o to be file based. - * - * @update gess 5/12/98 - * @param aMode represents the parser mode (nav, other) - * @return - */ -CScanner::CScanner(fstream& aStream,eParseMode aMode) : mBuffer("") { - mOffset=0; - mMarkPos=-1; - mTotalRead=0; - mParseMode=aMode; - mNetStream=0; - mIncremental=PR_FALSE; - mOwnsStream=PR_FALSE; + mOwnsStream=assumeOwnership; mFileStream=&aStream; } -/** - * Use this constructor if you want i/o to be based on a - * non-incremental netstream. - * - * @update gess 5/12/98 - * @param aMode represents the parser mode (nav, other) - * @return - */ -CScanner::CScanner(nsIURL* aURL,eParseMode aMode) : mBuffer("") { - NS_ASSERTION(0!=aURL,"Error: Null URL!"); - mOffset=0; - mMarkPos=-1; - mTotalRead=0; - mParseMode=aMode; - mFileStream=0; - PRInt32 error=0; - mIncremental=PR_FALSE; - mNetStream=aURL->Open(&error); - gURLRef=aURL->GetSpec(); - mOwnsStream=PR_FALSE; -} - /** * default destructor @@ -128,13 +92,7 @@ CScanner::~CScanner() { if(mOwnsStream) delete mFileStream; } - else if(mNetStream) { - mNetStream->Close(); - mNetStream->Release(); - } mFileStream=0; - mNetStream=0; - gURLRef=0; } /** @@ -200,34 +158,9 @@ void _PreCompressBuffer(nsString& aBuffer,PRInt32& anOffset,PRInt32& aMarkPos){ } -/** - * This method should only be called by the parser when - * we're doing incremental i/o over the net. - * - * @update gess 5/12/98 - * @param aBuffer contains next blob of i/o data - * @param aSize contains size of buffer - * @return 0 if all went well, otherwise error code. - */ -PRInt32 CScanner::IncrementalAppend(const char* aBuffer,PRInt32 aSize){ - NS_ASSERTION(((!mFileStream) && (!mNetStream)),"Error: Should only be called during incremental net i/o!"); - - PRInt32 result=0; - if((!mFileStream) && (!mNetStream)) { - - _PreCompressBuffer(mBuffer,mOffset,mMarkPos); - - //now that the buffer is (possibly) shortened, let's append the new data. - if(0read(buf,kBufsize); numread=mFileStream->gcount(); } - else if(mNetStream) { - numread=mNetStream->Read(&anError,buf,0,kBufsize); - if(1==anError) - anError=kEOF; - } mOffset=mBuffer.Length(); if((0=mBuffer.Length()) { - if(!mIncremental) - theError=FillBuffer(); - else return kInterrupted; + theError=FillBuffer(); } if(0==theError) @@ -451,21 +378,21 @@ PRInt32 CScanner::SkipPast(nsString& aValidSet){ * @return error code */ PRInt32 CScanner::ReadWhile(nsString& aString,nsString& aValidSet,PRBool addTerminal){ - PRUnichar ch=0; + PRUnichar theChar=0; PRInt32 result=kNoError; PRInt32 wrPos=0; while(kNoError==result) { - result=GetChar(ch); + result=GetChar(theChar); if(kNoError==result) { - PRInt32 pos=aValidSet.Find(ch); + PRInt32 pos=aValidSet.Find(theChar); if(kNotFound==pos) { if(addTerminal) - aString+=ch; - else PutBack(ch); + aString+=theChar; + else PutBack(theChar); break; } - else aString+=ch; + else aString+=theChar; } } return result; @@ -535,6 +462,18 @@ nsString& CScanner::GetBuffer(void) { return mBuffer; } +/** + * Retrieve the name of the file that the scanner is reading from. + * In some cases, it's just a given name, because the scanner isn't + * really reading from a file. + * + * @update gess 5/12/98 + * @return + */ +nsString& CScanner::GetFilename(void) { + return mFilename; +} + /** * Conduct self test. Actually, selftesting for this class * occurs in the parser selftest. diff --git a/htmlparser/src/nsScanner.h b/htmlparser/src/nsScanner.h index d03b9bfb2f8..627a7f27fe1 100644 --- a/htmlparser/src/nsScanner.h +++ b/htmlparser/src/nsScanner.h @@ -35,43 +35,21 @@ #include "nsString.h" #include "nsParserTypes.h" #include "prtypes.h" -#include "nsIInputStream.h" #include -class nsIURL; -//class ifstream; class CScanner { public: /** - * Use this constructor if you want an incremental (callback) - * based input stream. + * Use this constructor if you want i/o to be based on + * a file (therefore a stream) or just data you provide via Append(). * * @update gess 5/12/98 * @param aMode represents the parser mode (nav, other) * @return */ - CScanner(eParseMode aMode=eParseMode_navigator); - - /** - * Use this constructor if you want i/o to be based on a - * non-incremental netstream. - * - * @update gess 5/12/98 - * @param aMode represents the parser mode (nav, other) - * @return - */ - CScanner(nsIURL* aURL,eParseMode aMode=eParseMode_navigator); - - /** - * Use this constructor if you want i/o to be file based. - * - * @update gess 5/12/98 - * @param aMode represents the parser mode (nav, other) - * @return - */ - CScanner(const char* aFilename,eParseMode aMode=eParseMode_navigator); + CScanner(nsString& aFilename,PRBool aCreateStream=PR_TRUE); /** * Use this constructor if you want i/o to be stream based. @@ -80,7 +58,7 @@ class CScanner { * @param aMode represents the parser mode (nav, other) * @return */ - CScanner(fstream& aStream,eParseMode aMode=eParseMode_navigator); + CScanner(nsString& aFilename,fstream& aStream,PRBool assumeOwnership=PR_TRUE); ~CScanner(); @@ -241,16 +219,17 @@ class CScanner { * @param * @return */ - PRInt32 IncrementalAppend(const char* aBuffer,PRInt32 aSize); + nsString& GetBuffer(void); /** - * + * Retrieve the name of the file that the scanner is reading from. + * In some cases, it's just a given name, because the scanner isn't + * really reading from a file. * * @update gess 5/12/98 - * @param * @return */ - nsString& GetBuffer(void); + nsString& GetFilename(void); static void SelfTest(); @@ -268,13 +247,11 @@ class CScanner { fstream* mFileStream; - nsIInputStream* mNetStream; nsString mBuffer; + nsString mFilename; PRInt32 mOffset; PRInt32 mMarkPos; PRInt32 mTotalRead; - eParseMode mParseMode; - PRBool mIncremental; PRBool mOwnsStream; }; diff --git a/htmlparser/src/nsValidDTD.cpp b/htmlparser/src/nsValidDTD.cpp index 979a78bd12b..95874180e58 100644 --- a/htmlparser/src/nsValidDTD.cpp +++ b/htmlparser/src/nsValidDTD.cpp @@ -190,7 +190,7 @@ eAutoDetectResult CValidDTD::AutoDetectContentType(nsString& aBuffer,nsString& a * @param * @return */ -PRInt32 CValidDTD::WillBuildModel(const char* aFilename){ +PRInt32 CValidDTD::WillBuildModel(nsString& aFilename){ PRInt32 result=0; return result; } diff --git a/htmlparser/src/nsValidDTD.h b/htmlparser/src/nsValidDTD.h index c0798370091..24bfc89a38a 100644 --- a/htmlparser/src/nsValidDTD.h +++ b/htmlparser/src/nsValidDTD.h @@ -108,7 +108,7 @@ class CValidDTD : public nsIDTD { * @param * @return */ - virtual PRInt32 WillBuildModel(const char* aFilename=0); + virtual PRInt32 WillBuildModel(nsString& aFilename); /** * diff --git a/htmlparser/src/nsWellFormedDTD.cpp b/htmlparser/src/nsWellFormedDTD.cpp index d092ed0e9ec..8137c3299b9 100644 --- a/htmlparser/src/nsWellFormedDTD.cpp +++ b/htmlparser/src/nsWellFormedDTD.cpp @@ -177,7 +177,7 @@ eAutoDetectResult CWellFormedDTD::AutoDetectContentType(nsString& aBuffer,nsStri * @param * @return */ -PRInt32 CWellFormedDTD::WillBuildModel(const char* aFilename){ +PRInt32 CWellFormedDTD::WillBuildModel(nsString& aFilename){ PRInt32 result=0; return result; } diff --git a/htmlparser/src/nsWellFormedDTD.h b/htmlparser/src/nsWellFormedDTD.h index 6add8b9a5b5..47155413f68 100644 --- a/htmlparser/src/nsWellFormedDTD.h +++ b/htmlparser/src/nsWellFormedDTD.h @@ -97,7 +97,7 @@ class CWellFormedDTD : public nsIDTD { * @param * @return */ - virtual PRInt32 WillBuildModel(const char* aFilename=0); + virtual PRInt32 WillBuildModel(nsString& aFilename); /** * diff --git a/parser/htmlparser/src/CNavDTD.cpp b/parser/htmlparser/src/CNavDTD.cpp index a20c8c59367..3400ef36e19 100644 --- a/parser/htmlparser/src/CNavDTD.cpp +++ b/parser/htmlparser/src/CNavDTD.cpp @@ -91,6 +91,115 @@ static char gWhitespaceTags[]={ 0}; +/************************************************************************ + CTagStack class implementation. + The reason we use this class is so that we can view the stack state + in the usual way via the debugger. + ************************************************************************/ + + +CTagStack::CTagStack(int aDefaultSize) { +#ifdef _dynstack + mSize=aDefaultSize; + mTags =new eHTMLTags[mSize]; + mBits =new PRBool[mSize]; +#else + mSize=eStackSize; +#endif + mCount=0; + nsCRT::zero(mTags,mSize*sizeof(eHTMLTag_html)); + nsCRT::zero(mBits,mSize*sizeof(PRBool)); +} + +/** + * Default constructor + * @update gess7/9/98 + * @param aDefaultsize tells the stack what size to start out. + * however, we'll autosize as needed. + */ +CTagStack::~CTagStack() { +#ifdef _dynstack + delete mTags; + delete mBits; + mTags=0; + mBits=0; +#endif + mSize=mCount=0; + } + +/** + * + * @update gess7/9/98 + * @param + * @return + */ +void CTagStack::Push(eHTMLTags aTag) { + + if(mCount>=mSize) { + +#ifdef _dynstack + eHTMLTags* tmp=new eHTMLTags[2*mSize]; + nsCRT::zero(tmp,2*mSize*sizeof(eHTMLTag_html)); + nsCRT::memcpy(tmp,mTags,mSize*sizeof(eHTMLTag_html)); + delete mTags; + mTags=tmp; + + PRBool* tmp2=new PRBool[2*mSize]; + nsCRT::zero(tmp2,2*mSize*sizeof(PRBool)); + nsCRT::memcpy(tmp2,mBits,mSize*sizeof(PRBool)); + delete mBits; + mBits=tmp2; + mSize*=2; +#endif + } + mTags[mCount++]=aTag; +} + +/** + * + * @update gess7/9/98 + * @param + * @return + */ +eHTMLTags CTagStack::Pop() { + eHTMLTags result=eHTMLTag_unknown; + if(mCount>0) { + result=mTags[--mCount]; + mTags[mCount]=eHTMLTag_unknown; + mBits[mCount]=PR_FALSE; + } + return result; +} + +/** + * + * @update gess7/9/98 + * @param + * @return + */ +eHTMLTags CTagStack::First() const { + if(mCount>0) + return mTags[0]; + return eHTMLTag_unknown; +} + +/** + * + * @update gess7/9/98 + * @param + * @return + */ +eHTMLTags CTagStack::Last() const { + if(mCount>0) + return mTags[mCount-1]; + return eHTMLTag_unknown; +} + + +/************************************************************************ + And now for the main class -- CNavDTD... + ************************************************************************/ + /** * This method gets called as part of our COM-like interfaces. * Its purpose is to create an interface to parser object @@ -124,6 +233,7 @@ nsresult CNavDTD::QueryInterface(const nsIID& aIID, void** aInstancePtr) return NS_OK; } + /** * This method is defined in nsIParser. It is used to * cause the COM-like construction of an nsParser. @@ -234,15 +344,13 @@ static CNavTokenDeallocator gTokenKiller; * @param * @return */ -CNavDTD::CNavDTD() : nsIDTD(), mTokenDeque(gTokenKiller) { +CNavDTD::CNavDTD() : nsIDTD(), mTokenDeque(gTokenKiller), + mContextStack(), mStyleStack() { NS_INIT_REFCNT(); mParser=0; - mFilename=0; mSink = nsnull; mDTDDebug=0; nsCRT::zero(mTokenHandlers,sizeof(mTokenHandlers)); - mContextStackPos=0; - mStyleStackPos=0; mHasOpenForm=PR_FALSE; mHasOpenMap=PR_FALSE; InitializeDefaultTokenHandlers(); @@ -257,8 +365,6 @@ CNavDTD::CNavDTD() : nsIDTD(), mTokenDeque(gTokenKiller) { */ CNavDTD::~CNavDTD(){ DeleteTokenHandlers(); - if (mFilename) - PL_strfree(mFilename); if (mDTDDebug) NS_RELEASE(mDTDDebug); @@ -281,6 +387,7 @@ void CNavDTD::SetDTDDebug(nsIDTDDebug * aDTDDebug) NS_ADDREF(mDTDDebug); } + /** * This method is called to determine if the given DTD can parse * a document in a given source-type. @@ -308,24 +415,16 @@ eAutoDetectResult CNavDTD::AutoDetectContentType(nsString& aBuffer,nsString& aTy return result; } - - /** * * @update gess5/18/98 * @param * @return */ -PRInt32 CNavDTD::WillBuildModel(const char* aFilename){ +PRInt32 CNavDTD::WillBuildModel(nsString& aFilename){ PRInt32 result=0; - if (mFilename) { - PL_strfree(mFilename); - mFilename=0; - } - if(aFilename) { - mFilename = PL_strdup(aFilename); - } + mFilename=aFilename; if(mSink) mSink->WillBuildModel(); @@ -342,7 +441,7 @@ PRInt32 CNavDTD::WillBuildModel(const char* aFilename){ PRInt32 CNavDTD::DidBuildModel(PRInt32 anErrorCode){ PRInt32 result=0; - if((kNoError==anErrorCode) && (mContextStackPos>0)) { + if((kNoError==anErrorCode) && (mContextStack.mCount>0)) { CloseContainersTo(0,eHTMLTag_unknown,PR_FALSE); } if(mSink) { @@ -375,7 +474,7 @@ PRInt32 CNavDTD::HandleToken(CToken* aToken){ if(theHandler) { result=(*theHandler)(theToken,this); if (mDTDDebug) - mDTDDebug->Verify(this, mParser, mContextStackPos, mContextStack, mFilename); + mDTDDebug->Verify(this, mParser, mContextStack.mCount, mContextStack.mTags, mFilename); } }//if @@ -420,13 +519,13 @@ PRInt32 CNavDTD::HandleDefaultStartToken(CToken* aToken,eHTMLTags aChildTag,nsIP } if(IsContainer(aChildTag)){ - if(PR_TRUE==(PRBool)mLeafBits[mContextStackPos-1]) { + if(PR_TRUE==mContextStack.mBits[mContextStack.mCount-1]) { CloseTransientStyles(aChildTag); } result=OpenContainer(aNode,PR_TRUE); } else { - if(PR_FALSE==(PRBool)mLeafBits[mContextStackPos-1]) { + if(PR_FALSE==mContextStack.mBits[mContextStack.mCount-1]) { OpenTransientStyles(aChildTag); } result=AddLeaf(aNode); @@ -576,16 +675,8 @@ PRInt32 CNavDTD::HandleEndToken(CToken* aToken) { // we have to handle explicit styles the way it does. That means // that we keep an internal style stack.When an EndToken occurs, // we should see if it is an explicit style tag. If so, we can - // close AND explicit style tag (goofy, huh?) + // close the explicit style tag (goofy, huh?) -/* - if(0!=strchr(gStyleTags,tokenTagType)){ - eHTMLTags topTag=GetTopNode(); - if(0!=strchr(gStyleTags,topTag)){ - tokenTagType=topTag; - } - } -*/ //now check to see if this token should be omitted... if(PR_TRUE==CanOmitEndTag(GetTopNode(),tokenTagType)) { @@ -622,7 +713,7 @@ PRInt32 CNavDTD::HandleEndToken(CToken* aToken) { // Empty the transient style stack (we just closed any extra // ones off so it's safe to do it now) because they don't carry // forward across table cell boundaries. - mStyleStackPos = 0; + mStyleStack.mCount=0; break; default: @@ -1148,8 +1239,8 @@ PRBool CNavDTD::CanContain(PRInt32 aParent,PRInt32 aChild) { break; //singletons can't contain anything... case eHTMLTag_li: - if ((eHTMLTag_li == aChild) || - (eHTMLTag_ul == aChild) || // XXX this is temporary!!! + if ((eHTMLTag_li == aChild) || //XXX this is temporary!!! + (eHTMLTag_ul == aChild) || (eHTMLTag_ol == aChild) || (eHTMLTag_menu == aChild) || (eHTMLTag_dir == aChild)) { @@ -1620,29 +1711,6 @@ PRBool CNavDTD::BackwardPropagate(nsString& aVector,eHTMLTags aParentTag,eHTMLTa return PRBool(aParentTag==theParentTag); } -/** - * - * @update gess6/4/98 - * @param aTag is the id of the html container being opened - * @return 0 if all is well. - */ -PRInt32 CNavDTD::DidOpenContainer(eHTMLTags aTag,PRBool /*anExplicitOpen*/){ - PRInt32 result=0; - return result; -} - -/** - * - * @update gess6/4/98 - * @param - * @return - */ -PRInt32 CNavDTD::DidCloseContainer(eHTMLTags aTag,PRBool/*anExplicitClosure*/){ - PRInt32 result=0; - return result; -} - - /** * This method allows the caller to determine if a form * element is currently open. @@ -1672,9 +1740,7 @@ PRBool CNavDTD::HasOpenContainer(eHTMLTags aContainer) const { * @return tag id of topmost node in contextstack */ eHTMLTags CNavDTD::GetTopNode() const { - if(mContextStackPos) - return (eHTMLTags)(int)mContextStack[mContextStackPos-1]; - return eHTMLTag_unknown; + return mContextStack.Last(); } @@ -1688,8 +1754,8 @@ eHTMLTags CNavDTD::GetTopNode() const { */ PRInt32 CNavDTD::GetTopmostIndexOf(eHTMLTags aTag) const { int i=0; - for(i=mContextStackPos-1;i>=0;i--){ - if((eHTMLTags)(int)mContextStack[i]==aTag) + for(i=mContextStack.mCount-1;i>=0;i--){ + if(mContextStack.mTags[i]==aTag) return i; } return kNotFound; @@ -1720,8 +1786,8 @@ PRInt32 CNavDTD::OpenTransientStyles(eHTMLTags aTag){ eHTMLTags parentTag=GetTopNode(); if(CanContainStyles(parentTag)) { - for(pos=0;pos0) && (mLeafBits[mContextStackPos-1])) { + if((mStyleStack.mCount>0) && (mContextStack.mBits[mContextStack.mCount-1])) { if(0==strchr(gWhitespaceTags,aTag)){ - result=CloseContainersTo((eHTMLTags)(int)mStyleStack[0],PR_FALSE); - mLeafBits.ReplaceElementAt((void*)PR_FALSE,mContextStackPos-1); + result=CloseContainersTo(mStyleStack.mTags[0],PR_FALSE); + mContextStack.mBits[mContextStack.mCount-1]=PR_FALSE; }//if }//if @@ -1782,10 +1848,10 @@ PRInt32 CNavDTD::CloseTransientStyles(eHTMLTags aTag){ * @return TRUE if ok, FALSE if error */ PRInt32 CNavDTD::OpenHTML(const nsIParserNode& aNode){ - NS_PRECONDITION(mContextStackPos >= 0, kInvalidTagStackPos); + NS_PRECONDITION(mContextStack.mCount >= 0, kInvalidTagStackPos); PRInt32 result=mSink->OpenHTML(aNode); - mContextStack.ReplaceElementAt((void*)aNode.GetNodeType(),mContextStackPos++); + mContextStack.Push((eHTMLTags)aNode.GetNodeType()); return result; } @@ -1799,9 +1865,9 @@ PRInt32 CNavDTD::OpenHTML(const nsIParserNode& aNode){ * @return TRUE if ok, FALSE if error */ PRInt32 CNavDTD::CloseHTML(const nsIParserNode& aNode){ - NS_PRECONDITION(mContextStackPos > 0, kInvalidTagStackPos); + NS_PRECONDITION(mContextStack.mCount > 0, kInvalidTagStackPos); PRInt32 result=mSink->CloseHTML(aNode); - mContextStack.ReplaceElementAt((void*)eHTMLTag_unknown,--mContextStackPos); + mContextStack.Pop(); return result; } @@ -1815,7 +1881,7 @@ PRInt32 CNavDTD::CloseHTML(const nsIParserNode& aNode){ * @return TRUE if ok, FALSE if error */ PRInt32 CNavDTD::OpenHead(const nsIParserNode& aNode){ - mContextStack.ReplaceElementAt((void*)eHTMLTag_head,++mContextStackPos); + mContextStack.Push(eHTMLTag_head); PRInt32 result=mSink->OpenHead(aNode); return result; } @@ -1830,7 +1896,7 @@ PRInt32 CNavDTD::OpenHead(const nsIParserNode& aNode){ */ PRInt32 CNavDTD::CloseHead(const nsIParserNode& aNode){ PRInt32 result=mSink->CloseHead(aNode); - mContextStack.ReplaceElementAt((void*)eHTMLTag_unknown,--mContextStackPos); + mContextStack.Pop(); return result; } @@ -1843,7 +1909,7 @@ PRInt32 CNavDTD::CloseHead(const nsIParserNode& aNode){ * @return TRUE if ok, FALSE if error */ PRInt32 CNavDTD::OpenBody(const nsIParserNode& aNode){ - NS_PRECONDITION(mContextStackPos >= 0, kInvalidTagStackPos); + NS_PRECONDITION(mContextStack.mCount >= 0, kInvalidTagStackPos); PRInt32 result=kNoError; eHTMLTags topTag=GetTopNode(); @@ -1875,7 +1941,7 @@ PRInt32 CNavDTD::OpenBody(const nsIParserNode& aNode){ if(kNoError==result) { result=mSink->OpenBody(aNode); - mContextStack.ReplaceElementAt((void*)aNode.GetNodeType(),mContextStackPos++); + mContextStack.Push((eHTMLTags)aNode.GetNodeType()); } return result; } @@ -1889,9 +1955,9 @@ PRInt32 CNavDTD::OpenBody(const nsIParserNode& aNode){ * @return TRUE if ok, FALSE if error */ PRInt32 CNavDTD::CloseBody(const nsIParserNode& aNode){ - NS_PRECONDITION(mContextStackPos >= 0, kInvalidTagStackPos); + NS_PRECONDITION(mContextStack.mCount >= 0, kInvalidTagStackPos); PRInt32 result=mSink->CloseBody(aNode); - mContextStack.ReplaceElementAt((void*)eHTMLTag_unknown,--mContextStackPos); + mContextStack.Pop(); return result; } @@ -1980,9 +2046,9 @@ PRInt32 CNavDTD::CloseMap(const nsIParserNode& aNode){ * @return TRUE if ok, FALSE if error */ PRInt32 CNavDTD::OpenFrameset(const nsIParserNode& aNode){ - NS_PRECONDITION(mContextStackPos >= 0, kInvalidTagStackPos); + NS_PRECONDITION(mContextStack.mCount >= 0, kInvalidTagStackPos); PRInt32 result=mSink->OpenFrameset(aNode); - mContextStack.ReplaceElementAt((void*)aNode.GetNodeType(),mContextStackPos++); + mContextStack.Push((eHTMLTags)aNode.GetNodeType()); return result; } @@ -1995,9 +2061,9 @@ PRInt32 CNavDTD::OpenFrameset(const nsIParserNode& aNode){ * @return TRUE if ok, FALSE if error */ PRInt32 CNavDTD::CloseFrameset(const nsIParserNode& aNode){ - NS_PRECONDITION(mContextStackPos > 0, kInvalidTagStackPos); + NS_PRECONDITION(mContextStack.mCount > 0, kInvalidTagStackPos); PRInt32 result=mSink->CloseFrameset(aNode); - mContextStack.ReplaceElementAt((void*)eHTMLTag_unknown,--mContextStackPos); + mContextStack.Pop(); return result; } @@ -2011,7 +2077,7 @@ PRInt32 CNavDTD::CloseFrameset(const nsIParserNode& aNode){ * @return TRUE if ok, FALSE if error */ PRInt32 CNavDTD::OpenContainer(const nsIParserNode& aNode,PRBool aUpdateStyleStack){ - NS_PRECONDITION(mContextStackPos > 0, kInvalidTagStackPos); + NS_PRECONDITION(mContextStack.mCount > 0, kInvalidTagStackPos); PRInt32 result=kNoError; eHTMLTags nodeType=(eHTMLTags)aNode.GetNodeType(); @@ -2037,7 +2103,7 @@ PRInt32 CNavDTD::OpenContainer(const nsIParserNode& aNode,PRBool aUpdateStyleSta default: result=mSink->OpenContainer(aNode); - mContextStack.ReplaceElementAt((void*)nodeType,mContextStackPos++); + mContextStack.Push((eHTMLTags)aNode.GetNodeType()); break; } @@ -2057,7 +2123,7 @@ PRInt32 CNavDTD::OpenContainer(const nsIParserNode& aNode,PRBool aUpdateStyleSta * @return TRUE if ok, FALSE if error */ PRInt32 CNavDTD::CloseContainer(const nsIParserNode& aNode,eHTMLTags aTag,PRBool aUpdateStyles){ - NS_PRECONDITION(mContextStackPos > 0, kInvalidTagStackPos); + NS_PRECONDITION(mContextStack.mCount > 0, kInvalidTagStackPos); PRInt32 result=kNoError; //was false eHTMLTags nodeType=(eHTMLTags)aNode.GetNodeType(); @@ -2085,11 +2151,11 @@ PRInt32 CNavDTD::CloseContainer(const nsIParserNode& aNode,eHTMLTags aTag,PRBool case eHTMLTag_title: default: result=mSink->CloseContainer(aNode); - mContextStack.ReplaceElementAt((void*)eHTMLTag_unknown,--mContextStackPos); + mContextStack.Pop(); break; } - mLeafBits.ReplaceElementAt((void*)PR_FALSE, mContextStackPos); + mContextStack.mBits[mContextStack.mCount]=PR_FALSE; if((kNoError==result) && (PR_TRUE==aUpdateStyles)){ UpdateStyleStackForCloseTag(nodeType,aTag); } @@ -2106,15 +2172,15 @@ PRInt32 CNavDTD::CloseContainer(const nsIParserNode& aNode,eHTMLTags aTag,PRBool * @return TRUE if ok, FALSE if error */ PRInt32 CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTag,PRBool aUpdateStyles){ - NS_PRECONDITION(mContextStackPos > 0, kInvalidTagStackPos); + NS_PRECONDITION(mContextStack.mCount > 0, kInvalidTagStackPos); PRInt32 result=kNoError; CEndToken aToken(gEmpty); nsCParserNode theNode(&aToken); - if((anIndex=0)) { - while(mContextStackPos>anIndex) { - eHTMLTags theTag=(eHTMLTags)(int)mContextStack[mContextStackPos-1]; + if((anIndex=0)) { + while(mContextStack.mCount>anIndex) { + eHTMLTags theTag=mContextStack.Last(); aToken.SetTypeID(theTag); result=CloseContainer(theNode,aTag,aUpdateStyles); } @@ -2131,7 +2197,7 @@ PRInt32 CNavDTD::CloseContainersTo(PRInt32 anIndex,eHTMLTags aTag,PRBool aUpdate * @return TRUE if ok, FALSE if error */ PRInt32 CNavDTD::CloseContainersTo(eHTMLTags aTag,PRBool aUpdateStyles){ - NS_PRECONDITION(mContextStackPos > 0, kInvalidTagStackPos); + NS_PRECONDITION(mContextStack.mCount > 0, kInvalidTagStackPos); PRInt32 pos=GetTopmostIndexOf(aTag); @@ -2172,10 +2238,10 @@ PRInt32 CNavDTD::CloseContainersTo(eHTMLTags aTag,PRBool aUpdateStyles){ * @return TRUE if ok, FALSE if error */ PRInt32 CNavDTD::CloseTopmostContainer(){ - NS_PRECONDITION(mContextStackPos > 0, kInvalidTagStackPos); + NS_PRECONDITION(mContextStack.mCount > 0, kInvalidTagStackPos); CEndToken aToken(gEmpty); - eHTMLTags theTag=(eHTMLTags)(int)mContextStack[mContextStackPos-1]; + eHTMLTags theTag=mContextStack.Last(); aToken.SetTypeID(theTag); nsCParserNode theNode(&aToken); return CloseContainer(theNode,theTag,PR_TRUE); @@ -2217,7 +2283,7 @@ PRInt32 CNavDTD::CreateContextStackFor(eHTMLTags aChildTag){ //add code here to build up context stack based on forward propagated context vector... pos=0; cnt=theVector.Length()-1; - if(mContextStack[mContextStackPos-1]==(void*)theVector[cnt]) + if(mContextStack.Last()==(eHTMLTags)theVector[cnt]) result=kNoError; else result=kContextMismatch; } @@ -2236,8 +2302,8 @@ PRInt32 CNavDTD::CreateContextStackFor(eHTMLTags aChildTag){ pos=0; cnt=theVector.Length(); result=kNoError; - while(pos0) { + if(mStyleStack.mCount>0) { switch (aTag) { case eHTMLTag_a: @@ -2369,7 +2435,7 @@ PRInt32 CNavDTD::UpdateStyleStackForCloseTag(eHTMLTags aTag,eHTMLTags anActualTa case eHTMLTag_u: case eHTMLTag_var: if(aTag==anActualTag) - mStyleStack.ReplaceElementAt((void*)eHTMLTag_unknown,--mStyleStackPos); + mStyleStack.Pop(); break; case eHTMLTag_h1: case eHTMLTag_h2: @@ -2716,8 +2782,8 @@ PRInt32 CNavDTD::ConsumeToken(CToken*& aToken){ CScanner* theScanner=mParser->GetScanner(); if(kNoError==result){ - PRUnichar aChar; - result=theScanner->GetChar(aChar); + PRUnichar theChar; + result=theScanner->GetChar(theChar); switch(result) { case kEOF: break; @@ -2728,25 +2794,25 @@ PRInt32 CNavDTD::ConsumeToken(CToken*& aToken){ case kNoError: default: - switch(aChar) { + switch(theChar) { case kLessThan: - return ConsumeTag(aChar,*theScanner,aToken); + return ConsumeTag(theChar,*theScanner,aToken); case kAmpersand: - return ConsumeEntity(aChar,*theScanner,aToken); + return ConsumeEntity(theChar,*theScanner,aToken); case kCR: case kLF: - return ConsumeNewline(aChar,*theScanner,aToken); + return ConsumeNewline(theChar,*theScanner,aToken); case kNotFound: break; default: - if(!nsString::IsSpace(aChar)) { - nsAutoString temp(aChar); + if(!nsString::IsSpace(theChar)) { + nsAutoString temp(theChar); return ConsumeText(temp,*theScanner,aToken); } - return ConsumeWhitespace(aChar,*theScanner,aToken); + return ConsumeWhitespace(theChar,*theScanner,aToken); } //switch break; } //switch diff --git a/parser/htmlparser/src/CNavDTD.h b/parser/htmlparser/src/CNavDTD.h index 2ea700f9ec7..063874781d3 100644 --- a/parser/htmlparser/src/CNavDTD.h +++ b/parser/htmlparser/src/CNavDTD.h @@ -45,6 +45,54 @@ class nsIParserNode; class CITokenHandler; class nsParser; + + +/*************************************************************** + First define a helper class called CTagStack. + + Simple, we've built ourselves a little data structure that + serves as a stack for htmltags (and associated bits). + What's special is that if you #define _dynstack 1, the stack + size can grow dynamically (like you'ld want in a release build.) + If you don't #define _dynstack 1, then the stack is a fixed size, + equal to the eStackSize enum. This makes debugging easier, because + you can see the htmltags on the stack if its not dynamic. + ***************************************************************/ + +//#define _dynstack 1 +class CTagStack { + enum {eStackSize=200}; + +public: + + CTagStack(int aDefaultSize=50); + ~CTagStack(); + void Push(eHTMLTags aTag); + eHTMLTags Pop(); + eHTMLTags First() const; + eHTMLTags Last() const; + + int mSize; + int mCount; + +#ifdef _dynstack + eHTMLTags* mTags; + PRBool* mBits; +#else + eHTMLTags mTags[200]; + PRBool mBits[200]; +#endif +}; + +/*************************************************************** + Now the main event: CNavDTD. + + This not so simple class performs all the duties of token + construction and model building. It works in conjunction with + an nsParser. + ***************************************************************/ + + class CNavDTD : public nsIDTD { public: @@ -103,7 +151,7 @@ class CNavDTD : public nsIDTD { * @param * @return */ - virtual PRInt32 WillBuildModel(const char* aFilename=0); + virtual PRInt32 WillBuildModel(nsString& aFilename); /** * @@ -251,14 +299,6 @@ class CNavDTD : public nsIDTD { */ virtual PRBool BackwardPropagate(nsString& aVector,eHTMLTags aParentTag,eHTMLTags aChildTag) const; - /** - * - * @update gess6/4/98 - * @param - * @return - */ - virtual PRInt32 DidOpenContainer(eHTMLTags aTag,PRBool anExplicitOpen); - /** * Ask parser if a given container is open ANYWHERE on stack * @update gess5/11/98 @@ -283,129 +323,36 @@ class CNavDTD : public nsIDTD { */ virtual PRInt32 GetTopmostIndexOf(eHTMLTags aTag) const; - /** - * - * @update gess6/4/98 - * @param - * @return - */ - virtual PRInt32 DidCloseContainer(eHTMLTags aTag,PRBool anExplicitClosure); /** - * This method gets called when a start token has been consumed and needs - * to be handled (possibly added to content model via sink). + * The following set of methods are used to partially construct + * the content model (via the sink) according to the type of token. * @update gess5/11/98 * @param aToken is the start token to be handled * @return TRUE if the token was handled. */ PRInt32 HandleStartToken(CToken* aToken); - - /** - * This method gets called when a start token has been consumed, and - * we want to use default start token handling behavior. - * This method gets called automatically by handleStartToken. - * - * @update gess5/11/98 - * @param aToken is the start token to be handled - * @param aChildTag is the tag-type of given token - * @param aNode is a node be updated with info from given token - * @return TRUE if the token was handled. - */ PRInt32 HandleDefaultStartToken(CToken* aToken,eHTMLTags aChildTag,nsIParserNode& aNode); - - /** - * This method gets called when an end token has been consumed and needs - * to be handled (possibly added to content model via sink). - * @update gess5/11/98 - * @param aToken is the end token to be handled - * @return TRUE if the token was handled. - */ PRInt32 HandleEndToken(CToken* aToken); - - /** - * This method gets called when an entity token has been consumed and needs - * to be handled (possibly added to content model via sink). - * @update gess5/11/98 - * @param aToken is the entity token to be handled - * @return TRUE if the token was handled. - */ PRInt32 HandleEntityToken(CToken* aToken); - - /** - * This method gets called when a comment token has been consumed and needs - * to be handled (possibly added to content model via sink). - * @update gess5/11/98 - * @param aToken is the comment token to be handled - * @return TRUE if the token was handled. - */ PRInt32 HandleCommentToken(CToken* aToken); - - /** - * This method gets called when a skipped-content token has been consumed and needs - * to be handled (possibly added to content model via sink). - * @update gess5/11/98 - * @param aToken is the skipped-content token to be handled - * @return TRUE if the token was handled. - */ PRInt32 HandleSkippedContentToken(CToken* aToken); - - /** - * This method gets called when an attribute token has been consumed and needs - * to be handled (possibly added to content model via sink). - * @update gess5/11/98 - * @param aToken is the attribute token to be handled - * @return TRUE if the token was handled. - */ PRInt32 HandleAttributeToken(CToken* aToken); - - /** - * This method gets called when a script token has been consumed and needs - * to be handled (possibly added to content model via sink). - * @update gess5/11/98 - * @param aToken is the script token to be handled - * @return TRUE if the token was handled. - */ PRInt32 HandleScriptToken(CToken* aToken); - - /** - * This method gets called when a style token has been consumed and needs - * to be handled (possibly added to content model via sink). - * @update gess5/11/98 - * @param aToken is the style token to be handled - * @return TRUE if the token was handled. - */ PRInt32 HandleStyleToken(CToken* aToken); - protected: /** - * Causes token handlers to be registered for this parser. - * DO NOT CALL THIS! IT'S DEPRECATED! - * @update gess5/11/98 - */ - void InitializeDefaultTokenHandlers(); - - - /** - * DEPRECATED + * The following methods are use to create and manage + * the dynamic set of token handlers. * @update gess5/11/98 */ + void InitializeDefaultTokenHandlers(); CITokenHandler* GetTokenHandler(eHTMLTokenTypes aType) const; - - /** - * DEPRECATED - * @update gess5/11/98 - */ CITokenHandler* AddTokenHandler(CITokenHandler* aHandler); - - /** - * DEPRECATED - * @update gess5/11/98 - */ - void DeleteTokenHandlers(void); - + void DeleteTokenHandlers(void); //************************************************* @@ -414,145 +361,43 @@ protected: //************************************************* /** - * This cover method opens the given node as a HTML item in - * content sink. + * The next set of method open given HTML element. + * * @update gess5/11/98 * @param HTML (node) to be opened in content sink. * @return TRUE if all went well. */ PRInt32 OpenHTML(const nsIParserNode& aNode); - - /** - * - * @update gess5/11/98 - * @param - * @return - */ - PRInt32 CloseHTML(const nsIParserNode& aNode); - - /** - * This cover method opens the given node as a head item in - * content sink. - * @update gess5/11/98 - * @param HEAD (node) to be opened in content sink. - * @return TRUE if all went well. - */ PRInt32 OpenHead(const nsIParserNode& aNode); - - /** - * This cover method causes the content-sink head to be closed - * @update gess5/11/98 - * @param aNode is the node to be closed in sink (usually ignored) - * @return TRUE if all went well. - */ - PRInt32 CloseHead(const nsIParserNode& aNode); - - /** - * This cover method opens the given node as a body item in - * content sink. - * @update gess5/11/98 - * @param BODY (node) to be opened in content sink. - * @return TRUE if all went well. - */ PRInt32 OpenBody(const nsIParserNode& aNode); - - /** - * This cover method causes the content-sink body to be closed - * @update gess5/11/98 - * @param aNode is the body node to be closed in sink (usually ignored) - * @return TRUE if all went well. - */ - PRInt32 CloseBody(const nsIParserNode& aNode); - - /** - * This cover method opens the given node as a form item in - * content sink. - * @update gess5/11/98 - * @param FORM (node) to be opened in content sink. - * @return TRUE if all went well. - */ PRInt32 OpenForm(const nsIParserNode& aNode); - - /** - * This cover method causes the content-sink form to be closed - * @update gess5/11/98 - * @param aNode is the form node to be closed in sink (usually ignored) - * @return TRUE if all went well. - */ - PRInt32 CloseForm(const nsIParserNode& aNode); - - /** - * This cover method opens the given node as a form item in - * content sink. - * @update gess5/11/98 - * @param FORM (node) to be opened in content sink. - * @return TRUE if all went well. - */ PRInt32 OpenMap(const nsIParserNode& aNode); - - /** - * This cover method causes the content-sink form to be closed - * @update gess5/11/98 - * @param aNode is the form node to be closed in sink (usually ignored) - * @return TRUE if all went well. - */ - PRInt32 CloseMap(const nsIParserNode& aNode); - - /** - * This cover method opens the given node as a frameset item in - * content sink. - * @update gess5/11/98 - * @param FRAMESET (node) to be opened in content sink. - * @return TRUE if all went well. - */ PRInt32 OpenFrameset(const nsIParserNode& aNode); - - /** - * This cover method causes the content-sink frameset to be closed - * @update gess5/11/98 - * @param aNode is the frameeset node to be closed in sink (usually ignored) - * @return TRUE if all went well. - */ - PRInt32 CloseFrameset(const nsIParserNode& aNode); - - /** - * This cover method opens the given node as a generic container in - * content sink. - * @update gess5/11/98 - * @param generic container (node) to be opened in content sink. - * @return TRUE if all went well. - */ PRInt32 OpenContainer(const nsIParserNode& aNode,PRBool aUpdateStyleStack); /** - * This cover method causes a generic containre in the content-sink to be closed + * The next set of methods close the given HTML element. + * * @update gess5/11/98 - * @param aNode is the node to be closed in sink (usually ignored) + * @param HTML (node) to be opened in content sink. * @return TRUE if all went well. */ + PRInt32 CloseHTML(const nsIParserNode& aNode); + PRInt32 CloseHead(const nsIParserNode& aNode); + PRInt32 CloseBody(const nsIParserNode& aNode); + PRInt32 CloseForm(const nsIParserNode& aNode); + PRInt32 CloseMap(const nsIParserNode& aNode); + PRInt32 CloseFrameset(const nsIParserNode& aNode); PRInt32 CloseContainer(const nsIParserNode& aNode,eHTMLTags anActualTag,PRBool aUpdateStyles); /** - * This cover method causes the topmost container to be closed in sink + * The special purpose methods automatically close + * one or more open containers. * @update gess5/11/98 * @return TRUE if all went well. */ PRInt32 CloseTopmostContainer(); - - /** - * Cause all containers down to topmost given tag to be closed - * @update gess5/11/98 - * @param aTag is the tag at which auto-closure should stop (inclusive) - * @return TRUE if all went well -- otherwise FALSE - */ PRInt32 CloseContainersTo(eHTMLTags aTag,PRBool aUpdateStyles); - - /** - * Cause all containers down to given position to be closed - * @update gess5/11/98 - * @param anIndex is the stack pos at which auto-closure should stop (inclusive) - * @return TRUE if all went well -- otherwise FALSE - */ PRInt32 CloseContainersTo(PRInt32 anIndex,eHTMLTags aTag,PRBool aUpdateStyles); /** @@ -603,81 +448,22 @@ protected: CToken* CreateTokenOfType(eHTMLTokenTypes aType); /** - * Retrieve the next TAG from the given scanner. + * The following methods consume a particular type + * of HTML token. + * * @update gess 5/11/98 * @param aScanner is the input source * @param aToken is the next token (or null) * @return error code */ PRInt32 ConsumeTag(PRUnichar aChar,CScanner& aScanner,CToken*& aToken); - - /** - * Retrieve next START tag from given scanner. - * @update gess 5/11/98 - * @param aScanner is the input source - * @param aToken is the next token (or null) - * @return error code - */ PRInt32 ConsumeStartTag(PRUnichar aChar,CScanner& aScanner,CToken*& aToken); - - /** - * Retrieve collection of HTML/XML attributes from given scanner - * @update gess 5/11/98 - * @param aScanner is the input source - * @param aToken is the next token (or null) - * @return error code - */ PRInt32 ConsumeAttributes(PRUnichar aChar,CScanner& aScanner,CStartToken* aToken); - - /** - * Retrieve a sequence of text from given scanner. - * @update gess 5/11/98 - * @param aString will contain retrieved text. - * @param aScanner is the input source - * @param aToken is the next token (or null) - * @return error code - */ - PRInt32 ConsumeText(const nsString& aString,CScanner& aScanner,CToken*& aToken); - - /** - * Retrieve an entity from given scanner - * @update gess 5/11/98 - * @param aChar last char read from scanner - * @param aScanner is the input source - * @param aToken is the next token (or null) - * @return error code - */ PRInt32 ConsumeEntity(PRUnichar aChar,CScanner& aScanner,CToken*& aToken); - - /** - * Retrieve a whitespace sequence from the given scanner - * @update gess 5/11/98 - * @param aChar last char read from scanner - * @param aScanner is the input source - * @param aToken is the next token (or null) - * @return error code - */ PRInt32 ConsumeWhitespace(PRUnichar aChar,CScanner& aScanner,CToken*& aToken); - - /** - * Retrieve a comment from the given scanner - * @update gess 5/11/98 - * @param aChar last char read from scanner - * @param aScanner is the input source - * @param aToken is the next token (or null) - * @return error code - */ PRInt32 ConsumeComment(PRUnichar aChar,CScanner& aScanner,CToken*& aToken); - - /** - * Retrieve newlines from given scanner - * @update gess 5/11/98 - * @param aChar last char read from scanner - * @param aScanner is the input source - * @param aToken is the next token (or null) - * @return error code - */ PRInt32 ConsumeNewline(PRUnichar aChar,CScanner& aScanner,CToken*& aToken); + PRInt32 ConsumeText(const nsString& aString,CScanner& aScanner,CToken*& aToken); /** * Causes content to be skipped up to sequence contained in aString. @@ -700,16 +486,13 @@ protected: CITokenHandler* mTokenHandlers[eToken_last]; - nsVoidArray mLeafBits; - nsVoidArray mContextStack; - PRInt32 mContextStackPos; - nsVoidArray mStyleStack; - PRInt32 mStyleStackPos; + CTagStack mContextStack; + CTagStack mStyleStack; PRBool mHasOpenForm; PRBool mHasOpenMap; nsDeque mTokenDeque; - char* mFilename; + nsString mFilename; nsIDTDDebug* mDTDDebug; }; diff --git a/parser/htmlparser/src/COtherDTD.cpp b/parser/htmlparser/src/COtherDTD.cpp index 886dc88c047..a3b2b0cd572 100644 --- a/parser/htmlparser/src/COtherDTD.cpp +++ b/parser/htmlparser/src/COtherDTD.cpp @@ -178,7 +178,7 @@ eAutoDetectResult COtherDTD::AutoDetectContentType(nsString& aBuffer,nsString& a * @param * @return */ -PRInt32 COtherDTD::WillBuildModel(const char* aFilename) { +PRInt32 COtherDTD::WillBuildModel(nsString& aFilename) { return CNavDTD::WillBuildModel(aFilename); } @@ -464,25 +464,6 @@ PRBool COtherDTD::BackwardPropagate(nsString& aVector,eHTMLTags aParentTag,eHTML return CNavDTD::BackwardPropagate(aVector,aParentTag,aChildTag); } -/** - * - * @update gess6/4/98 - * @param aTag is the id of the html container being opened - * @return 0 if all is well. - */ -PRInt32 COtherDTD::DidOpenContainer(eHTMLTags aTag,PRBool anExplicitOpen){ - return CNavDTD::DidOpenContainer(aTag,anExplicitOpen); -} - -/** - * - * @update gess6/4/98 - * @param - * @return - */ -PRInt32 COtherDTD::DidCloseContainer(eHTMLTags aTag,PRBool anExplicitClosure){ - return CNavDTD::DidOpenContainer(aTag,anExplicitClosure); -} /********************************************* Here comes code that handles the interface diff --git a/parser/htmlparser/src/COtherDTD.h b/parser/htmlparser/src/COtherDTD.h index 10813045aba..488b2f26886 100644 --- a/parser/htmlparser/src/COtherDTD.h +++ b/parser/htmlparser/src/COtherDTD.h @@ -87,7 +87,7 @@ class COtherDTD : public CNavDTD { * @param * @return */ - virtual PRInt32 WillBuildModel(const char* aFilename=0); + virtual PRInt32 WillBuildModel(nsString& aString); /** * @@ -218,22 +218,6 @@ class COtherDTD : public CNavDTD { */ virtual PRBool BackwardPropagate(nsString& aVector,eHTMLTags aParentTag,eHTMLTags aChildTag) const; - /** - * - * @update gess6/4/98 - * @param - * @return - */ - virtual PRInt32 DidOpenContainer(eHTMLTags aTag,PRBool anExplicitOpen); - - /** - * - * @update gess6/4/98 - * @param - * @return - */ - virtual PRInt32 DidCloseContainer(eHTMLTags aTag,PRBool anExplicitClosure); - /** * This method gets called when a start token has been consumed and needs * to be handled (possibly added to content model via sink). diff --git a/parser/htmlparser/src/CParserContext.cpp b/parser/htmlparser/src/CParserContext.cpp new file mode 100644 index 00000000000..fae66a3d063 --- /dev/null +++ b/parser/htmlparser/src/CParserContext.cpp @@ -0,0 +1,85 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +/** + * MODULE NOTES: + * @update gess 4/1/98 + * + */ + + +#include "CParserContext.h" +#include "nsToken.h" + + +class CTokenDeallocator: public nsDequeFunctor{ +public: + virtual void* operator()(void* anObject) { + CToken* aToken = (CToken*)anObject; + delete aToken; + return 0; + } +}; + +CTokenDeallocator gTokenDeallocator; + + +CParserContext::CParserContext(CScanner* aScanner, + CParserContext* aPreviousContext, + nsIStreamObserver* aListener) : + mTokenDeque(gTokenDeallocator), + mSourceType() +{ + mScanner=aScanner; + mPrevContext=aPreviousContext; + mListener=aListener; + NS_IF_ADDREF(mListener); + mMajorIteration=mMinorIteration=-1; + mParseMode=eParseMode_unknown; + mAutoDetectStatus=eUnknownDetect; + mTransferBuffer=new char[eTransferBufferSize+1]; + mCurrentPos=0; + mMarkPos=0; + mDTD=0; +} + + +/** + * Destructor for parser context + * NOTE: DO NOT destroy the dtd here. + * @update gess7/11/98 + */ +CParserContext::~CParserContext(){ + + if(mCurrentPos) + delete mCurrentPos; + if(mMarkPos) + delete mMarkPos; + + if(mScanner) + delete mScanner; + + if(mTransferBuffer) + delete [] mTransferBuffer; + + //Remember that it's ok to simply + //ignore the DTD and the prevcontext. + +} + + diff --git a/parser/htmlparser/src/CParserContext.h b/parser/htmlparser/src/CParserContext.h new file mode 100644 index 00000000000..41da84f49f9 --- /dev/null +++ b/parser/htmlparser/src/CParserContext.h @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +/** + * MODULE NOTES: + * @update gess 4/1/98 + * + */ + +#ifndef __CParserContext +#define __CParserContext + +#include "nsIParser.h" +#include "nsDeque.h" +#include "nsParserTypes.h" +#include "nsIURL.h" +#include "nsIDTD.h" +#include "nsScanner.h" +#include "nsIStreamListener.h" + + +/** + * Note that the parser is given FULL access to all + * data in a parsercontext. Hey, that what it's for! + */ + +class CParserContext { + +public: + + enum {eTransferBufferSize=4096}; + + CParserContext( CScanner* aScanner, + CParserContext* aPreviousContext=0, + nsIStreamObserver* aListener=0); + + + ~CParserContext(); + + + PRInt32 mMajorIteration; + PRInt32 mMinorIteration; + + nsString mSourceType; + eAutoDetectResult mAutoDetectStatus; + + nsDequeIterator* mCurrentPos; + nsDequeIterator* mMarkPos; + nsDeque mTokenDeque; + CScanner* mScanner; + nsIDTD* mDTD; + + eParseMode mParseMode; + char* mTransferBuffer; + nsIStreamObserver* mListener; + + CParserContext* mPrevContext; + +}; + + + +#endif + + diff --git a/parser/htmlparser/src/CRtfDTD.cpp b/parser/htmlparser/src/CRtfDTD.cpp index 51add7383a1..8bc844274e8 100644 --- a/parser/htmlparser/src/CRtfDTD.cpp +++ b/parser/htmlparser/src/CRtfDTD.cpp @@ -251,7 +251,7 @@ eAutoDetectResult CRtfDTD::AutoDetectContentType(nsString& aBuffer,nsString& aTy * @param * @return */ -PRInt32 CRtfDTD::WillBuildModel(const char* aFilename){ +PRInt32 CRtfDTD::WillBuildModel(nsString& aFilename){ PRInt32 result=0; return result; } diff --git a/parser/htmlparser/src/CRtfDTD.h b/parser/htmlparser/src/CRtfDTD.h index dff562561a7..4f40b2f2eba 100644 --- a/parser/htmlparser/src/CRtfDTD.h +++ b/parser/htmlparser/src/CRtfDTD.h @@ -190,7 +190,7 @@ class CRtfDTD : public nsIDTD { * @param * @return */ - virtual PRInt32 WillBuildModel(const char* aFilename=0); + virtual PRInt32 WillBuildModel(nsString& aFilename); /** * diff --git a/parser/htmlparser/src/Makefile b/parser/htmlparser/src/Makefile index 8a09a69ba9d..616e7f6f6b1 100644 --- a/parser/htmlparser/src/Makefile +++ b/parser/htmlparser/src/Makefile @@ -34,6 +34,7 @@ CPPSRCS = \ nsValidDTD.cpp \ nsWellFormedDTD.cpp \ nsParser.cpp \ + CParserContext.cpp \ nsHTMLTokens.cpp \ nsHTMLTags.cpp \ prstrm.cpp \ diff --git a/parser/htmlparser/src/makefile.win b/parser/htmlparser/src/makefile.win index 68b1598facb..0b786802cb6 100644 --- a/parser/htmlparser/src/makefile.win +++ b/parser/htmlparser/src/makefile.win @@ -34,6 +34,7 @@ CPPSRCS= \ nsHTMLTags.obj \ nsHTMLTokens.obj \ nsParser.obj \ + CParserContext.obj \ nsParserNode.obj \ nsScanner.obj \ nsToken.obj \ @@ -53,6 +54,7 @@ CPP_OBJS= \ .\$(OBJDIR)\nsHTMLTags.obj \ .\$(OBJDIR)\nsHTMLTokens.obj \ .\$(OBJDIR)\nsParser.obj \ + .\$(OBJDIR)\CParserContext.obj \ .\$(OBJDIR)\nsParserNode.obj \ .\$(OBJDIR)\nsScanner.obj \ .\$(OBJDIR)\nsToken.obj \ diff --git a/parser/htmlparser/src/nsDTDDebug.cpp b/parser/htmlparser/src/nsDTDDebug.cpp index a67ad7ac475..17166904c7f 100644 --- a/parser/htmlparser/src/nsDTDDebug.cpp +++ b/parser/htmlparser/src/nsDTDDebug.cpp @@ -67,7 +67,7 @@ public: void SetVerificationDirectory(char * verify_dir); void SetRecordStatistics(PRBool bval); - PRBool Verify(nsIDTD * aDTD, nsParser * aParser, int ContextStackPos, nsVoidArray &aContextStack, char * aURLRef); + PRBool Verify(nsIDTD * aDTD, nsParser * aParser, int ContextStackPos, eHTMLTags aContextStack[], nsString& aURLRef); void DumpVectorRecord(void); // global table for storing vector statistics and the size @@ -78,8 +78,8 @@ private: char * mVerificationDir; PRBool mRecordingStatistics; - PRBool DebugRecord(char * path, char * pURLRef, char * filename); - void NoteVector(nsVoidArray & aTags,PRInt32 count, PRBool good_vector); + PRBool DebugRecord(char * path, nsString& pURLRef, char * filename); + void NoteVector(eHTMLTags aTags[],PRInt32 count, PRBool good_vector); void MakeVectorString(char * vector_string, VectorInfo * pInfo); }; @@ -188,7 +188,7 @@ void CDTDDebug::SetRecordStatistics(PRBool bval) * @return TRUE if it is already record (dont rerecord) */ -PRBool CDTDDebug::DebugRecord(char * path, char * pURLRef, char * filename) +PRBool CDTDDebug::DebugRecord(char * path, nsString& aURLRef, char * filename) { char recordPath[2048]; PRIntn oflags = 0; @@ -215,7 +215,9 @@ PRBool CDTDDebug::DebugRecord(char * path, char * pURLRef, char * filename) // vectors are stored on the format iof "URL vector filename" // where the vector contains the verification path and // the filename contains the debug source dump - sprintf(string,"%s %s %s\r\n", pURLRef, path, filename); + char buffer[513]; + aURLRef.ToCString(buffer,sizeof(buffer)-1); + sprintf(string,"%s %s %s\r\n", buffer, path, filename); // get the file size, read in the file and parse it line at // a time to check to see if we have already recorded this @@ -310,7 +312,7 @@ static int compare( const void *arg1, const void *arg2 ) * @return */ -void CDTDDebug::NoteVector(nsVoidArray & aTags,PRInt32 count, PRBool good_vector) +void CDTDDebug::NoteVector(eHTMLTags aTags[],PRInt32 count, PRBool good_vector) { // if the table doesn't exist, create it if (!mVectorInfoArray) { @@ -327,7 +329,7 @@ void CDTDDebug::NoteVector(nsVoidArray & aTags,PRInt32 count, PRBool good_vector PRBool match = PR_TRUE; for (PRInt32 j = 0; j < count; j++) - if (mVectorInfoArray[i]->vector[j] != (eHTMLTags)(int)aTags[j]) { + if (mVectorInfoArray[i]->vector[j] != aTags[j]) { match = PR_FALSE; break; } @@ -348,7 +350,7 @@ void CDTDDebug::NoteVector(nsVoidArray & aTags,PRInt32 count, PRBool good_vector pVectorInfo->good_vector = good_vector; pVectorInfo->vector = (eHTMLTags*)PR_Malloc(count*sizeof(eHTMLTags)); for (PRInt32 i = 0; i < count; i++) - pVectorInfo->vector[i] = (eHTMLTags)(int)aTags[i]; + pVectorInfo->vector[i] = aTags[i]; mVectorInfoArray[mVectorCount++] = pVectorInfo; // have we maxed out the table? grow it.. sort it.. love it. @@ -467,7 +469,7 @@ void CDTDDebug::DumpVectorRecord(void) * @return TRUE if we know how to handle it, else false */ -PRBool CDTDDebug::Verify(nsIDTD * aDTD, nsParser * aParser, int aContextStackPos, nsVoidArray &aContextStack, char * aURLRef) +PRBool CDTDDebug::Verify(nsIDTD * aDTD, nsParser * aParser, int aContextStackPos, eHTMLTags aContextStack[], nsString& aURLRef) { PRBool result=PR_TRUE; @@ -477,7 +479,7 @@ PRBool CDTDDebug::Verify(nsIDTD * aDTD, nsParser * aParser, int aContextStackPo if(aDTD && aContextStackPos>1) { for (int i = 0; i < aContextStackPos-1; i++) - if (!aDTD->CanContain((eHTMLTags)(int)aContextStack[i],(eHTMLTags)(int)aContextStack[i+1])) { + if (!aDTD->CanContain(aContextStack[i],aContextStack[i+1])) { result = PR_FALSE; break; } @@ -495,7 +497,7 @@ PRBool CDTDDebug::Verify(nsIDTD * aDTD, nsParser * aParser, int aContextStackPo int i=0; for(i=0;i -#include "nsString.h" +#include "nsstring.h" #include "nsParserTypes.h" static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); @@ -89,8 +89,8 @@ NS_IMPL_RELEASE(CHTMLContentSinkStream) * @param nsIParser** ptr to newly instantiated parser * @return NS_xxx error result */ -NS_HTMLPARS nsresult NS_New_HTML_ContentSinkStream(CHTMLContentSinkStream** aInstancePtrResult) { - CHTMLContentSinkStream* it = new CHTMLContentSinkStream(); +NS_HTMLPARS nsresult NS_New_HTML_ContentSinkStream(CHTMLContentSinkStream** aInstancePtrResult,ostream* aStream) { + CHTMLContentSinkStream* it = new CHTMLContentSinkStream(aStream); if (it == 0) { return NS_ERROR_OUT_OF_MEMORY; @@ -99,25 +99,14 @@ NS_HTMLPARS nsresult NS_New_HTML_ContentSinkStream(CHTMLContentSinkStream** aIns return it->QueryInterface(kClassIID, (void **) aInstancePtrResult); } - /** * Construct a content sink stream. * @update gess7/7/98 * @param * @return */ -CHTMLContentSinkStream::CHTMLContentSinkStream() { - mOutput=&cout; -} - -/** - * Construct a content sink stream. - * @update gess7/7/98 - * @param - * @return - */ -CHTMLContentSinkStream::CHTMLContentSinkStream(ostream& aStream) { - mOutput=&aStream; +CHTMLContentSinkStream::CHTMLContentSinkStream(ostream* aStream) { + mOutput=(0==aStream) ? &cout : aStream; } @@ -132,17 +121,6 @@ CHTMLContentSinkStream::~CHTMLContentSinkStream() { } -/** - * - * @update gess7/7/98 - * @param - * @return - */ -void CHTMLContentSinkStream::SetOutputStream(ostream& aStream) { - mOutput=&aStream; -} - - /** * * @update gess7/7/98 @@ -171,7 +149,7 @@ void WriteAttributes(const nsIParserNode& aNode,ostream& aStream) { * @param * @return */ -void OpenTagWithAttributes(const char* theTag,const nsIParserNode& aNode,int tab,ostream& aStream,PRBool aNewline) { +void OpenTagWithAttributes(const char* theTag,const nsIParserNode& aNode,int tab,ostream& aStream,bool aNewline) { int i=0; for(i=0;i -#include "nsIInputStream.h" #include "nsIParserFilter.h" #include "nsIDTDDebug.h" #include "nshtmlpars.h" @@ -47,13 +46,10 @@ static const char* kNullURL = "Error: Null URL given"; static const char* kNullFilename= "Error: Null filename given"; static const char* kNullTokenizer = "Error: Unable to construct tokenizer"; static const char* kHTMLTextContentType = "text/html"; +static nsString kUnknownFilename("unknown"); static const int gTransferBufferSize=4096; //size of the buffer used in moving data from iistream -#define DEBUG_SAVE_SOURCE_DOC 1 -#ifdef DEBUG_SAVE_SOURCE_DOC -fstream* gTempStream=0; -#endif /** @@ -84,7 +80,7 @@ public: } }; -CTokenDeallocator gTokenDeallocator; +CTokenDeallocator gTokenDeallocator2; class CDTDDeallocator: public nsDequeFunctor{ public: @@ -114,6 +110,7 @@ public: CSharedParserObjects() : mDeallocator(), mDTDDeque(mDeallocator) { } + ~CSharedParserObjects() { } @@ -141,25 +138,13 @@ CSharedParserObjects gSharedParserObjects; * @param * @return */ -nsParser::nsParser() : - mTokenDeque(gTokenDeallocator), - mSourceType(), - mTargetType() -{ +nsParser::nsParser() { NS_INIT_REFCNT(); mDTDDebug = 0; mParserFilter = 0; mObserver = 0; - mTransferBuffer=0; mSink=0; - mCurrentPos=0; - mMarkPos=0; - mParseMode=eParseMode_unknown; - mURL=0; - mDTD=0; - mScanner=0; - mTransferBuffer=new char[gTransferBufferSize+1]; - mAutoDetectStatus=eUnknownDetect; + mParserContext=0; } @@ -172,20 +157,12 @@ nsParser::nsParser() : */ nsParser::~nsParser() { NS_IF_RELEASE(mObserver); - NS_IF_RELEASE(mDTDDebug); - if(mTransferBuffer) - delete [] mTransferBuffer; - mTransferBuffer=0; +// NS_IF_RELEASE(mDTDDebug); NS_RELEASE(mSink); - if(mCurrentPos) - delete mCurrentPos; - mCurrentPos=0; - if(mScanner) - delete mScanner; - mScanner=0; - - NS_IF_RELEASE(mURL); + //don't forget to add code here to delete + //what may be several contexts... + delete mParserContext; } @@ -298,7 +275,9 @@ void nsParser::RegisterDTD(nsIDTD* aDTD){ * @return */ CScanner* nsParser::GetScanner(void){ - return mScanner; + if(mParserContext) + return mParserContext->mScanner; + return 0; } /** @@ -311,6 +290,7 @@ CScanner* nsParser::GetScanner(void){ eParseMode DetermineParseMode() { const char* theModeStr= PR_GetEnv("PARSE_MODE"); const char* other="other"; + eParseMode result=eParseMode_navigator; if(theModeStr) @@ -326,25 +306,23 @@ eParseMode DetermineParseMode() { * @param * @return */ -PRBool FindSuitableDTD( eParseMode aMode, - nsString& aSourceType, - nsString& aTargetType, - nsIDTD*& aDefaultDTD) { +PRBool FindSuitableDTD( CParserContext& aParserContext) { //Let's start by tring the defaultDTD, if one exists... - if(aDefaultDTD && (aDefaultDTD->CanParse(aSourceType,0))) + if(aParserContext.mDTD && (aParserContext.mDTD->CanParse(aParserContext.mSourceType,0))) return PR_TRUE; PRBool result=PR_FALSE; + nsDequeIterator b=gSharedParserObjects.mDTDDeque.Begin(); nsDequeIterator e=gSharedParserObjects.mDTDDeque.End(); while(bCanParse(aSourceType,0); + result=theDTD->CanParse(aParserContext.mSourceType,0); if(result){ - aDefaultDTD=theDTD; + aParserContext.mDTD=theDTD; break; } } @@ -371,22 +349,22 @@ eAutoDetectResult nsParser::AutoDetectContentType(nsString& aBuffer,nsString& aT // recognize the content in the scanner. // Somebody should say yes, or we can't continue. - //This method may change mSourceType and mDTD. - //It absolutely changes mAutoDetectStatus + //This method may change mSourceType and mParserContext->mDTD. + //It absolutely changes mParserContext->mAutoDetectStatus nsDequeIterator b=gSharedParserObjects.mDTDDeque.Begin(); nsDequeIterator e=gSharedParserObjects.mDTDDeque.End(); - mAutoDetectStatus=eUnknownDetect; - while((bmAutoDetectStatus=eUnknownDetect; + while((bmAutoDetectStatus)){ nsIDTD* theDTD=(nsIDTD*)b.GetCurrent(); if(theDTD) { - mAutoDetectStatus=theDTD->AutoDetectContentType(aBuffer,aType); + mParserContext->mAutoDetectStatus=theDTD->AutoDetectContentType(aBuffer,aType); } b++; } - return mAutoDetectStatus; + return mParserContext->mAutoDetectStatus; } @@ -401,27 +379,18 @@ eAutoDetectResult nsParser::AutoDetectContentType(nsString& aBuffer,nsString& aT * @param * @return */ -PRInt32 nsParser::WillBuildModel(const char* aFilename){ +PRInt32 nsParser::WillBuildModel(nsString& aFilename){ - mMajorIteration=-1; - mMinorIteration=-1; + mParserContext->mMajorIteration=-1; + mParserContext->mMinorIteration=-1; - mParseMode=DetermineParseMode(); - if(PR_TRUE==FindSuitableDTD(mParseMode,mSourceType,mTargetType,mDTD)) { - mDTD->SetParser(this); - mDTD->SetContentSink(mSink); - mDTD->WillBuildModel(aFilename); + mParserContext->mParseMode=DetermineParseMode(); + if(PR_TRUE==FindSuitableDTD(*mParserContext)) { + mParserContext->mDTD->SetParser(this); + mParserContext->mDTD->SetContentSink(mSink); + mParserContext->mDTD->WillBuildModel(aFilename); } -#ifdef DEBUG_SAVE_SOURCE_DOC -#if defined(XP_UNIX) && (defined(IRIX) || defined(MKLINUX)) - /* XXX: IRIX does not support ios::binary */ - gTempStream =new fstream("/tmp/out.html",ios::out); -#else - gTempStream = new fstream("c:/temp/out.html",ios::out|ios::binary); -#endif -#endif - return kNoError; } @@ -434,18 +403,10 @@ PRInt32 nsParser::WillBuildModel(const char* aFilename){ PRInt32 nsParser::DidBuildModel(PRInt32 anErrorCode) { //One last thing...close any open containers. PRInt32 result=anErrorCode; - if(mDTD) { - result=mDTD->DidBuildModel(anErrorCode); + if(mParserContext->mDTD) { + result=mParserContext->mDTD->DidBuildModel(anErrorCode); } -#ifdef DEBUG_SAVE_SOURCE_DOC - if(gTempStream) { - gTempStream->close(); - delete gTempStream; - gTempStream=0; - } -#endif - return result; } @@ -460,22 +421,21 @@ PRInt32 nsParser::DidBuildModel(PRInt32 anErrorCode) { * @param aFilename -- const char* containing file to be parsed. * @return PR_TRUE if parse succeeded, PR_FALSE otherwise. */ -PRBool nsParser::Parse(const char* aFilename){ - NS_PRECONDITION(0!=aFilename,kNullFilename); +PRInt32 nsParser::Parse(nsString& aFilename){ PRInt32 status=kBadFilename; if(aFilename) { //ok, time to create our tokenizer and begin the process - mTargetType=kHTMLTextContentType; - mScanner=new CScanner(aFilename,mParseMode); - if(mScanner) { - mScanner->Eof(); - if(eValidDetect==AutoDetectContentType(mScanner->GetBuffer(),mSourceType)) { - WillBuildModel(aFilename); - status=ResumeParse(); - DidBuildModel(status); - } + + mParserContext = new CParserContext(new CScanner(aFilename),mParserContext); + mParserContext->mScanner->Eof(); + if(eValidDetect==AutoDetectContentType(mParserContext->mScanner->GetBuffer(), + mParserContext->mSourceType)) + { + WillBuildModel(aFilename); + status=ResumeParse(); + DidBuildModel(status); } //if } return status; @@ -488,11 +448,35 @@ PRBool nsParser::Parse(const char* aFilename){ * @return TRUE if all went well -- FALSE otherwise */ PRInt32 nsParser::Parse(fstream& aStream){ - PRInt32 result=0; - return result; + + PRInt32 status=kNoError; + + //ok, time to create our tokenizer and begin the process + mParserContext = new CParserContext(new CScanner(kUnknownFilename,aStream,PR_FALSE),mParserContext); + + mParserContext->mScanner->Eof(); + if(eValidDetect==AutoDetectContentType(mParserContext->mScanner->GetBuffer(), + mParserContext->mSourceType)) { + WillBuildModel(mParserContext->mScanner->GetFilename()); + status=ResumeParse(); + DidBuildModel(status); + } //if + + return status; } +/** + * + * @update gess7/13/98 + * @param + * @return + */ +PRInt32 nsParser::Parse(nsIInputStream* pIStream,nsIStreamObserver* aListener,nsIDTDDebug* aDTDDebug){ + PRInt32 result=kNoError; + return result; +} + /** * This is the main controlling routine in the parsing process. * Note that it may get called multiple times for the same scanner, @@ -512,19 +496,14 @@ PRInt32 nsParser::Parse(nsIURL* aURL,nsIStreamObserver* aListener, nsIDTDDebug * PRInt32 status=kBadURL; +/* Disable DTD Debug for now... mDTDDebug = aDTDDebug; NS_IF_ADDREF(mDTDDebug); - - NS_IF_RELEASE(mURL); - mURL = aURL; - NS_IF_ADDREF(mURL); - - NS_IF_RELEASE(mObserver); - mObserver = aListener; - NS_IF_ADDREF(mObserver); +*/ - if(mURL) { - mScanner=new CScanner(mParseMode); + if(aURL) { + nsAutoString theName(aURL->GetSpec()); + mParserContext=new CParserContext(new CScanner(theName,PR_FALSE),mParserContext,aListener); status=NS_OK; } return status; @@ -533,6 +512,8 @@ PRInt32 nsParser::Parse(nsIURL* aURL,nsIStreamObserver* aListener, nsIDTDDebug * /** * Call this method if all you want to do is parse 1 string full of HTML text. + * In particular, this method should be called by the DOM when it has an HTML + * string to feed to the parser in real-time. * * @update gess5/11/98 * @param anHTMLString contains a string-full of real HTML @@ -542,11 +523,10 @@ PRInt32 nsParser::Parse(nsIURL* aURL,nsIStreamObserver* aListener, nsIDTDDebug * PRInt32 nsParser::Parse(nsString& aSourceBuffer,PRBool appendTokens){ PRInt32 result=kNoError; - mTargetType=kHTMLTextContentType; - mScanner=new CScanner(); - mScanner->Append(aSourceBuffer); - if(eValidDetect==AutoDetectContentType(aSourceBuffer,mSourceType)) { - WillBuildModel(""); + mParserContext = new CParserContext(new CScanner(kUnknownFilename),mParserContext,0); + mParserContext->mScanner->Append(aSourceBuffer); + if(eValidDetect==AutoDetectContentType(aSourceBuffer,mParserContext->mSourceType)) { + WillBuildModel(mParserContext->mScanner->GetFilename()); result=ResumeParse(); DidBuildModel(result); } @@ -567,12 +547,12 @@ PRInt32 nsParser::Parse(nsString& aSourceBuffer,PRBool appendTokens){ PRInt32 nsParser::ResumeParse() { PRInt32 result=kNoError; - mDTD->WillResumeParse(); + mParserContext->mDTD->WillResumeParse(); if(kNoError==result) { result=Tokenize(); if(kInterrupted==result) - mDTD->WillInterruptParse(); - IterateTokens(); + mParserContext->mDTD->WillInterruptParse(); + BuildModel(); } return result; } @@ -585,26 +565,28 @@ PRInt32 nsParser::ResumeParse() { * @param * @return PR_TRUE if parse succeeded, PR_FALSE otherwise. */ -PRInt32 nsParser::IterateTokens() { - nsDequeIterator e=mTokenDeque.End(); +PRInt32 nsParser::BuildModel() { + + nsDequeIterator e=mParserContext->mTokenDeque.End(); nsDequeIterator theMarkPos(e); - mMajorIteration++; - if(!mCurrentPos) - mCurrentPos=new nsDequeIterator(mTokenDeque.Begin()); +// mParserContext->mMajorIteration++; + + if(!mParserContext->mCurrentPos) + mParserContext->mCurrentPos=new nsDequeIterator(mParserContext->mTokenDeque.Begin()); PRInt32 result=kNoError; - while((kNoError==result) && ((*mCurrentPosGetCurrent(); + while((kNoError==result) && ((*mParserContext->mCurrentPosmMinorIteration++; + CToken* theToken=(CToken*)mParserContext->mCurrentPos->GetCurrent(); - theMarkPos=*mCurrentPos; - result=mDTD->HandleToken(theToken); - ++(*mCurrentPos); + theMarkPos=*mParserContext->mCurrentPos; + result=mParserContext->mDTD->HandleToken(theToken); + ++(*mParserContext->mCurrentPos); } if(kInterrupted==result) - *mCurrentPos=theMarkPos; + *mParserContext->mCurrentPos=theMarkPos; return result; } @@ -619,17 +601,17 @@ PRInt32 nsParser::IterateTokens() { * @return error code (should be 0) */ PRInt32 nsParser::CollectAttributes(nsCParserNode& aNode,PRInt32 aCount){ - nsDequeIterator end=mTokenDeque.End(); + nsDequeIterator end=mParserContext->mTokenDeque.End(); int attr=0; for(attr=0;attrmCurrentPosmCurrentPos)); if(tkn){ if(eToken_attribute==eHTMLTokenTypes(tkn->GetTokenType())){ aNode.AddAttribute(tkn); } - else (*mCurrentPos)--; + else (*mParserContext->mCurrentPos)--; } else return kInterrupted; } @@ -649,18 +631,18 @@ PRInt32 nsParser::CollectAttributes(nsCParserNode& aNode,PRInt32 aCount){ */ PRInt32 nsParser::CollectSkippedContent(nsCParserNode& aNode,PRInt32& aCount) { eHTMLTokenTypes subtype=eToken_attribute; - nsDequeIterator end=mTokenDeque.End(); + nsDequeIterator end=mParserContext->mTokenDeque.End(); PRInt32 result=kNoError; aCount=0; - while((*mCurrentPos!=end) && (eToken_attribute==subtype)) { - CToken* tkn=(CToken*)(++(*mCurrentPos)); + while((*mParserContext->mCurrentPos!=end) && (eToken_attribute==subtype)) { + CToken* tkn=(CToken*)(++(*mParserContext->mCurrentPos)); subtype=eHTMLTokenTypes(tkn->GetTokenType()); if(eToken_skippedcontent==subtype) { aNode.SetSkippedContent(tkn); aCount++; } - else (*mCurrentPos)--; + else (*mParserContext->mCurrentPos)--; } return result; } @@ -710,10 +692,9 @@ nsresult nsParser::OnStartBinding(const char *aSourceType){ if (nsnull != mObserver) { mObserver->OnStartBinding(aSourceType); } - mAutoDetectStatus=eUnknownDetect; - mDTD=0; - - mSourceType=aSourceType; + mParserContext->mAutoDetectStatus=eUnknownDetect; + mParserContext->mDTD=0; + mParserContext->mSourceType=aSourceType; return kNoError; } @@ -732,37 +713,33 @@ nsresult nsParser::OnDataAvailable(nsIInputStream *pIStream, PRInt32 length){ mListener->OnDataAvailable(pIStream, length); } */ - int len=0; - int offset=0; - if(eInvalidDetect==mAutoDetectStatus) { - if(mScanner) { - mScanner->GetBuffer().Truncate(); + if(eInvalidDetect==mParserContext->mAutoDetectStatus) { + if(mParserContext->mScanner) { + mParserContext->mScanner->GetBuffer().Truncate(); } } - do { - PRInt32 err; - len = pIStream->Read(&err, mTransferBuffer, 0, gTransferBufferSize); - if(len>0) { + int len=1; //init to a non-zero value + int err; + int offset=0; - #ifdef DEBUG_SAVE_SOURCE_DOC - if(gTempStream) { - gTempStream->write(mTransferBuffer,len); - } - #endif + while (len > 0) { + len = pIStream->Read(&err, mParserContext->mTransferBuffer, 0, mParserContext->eTransferBufferSize); + if(len>0) { - if (mParserFilter) - mParserFilter->RawBuffer(mTransferBuffer, &len); - mScanner->Append(mTransferBuffer,len); + if(mParserFilter) + mParserFilter->RawBuffer(mParserContext->mTransferBuffer, &len); - if(eUnknownDetect==mAutoDetectStatus) { - if(eValidDetect==AutoDetectContentType(mScanner->GetBuffer(),mSourceType)) { - nsresult result=WillBuildModel(mURL->GetSpec()); - } //if - } - } //if - } while (len > 0); + mParserContext->mScanner->Append(mParserContext->mTransferBuffer,len); + + if(eUnknownDetect==mParserContext->mAutoDetectStatus) { + if(eValidDetect==AutoDetectContentType(mParserContext->mScanner->GetBuffer(),mParserContext->mSourceType)) { + nsresult result=WillBuildModel(mParserContext->mScanner->GetFilename()); + } //if + } + } //if + } nsresult result=ResumeParse(); return result; @@ -797,7 +774,7 @@ nsresult nsParser::OnStopBinding(PRInt32 status, const nsString& aMsg){ * @return new token or null */ PRInt32 nsParser::ConsumeToken(CToken*& aToken) { - PRInt32 result=mDTD->ConsumeToken(aToken); + PRInt32 result=mParserContext->mDTD->ConsumeToken(aToken); return result; } @@ -811,39 +788,11 @@ PRInt32 nsParser::ConsumeToken(CToken*& aToken) { * @param * @return TRUE if it's ok to proceed */ -PRBool nsParser::WillTokenize(void){ +PRBool nsParser::WillTokenize(){ PRBool result=PR_TRUE; return result; } -/** - * - * @update gess 3/25/98 - * @return TRUE if it's ok to proceed - */ -PRInt32 nsParser::Tokenize(nsString& aSourceBuffer,PRBool appendTokens){ - CToken* theToken=0; - PRInt32 result=kNoError; - PRInt32 debugCounter=0; //this can be removed. It's only for debugging... - - WillTokenize(); - - while(kNoError==result) { - debugCounter++; - result=ConsumeToken(theToken); - if(theToken && (kNoError==result)) { - -#ifdef VERBOSE_DEBUG - theToken->DebugDumpToken(cout); -#endif - mTokenDeque.Push(theToken); - } - } - if(kEOF==result) - result=kNoError; - DidTokenize(); - return result; -} /** * This is the primary control routine. It iteratively @@ -853,14 +802,14 @@ PRInt32 nsParser::Tokenize(nsString& aSourceBuffer,PRBool appendTokens){ * @update gess 3/25/98 * @return error code */ -PRInt32 nsParser::Tokenize(void) { +PRInt32 nsParser::Tokenize(){ CToken* theToken=0; PRInt32 result=kNoError; - PRBool done=(0==mMajorIteration) ? (!WillTokenize()) : PR_FALSE; + PRBool done=(0==++mParserContext->mMajorIteration) ? (!WillTokenize()) : PR_FALSE; while((PR_FALSE==done) && (kNoError==result)) { - mScanner->Mark(); + mParserContext->mScanner->Mark(); result=ConsumeToken(theToken); if(kNoError==result) { if(theToken) { @@ -868,14 +817,14 @@ PRInt32 nsParser::Tokenize(void) { #ifdef VERBOSE_DEBUG theToken->DebugDumpToken(cout); #endif - mTokenDeque.Push(theToken); + mParserContext->mTokenDeque.Push(theToken); } } else { if(theToken) delete theToken; - mScanner->RewindToMark(); + mParserContext->mScanner->RewindToMark(); } } if((PR_TRUE==done) && (kInterrupted!=result)) @@ -892,7 +841,7 @@ PRInt32 nsParser::Tokenize(void) { * @param * @return TRUE if all went well */ -PRBool nsParser::DidTokenize(void) { +PRBool nsParser::DidTokenize(){ PRBool result=PR_TRUE; #ifdef VERBOSE_DEBUG @@ -912,8 +861,8 @@ PRBool nsParser::DidTokenize(void) { * @return */ void nsParser::DebugDumpTokens(ostream& out) { - nsDequeIterator b=mTokenDeque.Begin(); - nsDequeIterator e=mTokenDeque.End(); + nsDequeIterator b=mParserContext->mTokenDeque.Begin(); + nsDequeIterator e=mParserContext->mTokenDeque.End(); CToken* theToken; while(b!=e) { @@ -933,8 +882,8 @@ void nsParser::DebugDumpTokens(ostream& out) { * @return */ void nsParser::DebugDumpSource(ostream& out) { - nsDequeIterator b=mTokenDeque.Begin(); - nsDequeIterator e=mTokenDeque.End(); + nsDequeIterator b=mParserContext->mTokenDeque.Begin(); + nsDequeIterator e=mParserContext->mTokenDeque.End(); CToken* theToken; while(b!=e) { diff --git a/parser/htmlparser/src/nsParser.h b/parser/htmlparser/src/nsParser.h index 8fdf384dba1..2f59c0b3abc 100644 --- a/parser/htmlparser/src/nsParser.h +++ b/parser/htmlparser/src/nsParser.h @@ -60,7 +60,7 @@ #include "nsParserNode.h" #include "nsParserTypes.h" #include "nsIURL.h" - +#include "CParserContext.h" #define NS_PARSER_IID \ {0x2ce606b0, 0xbee6, 0x11d1, \ @@ -69,7 +69,6 @@ class IContentSink; class nsIHTMLContentSink; -class nsIURL; class nsIDTD; class nsIDTDDebug; class CScanner; @@ -119,14 +118,26 @@ friend class CTokenHandler; virtual CScanner* GetScanner(void); /** - * Cause parser to parse input from given URL in given mode + * Cause parser to parse input from given URL * @update gess5/11/98 * @param aURL is a descriptor for source document * @param aListener is a listener to forward notifications to * @return TRUE if all went well -- FALSE otherwise */ virtual PRInt32 Parse(nsIURL* aURL, - nsIStreamObserver* aListener, nsIDTDDebug * aDTDDebug = 0); + nsIStreamObserver* aListener, + nsIDTDDebug* aDTDDebug = 0); + + /** + * Cause parser to parse input from given nsIInputStream + * @update gess5/11/98 + * @param pIStream is an nsIInputStream + * @param aListener is a listener to forward notifications to + * @return TRUE if all went well -- FALSE otherwise + */ + virtual PRInt32 Parse(nsIInputStream* pIStream, + nsIStreamObserver* aListener, + nsIDTDDebug* aDTDDebug = 0); /** * Cause parser to parse input from given file in given mode @@ -134,7 +145,7 @@ friend class CTokenHandler; * @param aFilename is a path for file document * @return TRUE if all went well -- FALSE otherwise */ - virtual PRInt32 Parse(const char* aFilename); + virtual PRInt32 Parse(nsString& aFilename); /** * Cause parser to parse input from given stream @@ -157,7 +168,7 @@ friend class CTokenHandler; * @update gess5/11/98 * @return TRUE if all went well, otherwise FALSE */ - virtual PRInt32 ResumeParse(void); + virtual PRInt32 ResumeParse(); /** * Causes the parser to scan foward, collecting nearby (sequential) @@ -208,7 +219,7 @@ protected: * @param * @return */ - PRInt32 WillBuildModel(const char* aFilename=0); + PRInt32 WillBuildModel(nsString& aFilename); /** * @@ -224,7 +235,7 @@ protected: * @update gess5/11/98 * @return YES if model building went well -- NO otherwise. */ - virtual PRInt32 IterateTokens(void); + virtual PRInt32 BuildModel(void); private: @@ -251,15 +262,9 @@ private: * @param * @return TRUE if it's ok to proceed */ - PRBool WillTokenize(void); - - /** - * - * @update gess 3/25/98 - * @return TRUE if it's ok to proceed - */ - PRInt32 Tokenize(nsString& aSourceBuffer,PRBool appendTokens); + PRBool WillTokenize(); + /** * This is the primary control routine. It iteratively * consumes tokens until an error occurs or you run out @@ -268,7 +273,7 @@ private: * @update gess 3/25/98 * @return error code */ - PRInt32 Tokenize(void); + PRInt32 Tokenize(); /** * This is the tail-end of the code sandwich for the @@ -279,7 +284,7 @@ private: * @param * @return TRUE if all went well */ - PRBool DidTokenize(void); + PRBool DidTokenize(); /** * This debug routine is used to cause the tokenizer to @@ -311,27 +316,42 @@ protected: // And now, some data members... //********************************************* - nsIStreamObserver* mObserver; - nsIContentSink* mSink; - nsIParserFilter* mParserFilter; - - nsDequeIterator* mCurrentPos; - nsDequeIterator* mMarkPos; - - nsIDTD* mDTD; - eParseMode mParseMode; - char* mTransferBuffer; + /***************************************************** + All of these moved into the parse-context object: PRInt32 mMajorIteration; PRInt32 mMinorIteration; - nsDeque mTokenDeque; - CScanner* mScanner; nsIURL* mURL; - nsIDTDDebug* mDTDDebug; nsString mSourceType; nsString mTargetType; eAutoDetectResult mAutoDetectStatus; + + nsDequeIterator* mCurrentPos; + nsDequeIterator* mMarkPos; + nsDeque mTokenDeque; + CScanner* mScanner; + nsIDTD* mDTD; + + eParseMode mParseMode; + char* mTransferBuffer; + *****************************************************/ + + CParserContext* mParserContext; + + /***************************************************** + The above fields are moving into parse-context + *****************************************************/ + + + nsIStreamObserver* mObserver; + nsIContentSink* mSink; + nsIParserFilter* mParserFilter; + + + nsIDTDDebug* mDTDDebug; + + }; diff --git a/parser/htmlparser/src/nsScanner.cpp b/parser/htmlparser/src/nsScanner.cpp index 6e38c26f645..7a9118a1fbc 100644 --- a/parser/htmlparser/src/nsScanner.cpp +++ b/parser/htmlparser/src/nsScanner.cpp @@ -19,10 +19,8 @@ //#define __INCREMENTAL 1 #include "nsScanner.h" -#include "nsIURL.h" #include "nsDebug.h" -const char* gURLRef=0; const char* kBadHTMLText="

Oops...

You just tried to read a non-existent document:
"; #ifdef __INCREMENTAL @@ -31,89 +29,55 @@ const int kBufsize=1; const int kBufsize=64; #endif + /** - * Use this constructor if you want an incremental (callback) - * based input stream. + * Use this constructor if you want i/o to be based on an + * incremental netstream. If you pass a null filename, you + * can still provide data to the scanner via append. * * @update gess 5/12/98 - * @param aMode represents the parser mode (nav, other) + * @param aFilename -- * @return */ -CScanner::CScanner(eParseMode aMode) : mBuffer("") { +CScanner::CScanner(nsString& aFilename,PRBool aCreateStream) : + mBuffer(""), mFilename(aFilename) +{ mOffset=0; mMarkPos=-1; mTotalRead=0; - mParseMode=aMode; - mNetStream=0; + mOwnsStream=aCreateStream; mFileStream=0; - mIncremental=PR_TRUE; - mOwnsStream=PR_TRUE; + if(aCreateStream) { + char buffer[513]; + aFilename.ToCString(buffer,sizeof(buffer)-1); + #if defined(XP_UNIX) && (defined(IRIX) || defined(MKLINUX)) + /* XXX: IRIX does not support ios::binary */ + mFileStream=new fstream(buffer,ios::in); + #else + mFileStream=new fstream(buffer,ios::in|ios::binary); + #endif + } //if } /** - * Use this constructor if you want i/o to be file based. + * Use this constructor if you want i/o to be stream based. * * @update gess 5/12/98 - * @param aMode represents the parser mode (nav, other) + * @param aStream -- + * @param assumeOwnership -- + * @param aFilename -- * @return */ -CScanner::CScanner(const char* aFilename,eParseMode aMode) : mBuffer("") { - NS_ASSERTION(0!=aFilename,"Error: Null filename!"); +CScanner::CScanner(nsString& aFilename,fstream& aStream,PRBool assumeOwnership) : + mBuffer(""), mFilename(aFilename) +{ mOffset=0; mMarkPos=-1; mTotalRead=0; - mParseMode=aMode; - mNetStream=0; - mIncremental=PR_FALSE; - mOwnsStream=PR_TRUE; -#if defined(XP_UNIX) && (defined(IRIX) || defined(MKLINUX)) - /* XXX: IRIX does not support ios::binary */ - mFileStream=new fstream(aFilename,ios::in); -#else - mFileStream=new fstream(aFilename,ios::in|ios::binary); -#endif -} - -/** - * Use this constructor if you want i/o to be file based. - * - * @update gess 5/12/98 - * @param aMode represents the parser mode (nav, other) - * @return - */ -CScanner::CScanner(fstream& aStream,eParseMode aMode) : mBuffer("") { - mOffset=0; - mMarkPos=-1; - mTotalRead=0; - mParseMode=aMode; - mNetStream=0; - mIncremental=PR_FALSE; - mOwnsStream=PR_FALSE; + mOwnsStream=assumeOwnership; mFileStream=&aStream; } -/** - * Use this constructor if you want i/o to be based on a - * non-incremental netstream. - * - * @update gess 5/12/98 - * @param aMode represents the parser mode (nav, other) - * @return - */ -CScanner::CScanner(nsIURL* aURL,eParseMode aMode) : mBuffer("") { - NS_ASSERTION(0!=aURL,"Error: Null URL!"); - mOffset=0; - mMarkPos=-1; - mTotalRead=0; - mParseMode=aMode; - mFileStream=0; - PRInt32 error=0; - mIncremental=PR_FALSE; - mNetStream=aURL->Open(&error); - gURLRef=aURL->GetSpec(); - mOwnsStream=PR_FALSE; -} - /** * default destructor @@ -128,13 +92,7 @@ CScanner::~CScanner() { if(mOwnsStream) delete mFileStream; } - else if(mNetStream) { - mNetStream->Close(); - mNetStream->Release(); - } mFileStream=0; - mNetStream=0; - gURLRef=0; } /** @@ -200,34 +158,9 @@ void _PreCompressBuffer(nsString& aBuffer,PRInt32& anOffset,PRInt32& aMarkPos){ } -/** - * This method should only be called by the parser when - * we're doing incremental i/o over the net. - * - * @update gess 5/12/98 - * @param aBuffer contains next blob of i/o data - * @param aSize contains size of buffer - * @return 0 if all went well, otherwise error code. - */ -PRInt32 CScanner::IncrementalAppend(const char* aBuffer,PRInt32 aSize){ - NS_ASSERTION(((!mFileStream) && (!mNetStream)),"Error: Should only be called during incremental net i/o!"); - - PRInt32 result=0; - if((!mFileStream) && (!mNetStream)) { - - _PreCompressBuffer(mBuffer,mOffset,mMarkPos); - - //now that the buffer is (possibly) shortened, let's append the new data. - if(0read(buf,kBufsize); numread=mFileStream->gcount(); } - else if(mNetStream) { - numread=mNetStream->Read(&anError,buf,0,kBufsize); - if(1==anError) - anError=kEOF; - } mOffset=mBuffer.Length(); if((0=mBuffer.Length()) { - if(!mIncremental) - theError=FillBuffer(); - else return kInterrupted; + theError=FillBuffer(); } if(0==theError) @@ -451,21 +378,21 @@ PRInt32 CScanner::SkipPast(nsString& aValidSet){ * @return error code */ PRInt32 CScanner::ReadWhile(nsString& aString,nsString& aValidSet,PRBool addTerminal){ - PRUnichar ch=0; + PRUnichar theChar=0; PRInt32 result=kNoError; PRInt32 wrPos=0; while(kNoError==result) { - result=GetChar(ch); + result=GetChar(theChar); if(kNoError==result) { - PRInt32 pos=aValidSet.Find(ch); + PRInt32 pos=aValidSet.Find(theChar); if(kNotFound==pos) { if(addTerminal) - aString+=ch; - else PutBack(ch); + aString+=theChar; + else PutBack(theChar); break; } - else aString+=ch; + else aString+=theChar; } } return result; @@ -535,6 +462,18 @@ nsString& CScanner::GetBuffer(void) { return mBuffer; } +/** + * Retrieve the name of the file that the scanner is reading from. + * In some cases, it's just a given name, because the scanner isn't + * really reading from a file. + * + * @update gess 5/12/98 + * @return + */ +nsString& CScanner::GetFilename(void) { + return mFilename; +} + /** * Conduct self test. Actually, selftesting for this class * occurs in the parser selftest. diff --git a/parser/htmlparser/src/nsScanner.h b/parser/htmlparser/src/nsScanner.h index d03b9bfb2f8..627a7f27fe1 100644 --- a/parser/htmlparser/src/nsScanner.h +++ b/parser/htmlparser/src/nsScanner.h @@ -35,43 +35,21 @@ #include "nsString.h" #include "nsParserTypes.h" #include "prtypes.h" -#include "nsIInputStream.h" #include -class nsIURL; -//class ifstream; class CScanner { public: /** - * Use this constructor if you want an incremental (callback) - * based input stream. + * Use this constructor if you want i/o to be based on + * a file (therefore a stream) or just data you provide via Append(). * * @update gess 5/12/98 * @param aMode represents the parser mode (nav, other) * @return */ - CScanner(eParseMode aMode=eParseMode_navigator); - - /** - * Use this constructor if you want i/o to be based on a - * non-incremental netstream. - * - * @update gess 5/12/98 - * @param aMode represents the parser mode (nav, other) - * @return - */ - CScanner(nsIURL* aURL,eParseMode aMode=eParseMode_navigator); - - /** - * Use this constructor if you want i/o to be file based. - * - * @update gess 5/12/98 - * @param aMode represents the parser mode (nav, other) - * @return - */ - CScanner(const char* aFilename,eParseMode aMode=eParseMode_navigator); + CScanner(nsString& aFilename,PRBool aCreateStream=PR_TRUE); /** * Use this constructor if you want i/o to be stream based. @@ -80,7 +58,7 @@ class CScanner { * @param aMode represents the parser mode (nav, other) * @return */ - CScanner(fstream& aStream,eParseMode aMode=eParseMode_navigator); + CScanner(nsString& aFilename,fstream& aStream,PRBool assumeOwnership=PR_TRUE); ~CScanner(); @@ -241,16 +219,17 @@ class CScanner { * @param * @return */ - PRInt32 IncrementalAppend(const char* aBuffer,PRInt32 aSize); + nsString& GetBuffer(void); /** - * + * Retrieve the name of the file that the scanner is reading from. + * In some cases, it's just a given name, because the scanner isn't + * really reading from a file. * * @update gess 5/12/98 - * @param * @return */ - nsString& GetBuffer(void); + nsString& GetFilename(void); static void SelfTest(); @@ -268,13 +247,11 @@ class CScanner { fstream* mFileStream; - nsIInputStream* mNetStream; nsString mBuffer; + nsString mFilename; PRInt32 mOffset; PRInt32 mMarkPos; PRInt32 mTotalRead; - eParseMode mParseMode; - PRBool mIncremental; PRBool mOwnsStream; }; diff --git a/parser/htmlparser/src/nsValidDTD.cpp b/parser/htmlparser/src/nsValidDTD.cpp index 979a78bd12b..95874180e58 100644 --- a/parser/htmlparser/src/nsValidDTD.cpp +++ b/parser/htmlparser/src/nsValidDTD.cpp @@ -190,7 +190,7 @@ eAutoDetectResult CValidDTD::AutoDetectContentType(nsString& aBuffer,nsString& a * @param * @return */ -PRInt32 CValidDTD::WillBuildModel(const char* aFilename){ +PRInt32 CValidDTD::WillBuildModel(nsString& aFilename){ PRInt32 result=0; return result; } diff --git a/parser/htmlparser/src/nsValidDTD.h b/parser/htmlparser/src/nsValidDTD.h index c0798370091..24bfc89a38a 100644 --- a/parser/htmlparser/src/nsValidDTD.h +++ b/parser/htmlparser/src/nsValidDTD.h @@ -108,7 +108,7 @@ class CValidDTD : public nsIDTD { * @param * @return */ - virtual PRInt32 WillBuildModel(const char* aFilename=0); + virtual PRInt32 WillBuildModel(nsString& aFilename); /** * diff --git a/parser/htmlparser/src/nsWellFormedDTD.cpp b/parser/htmlparser/src/nsWellFormedDTD.cpp index d092ed0e9ec..8137c3299b9 100644 --- a/parser/htmlparser/src/nsWellFormedDTD.cpp +++ b/parser/htmlparser/src/nsWellFormedDTD.cpp @@ -177,7 +177,7 @@ eAutoDetectResult CWellFormedDTD::AutoDetectContentType(nsString& aBuffer,nsStri * @param * @return */ -PRInt32 CWellFormedDTD::WillBuildModel(const char* aFilename){ +PRInt32 CWellFormedDTD::WillBuildModel(nsString& aFilename){ PRInt32 result=0; return result; } diff --git a/parser/htmlparser/src/nsWellFormedDTD.h b/parser/htmlparser/src/nsWellFormedDTD.h index 6add8b9a5b5..47155413f68 100644 --- a/parser/htmlparser/src/nsWellFormedDTD.h +++ b/parser/htmlparser/src/nsWellFormedDTD.h @@ -97,7 +97,7 @@ class CWellFormedDTD : public nsIDTD { * @param * @return */ - virtual PRInt32 WillBuildModel(const char* aFilename=0); + virtual PRInt32 WillBuildModel(nsString& aFilename); /** *