WIP for token reduction and a few bug fixes
git-svn-id: svn://10.0.0.236/trunk@7298 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
parent
6355c16731
commit
8f5813c0a2
@ -208,25 +208,28 @@ eHTMLTags CTagStack::Last() const {
|
||||
return eHTMLTag_unknown;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************
|
||||
Now define the tokenrecycler class...
|
||||
**************************************************************/
|
||||
|
||||
/************************************************************************
|
||||
CTokenFactory class implementation.
|
||||
This class is used to create and destroy our tokens.
|
||||
CTokenRecycler class implementation.
|
||||
This class is used to recycle tokens.
|
||||
By using this simple class, we cut WAY down on the number of tokens
|
||||
that get created during the run of the system.
|
||||
************************************************************************/
|
||||
class CTokenFactory {
|
||||
class nsCTokenRecycler : public nsITokenRecycler {
|
||||
public:
|
||||
|
||||
enum {eCacheSize=50};
|
||||
enum {eCacheMaxSize=50};
|
||||
|
||||
nsCTokenRecycler();
|
||||
virtual ~nsCTokenRecycler();
|
||||
virtual void RecycleToken(CToken* aToken);
|
||||
virtual CToken* CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag, const nsString& aString);
|
||||
|
||||
CTokenFactory();
|
||||
~CTokenFactory();
|
||||
CToken* CreateToken(eHTMLTokenTypes aType, eHTMLTags aTag, const nsString& aString);
|
||||
void RecycleToken(CToken* aToken);
|
||||
protected:
|
||||
CToken* mTokenCache[eToken_last-1][eCacheSize];
|
||||
CToken* mTokenCache[eToken_last-1][eCacheMaxSize];
|
||||
PRInt32 mCount[eToken_last-1];
|
||||
};
|
||||
|
||||
@ -236,7 +239,7 @@ protected:
|
||||
* @update gess7/25/98
|
||||
* @param
|
||||
*/
|
||||
CTokenFactory::CTokenFactory() {
|
||||
nsCTokenRecycler::nsCTokenRecycler() : nsITokenRecycler() {
|
||||
nsCRT::zero(mTokenCache,sizeof(mTokenCache));
|
||||
nsCRT::zero(mCount,sizeof(mCount));
|
||||
}
|
||||
@ -245,29 +248,49 @@ CTokenFactory::CTokenFactory() {
|
||||
* Destructor for the token factory
|
||||
* @update gess7/25/98
|
||||
*/
|
||||
CTokenFactory::~CTokenFactory() {
|
||||
nsCTokenRecycler::~nsCTokenRecycler() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method is used as the factory for all HTML tokens.
|
||||
* There will be a corresponding recycler method, so that we can
|
||||
* cut down on the number of tokens we create.
|
||||
* This method gets called when someone wants to recycle a token
|
||||
* @update gess7/24/98
|
||||
* @param aType
|
||||
* @param aTag
|
||||
* @param aString
|
||||
* @return newly created token or null
|
||||
* @param aToken -- token to be recycled.
|
||||
* @return nada
|
||||
*/
|
||||
CToken* CTokenFactory::CreateToken(eHTMLTokenTypes aType, eHTMLTags aTag, const nsString& aString) {
|
||||
void nsCTokenRecycler::RecycleToken(CToken* aToken) {
|
||||
if(aToken) {
|
||||
PRInt32 theType=aToken->GetTokenType();
|
||||
if(mCount[theType-1]<eCacheMaxSize) {
|
||||
mTokenCache[theType-1][mCount[theType-1]]=aToken;
|
||||
mCount[theType-1]++;
|
||||
} else {
|
||||
//this is an overflow condition. More tokens of a given
|
||||
//type have been created than we can store in our recycler.
|
||||
//In this case, just destroy the extra token.
|
||||
delete aToken;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess8/4/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
CToken* nsCTokenRecycler::CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag, const nsString& aString) {
|
||||
|
||||
CToken* result;
|
||||
|
||||
if(mCount[aType-1]>0){
|
||||
result=mTokenCache[aType-1][--mCount[aType-1]];
|
||||
mTokenCache[aType-1][mCount[aType-1]]=0;
|
||||
if(0<mCount[aType-1]) {
|
||||
result=mTokenCache[aType-1][mCount[aType-1]-1];
|
||||
result->Reinitialize(aTag,aString);
|
||||
mTokenCache[aType-1][mCount[aType-1]-1]=0;
|
||||
mCount[aType-1]--;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
switch(aType){
|
||||
case eToken_start: result=new CStartToken(aTag); break;
|
||||
case eToken_end: result=new CEndToken(aTag); break;
|
||||
@ -287,29 +310,9 @@ CToken* CTokenFactory::CreateToken(eHTMLTokenTypes aType, eHTMLTags aTag, const
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method gets called when the DTD wants to recycle a token
|
||||
* it has finished using.
|
||||
* @update gess7/24/98
|
||||
* @param aToken -- token to be recycled.
|
||||
* @return nada
|
||||
*/
|
||||
void CTokenFactory::RecycleToken(CToken* aToken) {
|
||||
if(aToken) {
|
||||
eHTMLTokenTypes aType=(eHTMLTokenTypes)aToken->GetTokenType();
|
||||
if(mCount[aType-1]<eCacheSize) {
|
||||
mTokenCache[aType-1][mCount[aType-1]]=aToken;
|
||||
mCount[aType-1]++;
|
||||
} else {
|
||||
//this is an overflow condition. More tokens of a given
|
||||
//type have been created than we can store in our recycler.
|
||||
//In this case, just destroy the extra token.
|
||||
delete aToken;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CTokenFactory gTokenFactory;
|
||||
nsCTokenRecycler gTokenRecycler;
|
||||
|
||||
|
||||
/************************************************************************
|
||||
And now for the main class -- CNavDTD...
|
||||
@ -497,6 +500,18 @@ nsresult CNavDTD::CreateNewInstance(nsIDTD** aInstancePtrResult){
|
||||
return NS_NewNavHTMLDTD(aInstancePtrResult);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess8/4/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
nsITokenRecycler* CNavDTD::GetTokenRecycler(void){
|
||||
return 0;
|
||||
return &gTokenRecycler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the parser to initiate dtd verification of the
|
||||
* internal context stack.
|
||||
@ -1352,7 +1367,7 @@ PRBool CNavDTD::CanContain(PRInt32 aParent,PRInt32 aChild) {
|
||||
return CanContainFormElement((eHTMLTags)aParent,(eHTMLTags)aChild);
|
||||
}
|
||||
|
||||
if (0 != strchr(gStyleTags, aParent)) {
|
||||
if((aParent) && (0 != strchr(gStyleTags, aParent))) {
|
||||
if(eHTMLTag_li == aChild) {
|
||||
//This code was added to enforce the rule that listitems
|
||||
//autoclose prior listitems. Stylistic tags (including <A>)
|
||||
@ -2730,7 +2745,7 @@ nsresult CNavDTD::CreateContextStackFor(eHTMLTags aChildTag){
|
||||
int i=0;
|
||||
for(i=pos;i<cnt;i++) {
|
||||
// CStartToken* st=new CStartToken((eHTMLTags)theVector[cnt-1-i]);
|
||||
CToken* theToken=gTokenFactory.CreateToken(eToken_start,(eHTMLTags)theVector[cnt-1-i],gEmpty);
|
||||
CToken* theToken=gTokenRecycler.CreateTokenOfType(eToken_start,(eHTMLTags)theVector[cnt-1-i],gEmpty);
|
||||
HandleStartToken(theToken);
|
||||
}
|
||||
}
|
||||
@ -2856,12 +2871,12 @@ CNavDTD::ConsumeTag(PRUnichar aChar,CScanner& aScanner,CToken*& aToken) {
|
||||
result=aScanner.Peek(ch);
|
||||
if(NS_OK==result) {
|
||||
if(nsString::IsAlpha(ch))
|
||||
aToken=gTokenFactory.CreateToken(eToken_end,eHTMLTag_unknown,gEmpty);
|
||||
else aToken=gTokenFactory.CreateToken(eToken_comment,eHTMLTag_unknown,gEmpty);
|
||||
aToken=gTokenRecycler.CreateTokenOfType(eToken_end,eHTMLTag_unknown,gEmpty);
|
||||
else aToken=gTokenRecycler.CreateTokenOfType(eToken_comment,eHTMLTag_unknown,gEmpty);
|
||||
}//if
|
||||
break;
|
||||
case kExclamation:
|
||||
aToken=gTokenFactory.CreateToken(eToken_comment,eHTMLTag_unknown,gEmpty);
|
||||
aToken=gTokenRecycler.CreateTokenOfType(eToken_comment,eHTMLTag_unknown,gEmpty);
|
||||
break;
|
||||
default:
|
||||
if(nsString::IsAlpha(aChar))
|
||||
@ -2899,7 +2914,7 @@ CNavDTD::ConsumeAttributes(PRUnichar aChar,CScanner& aScanner,CStartToken* aToke
|
||||
PRInt16 theAttrCount=0;
|
||||
|
||||
while((!done) && (result==NS_OK)) {
|
||||
CAttributeToken* theToken= (CAttributeToken*)gTokenFactory.CreateToken(eToken_attribute,eHTMLTag_unknown,gEmpty);
|
||||
CAttributeToken* theToken= (CAttributeToken*)gTokenRecycler.CreateTokenOfType(eToken_attribute,eHTMLTag_unknown,gEmpty);
|
||||
if(theToken){
|
||||
result=theToken->Consume(aChar,aScanner); //tell new token to finish consuming text...
|
||||
|
||||
@ -2957,7 +2972,7 @@ CNavDTD::ConsumeContentToEndTag(const nsString& aString,
|
||||
nsAutoString endTag("</");
|
||||
endTag.Append(aString);
|
||||
endTag.Append(">");
|
||||
aToken=gTokenFactory.CreateToken(eToken_skippedcontent,aChildTag,endTag);
|
||||
aToken=gTokenRecycler.CreateTokenOfType(eToken_skippedcontent,aChildTag,endTag);
|
||||
return aToken->Consume(aChar,aScanner); //tell new token to finish consuming text...
|
||||
}
|
||||
|
||||
@ -2979,7 +2994,7 @@ CNavDTD::ConsumeStartTag(PRUnichar aChar,CScanner& aScanner,CToken*& aToken) {
|
||||
PRInt32 theDequeSize=mTokenDeque.GetSize();
|
||||
nsresult result=NS_OK;
|
||||
|
||||
aToken=gTokenFactory.CreateToken(eToken_start,eHTMLTag_unknown,gEmpty);
|
||||
aToken=gTokenRecycler.CreateTokenOfType(eToken_start,eHTMLTag_unknown,gEmpty);
|
||||
|
||||
if(aToken) {
|
||||
result= aToken->Consume(aChar,aScanner); //tell new token to finish consuming text...
|
||||
@ -3012,7 +3027,7 @@ CNavDTD::ConsumeStartTag(PRUnichar aChar,CScanner& aScanner,CToken*& aToken) {
|
||||
//In the case that we just read a given tag, we should go and
|
||||
//consume all the tag content itself (and throw it all away).
|
||||
|
||||
CToken* endtoken=gTokenFactory.CreateToken(eToken_end,theTag,gEmpty);
|
||||
CToken* endtoken=gTokenRecycler.CreateTokenOfType(eToken_end,theTag,gEmpty);
|
||||
mTokenDeque.Push(endtoken);
|
||||
} //if
|
||||
} //if
|
||||
@ -3053,11 +3068,11 @@ CNavDTD::ConsumeEntity(PRUnichar aChar,CScanner& aScanner,CToken*& aToken) {
|
||||
|
||||
if(NS_OK==result) {
|
||||
if(nsString::IsAlpha(ch)) { //handle common enity references &xxx; or �.
|
||||
aToken = gTokenFactory.CreateToken(eToken_entity,eHTMLTag_unknown,gEmpty);
|
||||
aToken = gTokenRecycler.CreateTokenOfType(eToken_entity,eHTMLTag_unknown,gEmpty);
|
||||
result = aToken->Consume(ch,aScanner); //tell new token to finish consuming text...
|
||||
}
|
||||
else if(kHashsign==ch) {
|
||||
aToken = gTokenFactory.CreateToken(eToken_entity,eHTMLTag_unknown,gEmpty);
|
||||
aToken = gTokenRecycler.CreateTokenOfType(eToken_entity,eHTMLTag_unknown,gEmpty);
|
||||
result=aToken->Consume(0,aScanner);
|
||||
}
|
||||
else {
|
||||
@ -3084,7 +3099,7 @@ nsresult
|
||||
CNavDTD::ConsumeWhitespace(PRUnichar aChar,
|
||||
CScanner& aScanner,
|
||||
CToken*& aToken) {
|
||||
aToken = gTokenFactory.CreateToken(eToken_whitespace,eHTMLTag_unknown,gEmpty);
|
||||
aToken = gTokenRecycler.CreateTokenOfType(eToken_whitespace,eHTMLTag_unknown,gEmpty);
|
||||
nsresult result=kNoError;
|
||||
if(aToken) {
|
||||
result=aToken->Consume(aChar,aScanner);
|
||||
@ -3103,7 +3118,7 @@ CNavDTD::ConsumeWhitespace(PRUnichar aChar,
|
||||
* @return new token or null
|
||||
*/
|
||||
nsresult CNavDTD::ConsumeComment(PRUnichar aChar,CScanner& aScanner,CToken*& aToken){
|
||||
aToken = gTokenFactory.CreateToken(eToken_comment,eHTMLTag_unknown,gEmpty);
|
||||
aToken = gTokenRecycler.CreateTokenOfType(eToken_comment,eHTMLTag_unknown,gEmpty);
|
||||
nsresult result=NS_OK;
|
||||
if(aToken) {
|
||||
result=aToken->Consume(aChar,aScanner);
|
||||
@ -3123,7 +3138,7 @@ nsresult CNavDTD::ConsumeComment(PRUnichar aChar,CScanner& aScanner,CToken*& aTo
|
||||
*/
|
||||
nsresult CNavDTD::ConsumeText(const nsString& aString,CScanner& aScanner,CToken*& aToken){
|
||||
nsresult result=NS_OK;
|
||||
aToken=gTokenFactory.CreateToken(eToken_text,eHTMLTag_text,aString);
|
||||
aToken=gTokenRecycler.CreateTokenOfType(eToken_text,eHTMLTag_text,aString);
|
||||
if(aToken) {
|
||||
PRUnichar ch=0;
|
||||
result=aToken->Consume(ch,aScanner);
|
||||
@ -3148,7 +3163,7 @@ nsresult CNavDTD::ConsumeText(const nsString& aString,CScanner& aScanner,CToken*
|
||||
* @return error code
|
||||
*/
|
||||
nsresult CNavDTD::ConsumeNewline(PRUnichar aChar,CScanner& aScanner,CToken*& aToken){
|
||||
aToken=gTokenFactory.CreateToken(eToken_newline,eHTMLTag_newline,gEmpty);
|
||||
aToken=gTokenRecycler.CreateTokenOfType(eToken_newline,eHTMLTag_newline,gEmpty);
|
||||
nsresult result=NS_OK;
|
||||
if(aToken) {
|
||||
result=aToken->Consume(aChar,aScanner);
|
||||
@ -3228,16 +3243,6 @@ nsresult CNavDTD::ConsumeToken(CToken*& aToken){
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess4/11/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
CToken* CNavDTD::CreateTokenOfType(eHTMLTokenTypes aType) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
@ -3254,10 +3259,10 @@ nsresult CNavDTD::WillResumeParse(void){
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* This method gets called when the parsing process is interrupted
|
||||
* due to lack of data (waiting for netlib).
|
||||
* @update gess5/18/98
|
||||
* @param
|
||||
* @return
|
||||
* @return error code
|
||||
*/
|
||||
nsresult CNavDTD::WillInterruptParse(void){
|
||||
nsresult result = NS_OK;
|
||||
|
||||
@ -443,6 +443,8 @@ CLASS_EXPORT_HTMLPARS CNavDTD : public nsIDTD {
|
||||
nsresult HandleScriptToken(CToken* aToken, nsCParserNode& aNode);
|
||||
nsresult HandleStyleToken(CToken* aToken);
|
||||
|
||||
virtual nsITokenRecycler* GetTokenRecycler(void);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
@ -551,14 +553,6 @@ protected:
|
||||
****************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* Called to cause delegate to create a token of given type.
|
||||
* @update gess 5/11/98
|
||||
* @param aType represents the kind of token you want to create.
|
||||
* @return new token or NULL
|
||||
*/
|
||||
CToken* CreateTokenOfType(eHTMLTokenTypes aType);
|
||||
|
||||
/**
|
||||
* The following methods consume a particular type
|
||||
* of HTML token.
|
||||
|
||||
@ -938,16 +938,6 @@ nsresult COtherDTD::ConsumeToken(CToken*& aToken){
|
||||
return CNavDTD::ConsumeToken(aToken);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess4/11/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
CToken* COtherDTD::CreateTokenOfType(eHTMLTokenTypes aType) {
|
||||
return CNavDTD::CreateTokenOfType(aType);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@ -504,14 +504,6 @@ private:
|
||||
****************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* Called to cause delegate to create a token of given type.
|
||||
* @update gess 5/11/98
|
||||
* @param aType represents the kind of token you want to create.
|
||||
* @return new token or NULL
|
||||
*/
|
||||
CToken* CreateTokenOfType(eHTMLTokenTypes aType);
|
||||
|
||||
/**
|
||||
* Retrieve the next TAG from the given scanner.
|
||||
* @update gess 5/11/98
|
||||
|
||||
@ -542,6 +542,16 @@ nsresult CRtfDTD::HandleToken(CToken* aToken) {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess8/4/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
nsITokenRecycler* CRtfDTD::GetTokenRecycler(void){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
Heres's the RTFControlWord subclass...
|
||||
***************************************************************/
|
||||
|
||||
@ -346,7 +346,14 @@ class CRtfDTD : public nsIDTD {
|
||||
* @return PR_TRUE if parent can contain child
|
||||
*/
|
||||
virtual PRBool CanContain(PRInt32 aParent,PRInt32 aChild);
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve a ptr to the global token recycler...
|
||||
* @update gess8/4/98
|
||||
* @return ptr to recycler (or null)
|
||||
*/
|
||||
virtual nsITokenRecycler* GetTokenRecycler(void);
|
||||
|
||||
protected:
|
||||
|
||||
nsParser* mParser;
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
#include "prtypes.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsHTMLTags.h"
|
||||
#include "nsCRT.h"
|
||||
|
||||
//#define GESS_MACHINE
|
||||
#ifdef GESS_MACHINE
|
||||
@ -94,6 +95,11 @@ static StrToUnicodeStruct gStrToUnicodeTable[] =
|
||||
{"yuml", 0x00ff}
|
||||
};
|
||||
|
||||
|
||||
/**************************************************************
|
||||
And now for the token classes...
|
||||
**************************************************************/
|
||||
|
||||
/*
|
||||
* default constructor
|
||||
*
|
||||
@ -128,6 +134,7 @@ void CHTMLToken::SetStringValue(const char* name){
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* constructor from tag id
|
||||
*
|
||||
@ -153,6 +160,18 @@ CStartToken::CStartToken(nsString& aString) : CHTMLToken(aString) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess8/4/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
void CStartToken::Reinitialize(PRInt32 aTag, const nsString& aString){
|
||||
CToken::Reinitialize(aTag,aString);
|
||||
mAttributed=PR_FALSE;
|
||||
mEmpty=PR_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method returns the typeid (the tag type) for this token.
|
||||
*
|
||||
@ -682,6 +701,18 @@ CAttributeToken::CAttributeToken(const nsString& aKey, const nsString& aName) :
|
||||
mLastAttribute=PR_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess8/4/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
void CAttributeToken::Reinitialize(PRInt32 aTag, const nsString& aString){
|
||||
CHTMLToken::Reinitialize(aTag,aString);
|
||||
mTextKey.Truncate();
|
||||
mLastAttribute=PR_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
@ -949,6 +980,7 @@ CEntityToken::CEntityToken(const nsString& aName) : CHTMLToken(aName) {
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Consume the rest of the entity. We've already eaten the "&".
|
||||
*
|
||||
@ -1329,6 +1361,7 @@ nsresult CSkippedContentToken::Consume(PRUnichar,CScanner& aScanner) {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* This method iterates the tagtable to ensure that is
|
||||
|
||||
@ -71,6 +71,7 @@ const char* GetTagName(PRInt32 aTag);
|
||||
*/
|
||||
class CHTMLToken : public CToken {
|
||||
public:
|
||||
|
||||
CHTMLToken(eHTMLTags aTag);
|
||||
CHTMLToken(const nsString& aString);
|
||||
virtual void SetStringValue(const char* name);
|
||||
@ -99,6 +100,7 @@ class CStartToken: public CHTMLToken {
|
||||
PRBool IsEmpty(void);
|
||||
void SetEmpty(PRBool aValue);
|
||||
virtual void DebugDumpSource(ostream& out);
|
||||
virtual void Reinitialize(PRInt32 aTag, const nsString& aString);
|
||||
|
||||
protected:
|
||||
PRBool mAttributed;
|
||||
@ -225,6 +227,7 @@ class CAttributeToken: public CHTMLToken {
|
||||
virtual void DebugDumpToken(ostream& out);
|
||||
virtual void DebugDumpSource(ostream& out);
|
||||
PRBool mLastAttribute;
|
||||
virtual void Reinitialize(PRInt32 aTag, const nsString& aString);
|
||||
|
||||
protected:
|
||||
nsString mTextKey;
|
||||
|
||||
@ -44,8 +44,16 @@ class nsIDTDDebug;
|
||||
class nsIURL;
|
||||
class nsString;
|
||||
|
||||
|
||||
enum eAutoDetectResult {eUnknownDetect, eValidDetect, eInvalidDetect};
|
||||
|
||||
|
||||
class nsITokenRecycler {
|
||||
public:
|
||||
virtual void RecycleToken(CToken* aToken)=0;
|
||||
};
|
||||
|
||||
|
||||
class nsIDTD : public nsISupports {
|
||||
public:
|
||||
|
||||
@ -177,7 +185,17 @@ class nsIDTD : public nsISupports {
|
||||
*/
|
||||
virtual PRBool Verify(nsString& aURLRef)=0;
|
||||
|
||||
/**
|
||||
* Retrieve a ptr to the global token recycler...
|
||||
* @update gess8/4/98
|
||||
* @return ptr to recycler (or null)
|
||||
*/
|
||||
virtual nsITokenRecycler* GetTokenRecycler(void)=0;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* nsIDTD_h___ */
|
||||
|
||||
|
||||
@ -93,7 +93,7 @@ public:
|
||||
|
||||
void RegisterDTD(nsIDTD* aDTD){
|
||||
CDTDFinder theFinder(aDTD);
|
||||
if(!mDTDDeque.ForEach(theFinder))
|
||||
if(!mDTDDeque.FirstThat(theFinder))
|
||||
mDTDDeque.Push(aDTD);
|
||||
}
|
||||
|
||||
@ -383,6 +383,20 @@ PRInt32 nsParser::DidBuildModel(PRInt32 anErrorCode) {
|
||||
result=mParserContext->mDTD->DidBuildModel(anErrorCode,PRBool(0==mParserContext->mPrevContext));
|
||||
}
|
||||
|
||||
//Now it's time to recycle our used tokens.
|
||||
//The current context has a deque full of them,
|
||||
//and the ones that preceed currentpos are no
|
||||
//longer needed. Let's recycle them.
|
||||
nsDeque& theDeque=mParserContext->mTokenDeque;
|
||||
nsITokenRecycler* theRecycler=mParserContext->mDTD->GetTokenRecycler();
|
||||
if(theRecycler) {
|
||||
CToken* theToken=(CToken*)theDeque.Pop();
|
||||
while(theToken) {
|
||||
theRecycler->RecycleToken(theToken);
|
||||
theToken=(CToken*)theDeque.Pop();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -554,23 +568,6 @@ PRInt32 nsParser::BuildModel() {
|
||||
while((kNoError==result) && ((*mParserContext->mCurrentPos<e))){
|
||||
mMinorIteration++;
|
||||
CToken* theToken=(CToken*)mParserContext->mCurrentPos->GetCurrent();
|
||||
|
||||
/**************************************************************************
|
||||
The point of this code to serve as a testbed for parser reentrancy.
|
||||
If you set recurse=1, we go reentrant, passing a text string of HTML onto
|
||||
the parser for inline processing, just like javascript/DOM would do it.
|
||||
And guess what? It worked the first time!
|
||||
Uncomment the following code to enable the test:
|
||||
|
||||
int recurse=0;
|
||||
if(recurse){
|
||||
nsString theString(" this is just a great big empty string ");
|
||||
// nsString theString("<P>doc.write");
|
||||
// nsString theString("<table border=1><tr><td BGCOLOR=blue>cell</td></tr></table>");
|
||||
Parse(theString,PR_TRUE);
|
||||
}
|
||||
*/
|
||||
|
||||
theMarkPos=*mParserContext->mCurrentPos;
|
||||
++(*mParserContext->mCurrentPos);
|
||||
result=theRootDTD->HandleToken(theToken);
|
||||
@ -578,9 +575,25 @@ PRInt32 nsParser::BuildModel() {
|
||||
theRootDTD->Verify(kEmptyString);
|
||||
}
|
||||
|
||||
if(kInterrupted==result)
|
||||
if(kInterrupted==result) {
|
||||
*mParserContext->mCurrentPos=theMarkPos;
|
||||
|
||||
//Now it's time to recycle our used tokens.
|
||||
//The current context has a deque full of them,
|
||||
//and the ones that preceed currentpos are no
|
||||
//longer needed. Let's recycle them.
|
||||
nsITokenRecycler* theRecycler=theRootDTD->GetTokenRecycler();
|
||||
if(theRecycler) {
|
||||
nsDeque& theDeque=mParserContext->mTokenDeque;
|
||||
CToken* theCurrentToken=(CToken*)mParserContext->mCurrentPos->GetCurrent();
|
||||
CToken* theToken=(CToken*)theDeque.Peek();
|
||||
while(theToken && (theToken!=theCurrentToken)) {
|
||||
theDeque.Pop();
|
||||
theRecycler->RecycleToken(theToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@ -19,6 +19,13 @@
|
||||
#include "nsToken.h"
|
||||
#include "nsScanner.h"
|
||||
|
||||
static int TokenCount=0;
|
||||
|
||||
|
||||
/**************************************************************
|
||||
And now for the CToken...
|
||||
**************************************************************/
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*
|
||||
@ -27,6 +34,7 @@
|
||||
CToken::CToken(PRInt32 aTag) : mTextValue() {
|
||||
mTypeID=aTag;
|
||||
mAttrCount=0;
|
||||
TokenCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -38,6 +46,7 @@ CToken::CToken(PRInt32 aTag) : mTextValue() {
|
||||
CToken::CToken(const nsString& aName) : mTextValue(aName) {
|
||||
mTypeID=0;
|
||||
mAttrCount=0;
|
||||
TokenCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -49,6 +58,7 @@ CToken::CToken(const nsString& aName) : mTextValue(aName) {
|
||||
CToken::CToken(const char* aName) : mTextValue(aName) {
|
||||
mTypeID=0;
|
||||
mAttrCount=0;
|
||||
TokenCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -69,7 +79,11 @@ CToken::~CToken() {
|
||||
* @param aString
|
||||
*/
|
||||
void CToken::Reinitialize(PRInt32 aTag, const nsString& aString){
|
||||
mTypeID=0;
|
||||
if(0==aString.Length())
|
||||
mTextValue.Truncate(0);
|
||||
else mTextValue.SetString(aString);
|
||||
mAttrCount=0;
|
||||
mTypeID=aTag;
|
||||
mAttrCount=0;
|
||||
}
|
||||
|
||||
@ -211,6 +225,7 @@ const char* CToken::GetClassName(void) {
|
||||
return "token";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess 3/25/98
|
||||
|
||||
@ -41,6 +41,7 @@
|
||||
|
||||
class CScanner;
|
||||
|
||||
|
||||
/**
|
||||
* Token objects represent sequences of characters as they
|
||||
* are consumed from the input stream (URL). While they're
|
||||
|
||||
@ -356,3 +356,13 @@ NS_IMETHODIMP CValidDTD::HandleToken(CToken* aToken) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess8/4/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
nsITokenRecycler* CValidDTD::GetTokenRecycler(void){
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -210,7 +210,14 @@ class CValidDTD : public nsIDTD {
|
||||
* @return PR_TRUE if parent can contain child
|
||||
*/
|
||||
virtual PRBool CanContain(PRInt32 aParent,PRInt32 aChild);
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve a ptr to the global token recycler...
|
||||
* @update gess8/4/98
|
||||
* @return ptr to recycler (or null)
|
||||
*/
|
||||
virtual nsITokenRecycler* GetTokenRecycler(void);
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
|
||||
@ -343,3 +343,13 @@ NS_IMETHODIMP CWellFormedDTD::HandleToken(CToken* aToken) {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess8/4/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
nsITokenRecycler* CWellFormedDTD::GetTokenRecycler(void){
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -200,7 +200,14 @@ class CWellFormedDTD : public nsIDTD {
|
||||
* @return PR_TRUE if parent can contain child
|
||||
*/
|
||||
virtual PRBool CanContain(PRInt32 aParent,PRInt32 aChild);
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve a ptr to the global token recycler...
|
||||
* @update gess8/4/98
|
||||
* @return ptr to recycler (or null)
|
||||
*/
|
||||
virtual nsITokenRecycler* GetTokenRecycler(void);
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
|
||||
@ -160,7 +160,7 @@ eXIFTags DetermineXIFTagType(const nsString& aString)
|
||||
|
||||
while(low<=high){
|
||||
middle=(PRInt32)(low+high)/2;
|
||||
result=aString.Compare(gXIFTagTable[middle].mName, PR_TRUE);
|
||||
result=aString.Compare(gXIFTagTable[middle].mName, PR_TRUE);
|
||||
if (result==0)
|
||||
return gXIFTagTable[middle].fTagID;
|
||||
if (result<0)
|
||||
@ -1736,16 +1736,6 @@ PRInt32 nsXIFDTD::CollectSkippedContent(nsCParserNode& aNode,PRInt32& aCount) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gpk 06/18/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
CToken* nsXIFDTD::CreateTokenOfType(eHTMLTokenTypes aType) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
@ -1989,3 +1979,13 @@ void nsXIFDTD::AddCSSDeclaration(const nsIParserNode& aNode)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess8/4/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
nsITokenRecycler* nsXIFDTD::GetTokenRecycler(void){
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -499,14 +499,6 @@ private:
|
||||
****************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* Called to cause delegate to create a token of given type.
|
||||
* @update gpk 06/18/98
|
||||
* @param aType represents the kind of token you want to create.
|
||||
* @return new token or NULL
|
||||
*/
|
||||
CToken* CreateTokenOfType(eHTMLTokenTypes aType);
|
||||
|
||||
/**
|
||||
* Retrieve the next TAG from the given scanner.
|
||||
* @update gpk 06/18/98
|
||||
@ -627,6 +619,12 @@ private:
|
||||
void PopAndDelete();
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve a ptr to the global token recycler...
|
||||
* @update gess8/4/98
|
||||
* @return ptr to recycler (or null)
|
||||
*/
|
||||
virtual nsITokenRecycler* GetTokenRecycler(void);
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
@ -208,25 +208,28 @@ eHTMLTags CTagStack::Last() const {
|
||||
return eHTMLTag_unknown;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************
|
||||
Now define the tokenrecycler class...
|
||||
**************************************************************/
|
||||
|
||||
/************************************************************************
|
||||
CTokenFactory class implementation.
|
||||
This class is used to create and destroy our tokens.
|
||||
CTokenRecycler class implementation.
|
||||
This class is used to recycle tokens.
|
||||
By using this simple class, we cut WAY down on the number of tokens
|
||||
that get created during the run of the system.
|
||||
************************************************************************/
|
||||
class CTokenFactory {
|
||||
class nsCTokenRecycler : public nsITokenRecycler {
|
||||
public:
|
||||
|
||||
enum {eCacheSize=50};
|
||||
enum {eCacheMaxSize=50};
|
||||
|
||||
nsCTokenRecycler();
|
||||
virtual ~nsCTokenRecycler();
|
||||
virtual void RecycleToken(CToken* aToken);
|
||||
virtual CToken* CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag, const nsString& aString);
|
||||
|
||||
CTokenFactory();
|
||||
~CTokenFactory();
|
||||
CToken* CreateToken(eHTMLTokenTypes aType, eHTMLTags aTag, const nsString& aString);
|
||||
void RecycleToken(CToken* aToken);
|
||||
protected:
|
||||
CToken* mTokenCache[eToken_last-1][eCacheSize];
|
||||
CToken* mTokenCache[eToken_last-1][eCacheMaxSize];
|
||||
PRInt32 mCount[eToken_last-1];
|
||||
};
|
||||
|
||||
@ -236,7 +239,7 @@ protected:
|
||||
* @update gess7/25/98
|
||||
* @param
|
||||
*/
|
||||
CTokenFactory::CTokenFactory() {
|
||||
nsCTokenRecycler::nsCTokenRecycler() : nsITokenRecycler() {
|
||||
nsCRT::zero(mTokenCache,sizeof(mTokenCache));
|
||||
nsCRT::zero(mCount,sizeof(mCount));
|
||||
}
|
||||
@ -245,29 +248,49 @@ CTokenFactory::CTokenFactory() {
|
||||
* Destructor for the token factory
|
||||
* @update gess7/25/98
|
||||
*/
|
||||
CTokenFactory::~CTokenFactory() {
|
||||
nsCTokenRecycler::~nsCTokenRecycler() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method is used as the factory for all HTML tokens.
|
||||
* There will be a corresponding recycler method, so that we can
|
||||
* cut down on the number of tokens we create.
|
||||
* This method gets called when someone wants to recycle a token
|
||||
* @update gess7/24/98
|
||||
* @param aType
|
||||
* @param aTag
|
||||
* @param aString
|
||||
* @return newly created token or null
|
||||
* @param aToken -- token to be recycled.
|
||||
* @return nada
|
||||
*/
|
||||
CToken* CTokenFactory::CreateToken(eHTMLTokenTypes aType, eHTMLTags aTag, const nsString& aString) {
|
||||
void nsCTokenRecycler::RecycleToken(CToken* aToken) {
|
||||
if(aToken) {
|
||||
PRInt32 theType=aToken->GetTokenType();
|
||||
if(mCount[theType-1]<eCacheMaxSize) {
|
||||
mTokenCache[theType-1][mCount[theType-1]]=aToken;
|
||||
mCount[theType-1]++;
|
||||
} else {
|
||||
//this is an overflow condition. More tokens of a given
|
||||
//type have been created than we can store in our recycler.
|
||||
//In this case, just destroy the extra token.
|
||||
delete aToken;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess8/4/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
CToken* nsCTokenRecycler::CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag, const nsString& aString) {
|
||||
|
||||
CToken* result;
|
||||
|
||||
if(mCount[aType-1]>0){
|
||||
result=mTokenCache[aType-1][--mCount[aType-1]];
|
||||
mTokenCache[aType-1][mCount[aType-1]]=0;
|
||||
if(0<mCount[aType-1]) {
|
||||
result=mTokenCache[aType-1][mCount[aType-1]-1];
|
||||
result->Reinitialize(aTag,aString);
|
||||
mTokenCache[aType-1][mCount[aType-1]-1]=0;
|
||||
mCount[aType-1]--;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
switch(aType){
|
||||
case eToken_start: result=new CStartToken(aTag); break;
|
||||
case eToken_end: result=new CEndToken(aTag); break;
|
||||
@ -287,29 +310,9 @@ CToken* CTokenFactory::CreateToken(eHTMLTokenTypes aType, eHTMLTags aTag, const
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method gets called when the DTD wants to recycle a token
|
||||
* it has finished using.
|
||||
* @update gess7/24/98
|
||||
* @param aToken -- token to be recycled.
|
||||
* @return nada
|
||||
*/
|
||||
void CTokenFactory::RecycleToken(CToken* aToken) {
|
||||
if(aToken) {
|
||||
eHTMLTokenTypes aType=(eHTMLTokenTypes)aToken->GetTokenType();
|
||||
if(mCount[aType-1]<eCacheSize) {
|
||||
mTokenCache[aType-1][mCount[aType-1]]=aToken;
|
||||
mCount[aType-1]++;
|
||||
} else {
|
||||
//this is an overflow condition. More tokens of a given
|
||||
//type have been created than we can store in our recycler.
|
||||
//In this case, just destroy the extra token.
|
||||
delete aToken;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CTokenFactory gTokenFactory;
|
||||
nsCTokenRecycler gTokenRecycler;
|
||||
|
||||
|
||||
/************************************************************************
|
||||
And now for the main class -- CNavDTD...
|
||||
@ -497,6 +500,18 @@ nsresult CNavDTD::CreateNewInstance(nsIDTD** aInstancePtrResult){
|
||||
return NS_NewNavHTMLDTD(aInstancePtrResult);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess8/4/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
nsITokenRecycler* CNavDTD::GetTokenRecycler(void){
|
||||
return 0;
|
||||
return &gTokenRecycler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the parser to initiate dtd verification of the
|
||||
* internal context stack.
|
||||
@ -1352,7 +1367,7 @@ PRBool CNavDTD::CanContain(PRInt32 aParent,PRInt32 aChild) {
|
||||
return CanContainFormElement((eHTMLTags)aParent,(eHTMLTags)aChild);
|
||||
}
|
||||
|
||||
if (0 != strchr(gStyleTags, aParent)) {
|
||||
if((aParent) && (0 != strchr(gStyleTags, aParent))) {
|
||||
if(eHTMLTag_li == aChild) {
|
||||
//This code was added to enforce the rule that listitems
|
||||
//autoclose prior listitems. Stylistic tags (including <A>)
|
||||
@ -2730,7 +2745,7 @@ nsresult CNavDTD::CreateContextStackFor(eHTMLTags aChildTag){
|
||||
int i=0;
|
||||
for(i=pos;i<cnt;i++) {
|
||||
// CStartToken* st=new CStartToken((eHTMLTags)theVector[cnt-1-i]);
|
||||
CToken* theToken=gTokenFactory.CreateToken(eToken_start,(eHTMLTags)theVector[cnt-1-i],gEmpty);
|
||||
CToken* theToken=gTokenRecycler.CreateTokenOfType(eToken_start,(eHTMLTags)theVector[cnt-1-i],gEmpty);
|
||||
HandleStartToken(theToken);
|
||||
}
|
||||
}
|
||||
@ -2856,12 +2871,12 @@ CNavDTD::ConsumeTag(PRUnichar aChar,CScanner& aScanner,CToken*& aToken) {
|
||||
result=aScanner.Peek(ch);
|
||||
if(NS_OK==result) {
|
||||
if(nsString::IsAlpha(ch))
|
||||
aToken=gTokenFactory.CreateToken(eToken_end,eHTMLTag_unknown,gEmpty);
|
||||
else aToken=gTokenFactory.CreateToken(eToken_comment,eHTMLTag_unknown,gEmpty);
|
||||
aToken=gTokenRecycler.CreateTokenOfType(eToken_end,eHTMLTag_unknown,gEmpty);
|
||||
else aToken=gTokenRecycler.CreateTokenOfType(eToken_comment,eHTMLTag_unknown,gEmpty);
|
||||
}//if
|
||||
break;
|
||||
case kExclamation:
|
||||
aToken=gTokenFactory.CreateToken(eToken_comment,eHTMLTag_unknown,gEmpty);
|
||||
aToken=gTokenRecycler.CreateTokenOfType(eToken_comment,eHTMLTag_unknown,gEmpty);
|
||||
break;
|
||||
default:
|
||||
if(nsString::IsAlpha(aChar))
|
||||
@ -2899,7 +2914,7 @@ CNavDTD::ConsumeAttributes(PRUnichar aChar,CScanner& aScanner,CStartToken* aToke
|
||||
PRInt16 theAttrCount=0;
|
||||
|
||||
while((!done) && (result==NS_OK)) {
|
||||
CAttributeToken* theToken= (CAttributeToken*)gTokenFactory.CreateToken(eToken_attribute,eHTMLTag_unknown,gEmpty);
|
||||
CAttributeToken* theToken= (CAttributeToken*)gTokenRecycler.CreateTokenOfType(eToken_attribute,eHTMLTag_unknown,gEmpty);
|
||||
if(theToken){
|
||||
result=theToken->Consume(aChar,aScanner); //tell new token to finish consuming text...
|
||||
|
||||
@ -2957,7 +2972,7 @@ CNavDTD::ConsumeContentToEndTag(const nsString& aString,
|
||||
nsAutoString endTag("</");
|
||||
endTag.Append(aString);
|
||||
endTag.Append(">");
|
||||
aToken=gTokenFactory.CreateToken(eToken_skippedcontent,aChildTag,endTag);
|
||||
aToken=gTokenRecycler.CreateTokenOfType(eToken_skippedcontent,aChildTag,endTag);
|
||||
return aToken->Consume(aChar,aScanner); //tell new token to finish consuming text...
|
||||
}
|
||||
|
||||
@ -2979,7 +2994,7 @@ CNavDTD::ConsumeStartTag(PRUnichar aChar,CScanner& aScanner,CToken*& aToken) {
|
||||
PRInt32 theDequeSize=mTokenDeque.GetSize();
|
||||
nsresult result=NS_OK;
|
||||
|
||||
aToken=gTokenFactory.CreateToken(eToken_start,eHTMLTag_unknown,gEmpty);
|
||||
aToken=gTokenRecycler.CreateTokenOfType(eToken_start,eHTMLTag_unknown,gEmpty);
|
||||
|
||||
if(aToken) {
|
||||
result= aToken->Consume(aChar,aScanner); //tell new token to finish consuming text...
|
||||
@ -3012,7 +3027,7 @@ CNavDTD::ConsumeStartTag(PRUnichar aChar,CScanner& aScanner,CToken*& aToken) {
|
||||
//In the case that we just read a given tag, we should go and
|
||||
//consume all the tag content itself (and throw it all away).
|
||||
|
||||
CToken* endtoken=gTokenFactory.CreateToken(eToken_end,theTag,gEmpty);
|
||||
CToken* endtoken=gTokenRecycler.CreateTokenOfType(eToken_end,theTag,gEmpty);
|
||||
mTokenDeque.Push(endtoken);
|
||||
} //if
|
||||
} //if
|
||||
@ -3053,11 +3068,11 @@ CNavDTD::ConsumeEntity(PRUnichar aChar,CScanner& aScanner,CToken*& aToken) {
|
||||
|
||||
if(NS_OK==result) {
|
||||
if(nsString::IsAlpha(ch)) { //handle common enity references &xxx; or �.
|
||||
aToken = gTokenFactory.CreateToken(eToken_entity,eHTMLTag_unknown,gEmpty);
|
||||
aToken = gTokenRecycler.CreateTokenOfType(eToken_entity,eHTMLTag_unknown,gEmpty);
|
||||
result = aToken->Consume(ch,aScanner); //tell new token to finish consuming text...
|
||||
}
|
||||
else if(kHashsign==ch) {
|
||||
aToken = gTokenFactory.CreateToken(eToken_entity,eHTMLTag_unknown,gEmpty);
|
||||
aToken = gTokenRecycler.CreateTokenOfType(eToken_entity,eHTMLTag_unknown,gEmpty);
|
||||
result=aToken->Consume(0,aScanner);
|
||||
}
|
||||
else {
|
||||
@ -3084,7 +3099,7 @@ nsresult
|
||||
CNavDTD::ConsumeWhitespace(PRUnichar aChar,
|
||||
CScanner& aScanner,
|
||||
CToken*& aToken) {
|
||||
aToken = gTokenFactory.CreateToken(eToken_whitespace,eHTMLTag_unknown,gEmpty);
|
||||
aToken = gTokenRecycler.CreateTokenOfType(eToken_whitespace,eHTMLTag_unknown,gEmpty);
|
||||
nsresult result=kNoError;
|
||||
if(aToken) {
|
||||
result=aToken->Consume(aChar,aScanner);
|
||||
@ -3103,7 +3118,7 @@ CNavDTD::ConsumeWhitespace(PRUnichar aChar,
|
||||
* @return new token or null
|
||||
*/
|
||||
nsresult CNavDTD::ConsumeComment(PRUnichar aChar,CScanner& aScanner,CToken*& aToken){
|
||||
aToken = gTokenFactory.CreateToken(eToken_comment,eHTMLTag_unknown,gEmpty);
|
||||
aToken = gTokenRecycler.CreateTokenOfType(eToken_comment,eHTMLTag_unknown,gEmpty);
|
||||
nsresult result=NS_OK;
|
||||
if(aToken) {
|
||||
result=aToken->Consume(aChar,aScanner);
|
||||
@ -3123,7 +3138,7 @@ nsresult CNavDTD::ConsumeComment(PRUnichar aChar,CScanner& aScanner,CToken*& aTo
|
||||
*/
|
||||
nsresult CNavDTD::ConsumeText(const nsString& aString,CScanner& aScanner,CToken*& aToken){
|
||||
nsresult result=NS_OK;
|
||||
aToken=gTokenFactory.CreateToken(eToken_text,eHTMLTag_text,aString);
|
||||
aToken=gTokenRecycler.CreateTokenOfType(eToken_text,eHTMLTag_text,aString);
|
||||
if(aToken) {
|
||||
PRUnichar ch=0;
|
||||
result=aToken->Consume(ch,aScanner);
|
||||
@ -3148,7 +3163,7 @@ nsresult CNavDTD::ConsumeText(const nsString& aString,CScanner& aScanner,CToken*
|
||||
* @return error code
|
||||
*/
|
||||
nsresult CNavDTD::ConsumeNewline(PRUnichar aChar,CScanner& aScanner,CToken*& aToken){
|
||||
aToken=gTokenFactory.CreateToken(eToken_newline,eHTMLTag_newline,gEmpty);
|
||||
aToken=gTokenRecycler.CreateTokenOfType(eToken_newline,eHTMLTag_newline,gEmpty);
|
||||
nsresult result=NS_OK;
|
||||
if(aToken) {
|
||||
result=aToken->Consume(aChar,aScanner);
|
||||
@ -3228,16 +3243,6 @@ nsresult CNavDTD::ConsumeToken(CToken*& aToken){
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess4/11/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
CToken* CNavDTD::CreateTokenOfType(eHTMLTokenTypes aType) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
@ -3254,10 +3259,10 @@ nsresult CNavDTD::WillResumeParse(void){
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* This method gets called when the parsing process is interrupted
|
||||
* due to lack of data (waiting for netlib).
|
||||
* @update gess5/18/98
|
||||
* @param
|
||||
* @return
|
||||
* @return error code
|
||||
*/
|
||||
nsresult CNavDTD::WillInterruptParse(void){
|
||||
nsresult result = NS_OK;
|
||||
|
||||
@ -443,6 +443,8 @@ CLASS_EXPORT_HTMLPARS CNavDTD : public nsIDTD {
|
||||
nsresult HandleScriptToken(CToken* aToken, nsCParserNode& aNode);
|
||||
nsresult HandleStyleToken(CToken* aToken);
|
||||
|
||||
virtual nsITokenRecycler* GetTokenRecycler(void);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
@ -551,14 +553,6 @@ protected:
|
||||
****************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* Called to cause delegate to create a token of given type.
|
||||
* @update gess 5/11/98
|
||||
* @param aType represents the kind of token you want to create.
|
||||
* @return new token or NULL
|
||||
*/
|
||||
CToken* CreateTokenOfType(eHTMLTokenTypes aType);
|
||||
|
||||
/**
|
||||
* The following methods consume a particular type
|
||||
* of HTML token.
|
||||
|
||||
@ -938,16 +938,6 @@ nsresult COtherDTD::ConsumeToken(CToken*& aToken){
|
||||
return CNavDTD::ConsumeToken(aToken);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess4/11/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
CToken* COtherDTD::CreateTokenOfType(eHTMLTokenTypes aType) {
|
||||
return CNavDTD::CreateTokenOfType(aType);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@ -504,14 +504,6 @@ private:
|
||||
****************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* Called to cause delegate to create a token of given type.
|
||||
* @update gess 5/11/98
|
||||
* @param aType represents the kind of token you want to create.
|
||||
* @return new token or NULL
|
||||
*/
|
||||
CToken* CreateTokenOfType(eHTMLTokenTypes aType);
|
||||
|
||||
/**
|
||||
* Retrieve the next TAG from the given scanner.
|
||||
* @update gess 5/11/98
|
||||
|
||||
@ -542,6 +542,16 @@ nsresult CRtfDTD::HandleToken(CToken* aToken) {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess8/4/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
nsITokenRecycler* CRtfDTD::GetTokenRecycler(void){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
Heres's the RTFControlWord subclass...
|
||||
***************************************************************/
|
||||
|
||||
@ -346,7 +346,14 @@ class CRtfDTD : public nsIDTD {
|
||||
* @return PR_TRUE if parent can contain child
|
||||
*/
|
||||
virtual PRBool CanContain(PRInt32 aParent,PRInt32 aChild);
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve a ptr to the global token recycler...
|
||||
* @update gess8/4/98
|
||||
* @return ptr to recycler (or null)
|
||||
*/
|
||||
virtual nsITokenRecycler* GetTokenRecycler(void);
|
||||
|
||||
protected:
|
||||
|
||||
nsParser* mParser;
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
#include "prtypes.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsHTMLTags.h"
|
||||
#include "nsCRT.h"
|
||||
|
||||
//#define GESS_MACHINE
|
||||
#ifdef GESS_MACHINE
|
||||
@ -94,6 +95,11 @@ static StrToUnicodeStruct gStrToUnicodeTable[] =
|
||||
{"yuml", 0x00ff}
|
||||
};
|
||||
|
||||
|
||||
/**************************************************************
|
||||
And now for the token classes...
|
||||
**************************************************************/
|
||||
|
||||
/*
|
||||
* default constructor
|
||||
*
|
||||
@ -128,6 +134,7 @@ void CHTMLToken::SetStringValue(const char* name){
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* constructor from tag id
|
||||
*
|
||||
@ -153,6 +160,18 @@ CStartToken::CStartToken(nsString& aString) : CHTMLToken(aString) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess8/4/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
void CStartToken::Reinitialize(PRInt32 aTag, const nsString& aString){
|
||||
CToken::Reinitialize(aTag,aString);
|
||||
mAttributed=PR_FALSE;
|
||||
mEmpty=PR_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method returns the typeid (the tag type) for this token.
|
||||
*
|
||||
@ -682,6 +701,18 @@ CAttributeToken::CAttributeToken(const nsString& aKey, const nsString& aName) :
|
||||
mLastAttribute=PR_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess8/4/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
void CAttributeToken::Reinitialize(PRInt32 aTag, const nsString& aString){
|
||||
CHTMLToken::Reinitialize(aTag,aString);
|
||||
mTextKey.Truncate();
|
||||
mLastAttribute=PR_FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
@ -949,6 +980,7 @@ CEntityToken::CEntityToken(const nsString& aName) : CHTMLToken(aName) {
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Consume the rest of the entity. We've already eaten the "&".
|
||||
*
|
||||
@ -1329,6 +1361,7 @@ nsresult CSkippedContentToken::Consume(PRUnichar,CScanner& aScanner) {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* This method iterates the tagtable to ensure that is
|
||||
|
||||
@ -71,6 +71,7 @@ const char* GetTagName(PRInt32 aTag);
|
||||
*/
|
||||
class CHTMLToken : public CToken {
|
||||
public:
|
||||
|
||||
CHTMLToken(eHTMLTags aTag);
|
||||
CHTMLToken(const nsString& aString);
|
||||
virtual void SetStringValue(const char* name);
|
||||
@ -99,6 +100,7 @@ class CStartToken: public CHTMLToken {
|
||||
PRBool IsEmpty(void);
|
||||
void SetEmpty(PRBool aValue);
|
||||
virtual void DebugDumpSource(ostream& out);
|
||||
virtual void Reinitialize(PRInt32 aTag, const nsString& aString);
|
||||
|
||||
protected:
|
||||
PRBool mAttributed;
|
||||
@ -225,6 +227,7 @@ class CAttributeToken: public CHTMLToken {
|
||||
virtual void DebugDumpToken(ostream& out);
|
||||
virtual void DebugDumpSource(ostream& out);
|
||||
PRBool mLastAttribute;
|
||||
virtual void Reinitialize(PRInt32 aTag, const nsString& aString);
|
||||
|
||||
protected:
|
||||
nsString mTextKey;
|
||||
|
||||
@ -44,8 +44,16 @@ class nsIDTDDebug;
|
||||
class nsIURL;
|
||||
class nsString;
|
||||
|
||||
|
||||
enum eAutoDetectResult {eUnknownDetect, eValidDetect, eInvalidDetect};
|
||||
|
||||
|
||||
class nsITokenRecycler {
|
||||
public:
|
||||
virtual void RecycleToken(CToken* aToken)=0;
|
||||
};
|
||||
|
||||
|
||||
class nsIDTD : public nsISupports {
|
||||
public:
|
||||
|
||||
@ -177,7 +185,17 @@ class nsIDTD : public nsISupports {
|
||||
*/
|
||||
virtual PRBool Verify(nsString& aURLRef)=0;
|
||||
|
||||
/**
|
||||
* Retrieve a ptr to the global token recycler...
|
||||
* @update gess8/4/98
|
||||
* @return ptr to recycler (or null)
|
||||
*/
|
||||
virtual nsITokenRecycler* GetTokenRecycler(void)=0;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* nsIDTD_h___ */
|
||||
|
||||
|
||||
@ -93,7 +93,7 @@ public:
|
||||
|
||||
void RegisterDTD(nsIDTD* aDTD){
|
||||
CDTDFinder theFinder(aDTD);
|
||||
if(!mDTDDeque.ForEach(theFinder))
|
||||
if(!mDTDDeque.FirstThat(theFinder))
|
||||
mDTDDeque.Push(aDTD);
|
||||
}
|
||||
|
||||
@ -383,6 +383,20 @@ PRInt32 nsParser::DidBuildModel(PRInt32 anErrorCode) {
|
||||
result=mParserContext->mDTD->DidBuildModel(anErrorCode,PRBool(0==mParserContext->mPrevContext));
|
||||
}
|
||||
|
||||
//Now it's time to recycle our used tokens.
|
||||
//The current context has a deque full of them,
|
||||
//and the ones that preceed currentpos are no
|
||||
//longer needed. Let's recycle them.
|
||||
nsDeque& theDeque=mParserContext->mTokenDeque;
|
||||
nsITokenRecycler* theRecycler=mParserContext->mDTD->GetTokenRecycler();
|
||||
if(theRecycler) {
|
||||
CToken* theToken=(CToken*)theDeque.Pop();
|
||||
while(theToken) {
|
||||
theRecycler->RecycleToken(theToken);
|
||||
theToken=(CToken*)theDeque.Pop();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -554,23 +568,6 @@ PRInt32 nsParser::BuildModel() {
|
||||
while((kNoError==result) && ((*mParserContext->mCurrentPos<e))){
|
||||
mMinorIteration++;
|
||||
CToken* theToken=(CToken*)mParserContext->mCurrentPos->GetCurrent();
|
||||
|
||||
/**************************************************************************
|
||||
The point of this code to serve as a testbed for parser reentrancy.
|
||||
If you set recurse=1, we go reentrant, passing a text string of HTML onto
|
||||
the parser for inline processing, just like javascript/DOM would do it.
|
||||
And guess what? It worked the first time!
|
||||
Uncomment the following code to enable the test:
|
||||
|
||||
int recurse=0;
|
||||
if(recurse){
|
||||
nsString theString(" this is just a great big empty string ");
|
||||
// nsString theString("<P>doc.write");
|
||||
// nsString theString("<table border=1><tr><td BGCOLOR=blue>cell</td></tr></table>");
|
||||
Parse(theString,PR_TRUE);
|
||||
}
|
||||
*/
|
||||
|
||||
theMarkPos=*mParserContext->mCurrentPos;
|
||||
++(*mParserContext->mCurrentPos);
|
||||
result=theRootDTD->HandleToken(theToken);
|
||||
@ -578,9 +575,25 @@ PRInt32 nsParser::BuildModel() {
|
||||
theRootDTD->Verify(kEmptyString);
|
||||
}
|
||||
|
||||
if(kInterrupted==result)
|
||||
if(kInterrupted==result) {
|
||||
*mParserContext->mCurrentPos=theMarkPos;
|
||||
|
||||
//Now it's time to recycle our used tokens.
|
||||
//The current context has a deque full of them,
|
||||
//and the ones that preceed currentpos are no
|
||||
//longer needed. Let's recycle them.
|
||||
nsITokenRecycler* theRecycler=theRootDTD->GetTokenRecycler();
|
||||
if(theRecycler) {
|
||||
nsDeque& theDeque=mParserContext->mTokenDeque;
|
||||
CToken* theCurrentToken=(CToken*)mParserContext->mCurrentPos->GetCurrent();
|
||||
CToken* theToken=(CToken*)theDeque.Peek();
|
||||
while(theToken && (theToken!=theCurrentToken)) {
|
||||
theDeque.Pop();
|
||||
theRecycler->RecycleToken(theToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@ -19,6 +19,13 @@
|
||||
#include "nsToken.h"
|
||||
#include "nsScanner.h"
|
||||
|
||||
static int TokenCount=0;
|
||||
|
||||
|
||||
/**************************************************************
|
||||
And now for the CToken...
|
||||
**************************************************************/
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*
|
||||
@ -27,6 +34,7 @@
|
||||
CToken::CToken(PRInt32 aTag) : mTextValue() {
|
||||
mTypeID=aTag;
|
||||
mAttrCount=0;
|
||||
TokenCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -38,6 +46,7 @@ CToken::CToken(PRInt32 aTag) : mTextValue() {
|
||||
CToken::CToken(const nsString& aName) : mTextValue(aName) {
|
||||
mTypeID=0;
|
||||
mAttrCount=0;
|
||||
TokenCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -49,6 +58,7 @@ CToken::CToken(const nsString& aName) : mTextValue(aName) {
|
||||
CToken::CToken(const char* aName) : mTextValue(aName) {
|
||||
mTypeID=0;
|
||||
mAttrCount=0;
|
||||
TokenCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -69,7 +79,11 @@ CToken::~CToken() {
|
||||
* @param aString
|
||||
*/
|
||||
void CToken::Reinitialize(PRInt32 aTag, const nsString& aString){
|
||||
mTypeID=0;
|
||||
if(0==aString.Length())
|
||||
mTextValue.Truncate(0);
|
||||
else mTextValue.SetString(aString);
|
||||
mAttrCount=0;
|
||||
mTypeID=aTag;
|
||||
mAttrCount=0;
|
||||
}
|
||||
|
||||
@ -211,6 +225,7 @@ const char* CToken::GetClassName(void) {
|
||||
return "token";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess 3/25/98
|
||||
|
||||
@ -41,6 +41,7 @@
|
||||
|
||||
class CScanner;
|
||||
|
||||
|
||||
/**
|
||||
* Token objects represent sequences of characters as they
|
||||
* are consumed from the input stream (URL). While they're
|
||||
|
||||
@ -356,3 +356,13 @@ NS_IMETHODIMP CValidDTD::HandleToken(CToken* aToken) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess8/4/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
nsITokenRecycler* CValidDTD::GetTokenRecycler(void){
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -210,7 +210,14 @@ class CValidDTD : public nsIDTD {
|
||||
* @return PR_TRUE if parent can contain child
|
||||
*/
|
||||
virtual PRBool CanContain(PRInt32 aParent,PRInt32 aChild);
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve a ptr to the global token recycler...
|
||||
* @update gess8/4/98
|
||||
* @return ptr to recycler (or null)
|
||||
*/
|
||||
virtual nsITokenRecycler* GetTokenRecycler(void);
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
|
||||
@ -343,3 +343,13 @@ NS_IMETHODIMP CWellFormedDTD::HandleToken(CToken* aToken) {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess8/4/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
nsITokenRecycler* CWellFormedDTD::GetTokenRecycler(void){
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -200,7 +200,14 @@ class CWellFormedDTD : public nsIDTD {
|
||||
* @return PR_TRUE if parent can contain child
|
||||
*/
|
||||
virtual PRBool CanContain(PRInt32 aParent,PRInt32 aChild);
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve a ptr to the global token recycler...
|
||||
* @update gess8/4/98
|
||||
* @return ptr to recycler (or null)
|
||||
*/
|
||||
virtual nsITokenRecycler* GetTokenRecycler(void);
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
|
||||
@ -160,7 +160,7 @@ eXIFTags DetermineXIFTagType(const nsString& aString)
|
||||
|
||||
while(low<=high){
|
||||
middle=(PRInt32)(low+high)/2;
|
||||
result=aString.Compare(gXIFTagTable[middle].mName, PR_TRUE);
|
||||
result=aString.Compare(gXIFTagTable[middle].mName, PR_TRUE);
|
||||
if (result==0)
|
||||
return gXIFTagTable[middle].fTagID;
|
||||
if (result<0)
|
||||
@ -1736,16 +1736,6 @@ PRInt32 nsXIFDTD::CollectSkippedContent(nsCParserNode& aNode,PRInt32& aCount) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gpk 06/18/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
CToken* nsXIFDTD::CreateTokenOfType(eHTMLTokenTypes aType) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
@ -1989,3 +1979,13 @@ void nsXIFDTD::AddCSSDeclaration(const nsIParserNode& aNode)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @update gess8/4/98
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
nsITokenRecycler* nsXIFDTD::GetTokenRecycler(void){
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -499,14 +499,6 @@ private:
|
||||
****************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* Called to cause delegate to create a token of given type.
|
||||
* @update gpk 06/18/98
|
||||
* @param aType represents the kind of token you want to create.
|
||||
* @return new token or NULL
|
||||
*/
|
||||
CToken* CreateTokenOfType(eHTMLTokenTypes aType);
|
||||
|
||||
/**
|
||||
* Retrieve the next TAG from the given scanner.
|
||||
* @update gpk 06/18/98
|
||||
@ -627,6 +619,12 @@ private:
|
||||
void PopAndDelete();
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve a ptr to the global token recycler...
|
||||
* @update gess8/4/98
|
||||
* @return ptr to recycler (or null)
|
||||
*/
|
||||
virtual nsITokenRecycler* GetTokenRecycler(void);
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user