LCOV - code coverage report
Current view: directory - parser/htmlparser/src - nsDTDUtils.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 381 171 44.9 %
Date: 2012-06-02 Functions: 48 27 56.2 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* vim: set ts=2 sw=2 et tw=80: */
       3                 : /* ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is mozilla.org code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * Netscape Communications Corporation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Pierre Phaneuf <pp@ludusdesign.com>
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      28                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 :        
      40                 :   
      41                 : #include "nsIAtom.h"
      42                 : #include "nsDTDUtils.h" 
      43                 : #include "CNavDTD.h" 
      44                 : #include "nsIParserNode.h"
      45                 : #include "nsParserNode.h" 
      46                 : #include "nsIChannel.h"
      47                 : #include "nsIServiceManager.h"
      48                 : #include "nsUnicharUtils.h"
      49                 : 
      50                 : /**************************************************************************************
      51                 :   A few notes about how residual style handling is performed:
      52                 :    
      53                 :     1. The style stack contains nsTagEntry elements. 
      54                 :     2. Every tag on the containment stack can have it's own residual style stack.
      55                 :     3. When a style leaks, it's mParent member is set to the level on the stack where 
      56                 :        it originated. A node with an mParent of 0 is not opened on tag stack, 
      57                 :        but is open on stylestack.
      58                 :     4. An easy way to tell that a container on the element stack is a residual style tag
      59                 :        is that it's use count is >1.
      60                 : 
      61                 :  **************************************************************************************/
      62                 : 
      63                 : 
      64                 : /**
      65                 :  * Default constructor
      66                 :  * @update      harishd 04/04/99
      67                 :  * @update  gess 04/22/99
      68                 :  */
      69              28 : nsEntryStack::nsEntryStack()  {
      70                 : 
      71              28 :   MOZ_COUNT_CTOR(nsEntryStack);
      72                 :   
      73              28 :   mCapacity=0;
      74              28 :   mCount=0;
      75              28 :   mEntries=0;
      76              28 : }
      77                 : 
      78                 : /**
      79                 :  * Default destructor
      80                 :  * @update  harishd 04/04/99
      81                 :  * @update  gess 04/22/99
      82                 :  */
      83              28 : nsEntryStack::~nsEntryStack() {
      84                 : 
      85              28 :   MOZ_COUNT_DTOR(nsEntryStack);
      86                 : 
      87              28 :   if(mEntries) {
      88                 :     //add code here to recycle the node if you have one...  
      89              28 :     delete [] mEntries;
      90              28 :     mEntries=0;
      91                 :   }
      92                 : 
      93              28 :   mCount=mCapacity=0;
      94              28 : }
      95                 : 
      96                 : /**
      97                 :  * Release all objects in the entry stack
      98                 :  */
      99                 : void 
     100               0 : nsEntryStack::ReleaseAll(nsNodeAllocator* aNodeAllocator)
     101                 : {
     102               0 :   NS_ASSERTION(aNodeAllocator,"no allocator? - potential leak!");
     103                 : 
     104               0 :   if(aNodeAllocator) {
     105               0 :     NS_ASSERTION(mCount >= 0,"count should not be negative");
     106               0 :     while(mCount > 0) {
     107               0 :       nsCParserNode* node=this->Pop();
     108               0 :       IF_FREE(node,aNodeAllocator);
     109                 :     }
     110                 :   }
     111               0 : }
     112                 : 
     113                 : /**
     114                 :  * Resets state of stack to be empty.
     115                 :  * @update harishd 04/04/99
     116                 :  */
     117               0 : void nsEntryStack::Empty(void) {
     118               0 :   mCount=0;
     119               0 : }
     120                 : 
     121                 : 
     122                 : /**
     123                 :  * 
     124                 :  * @update  gess 04/22/99
     125                 :  */
     126             850 : void nsEntryStack::EnsureCapacityFor(PRInt32 aNewMax,PRInt32 aShiftOffset) {
     127             850 :   if(mCapacity<aNewMax){ 
     128                 : 
     129              28 :     const int kDelta=16;
     130                 : 
     131              28 :     PRInt32 theSize = kDelta * ((aNewMax / kDelta) + 1);
     132              56 :     nsTagEntry* temp=new nsTagEntry[theSize]; 
     133              28 :     mCapacity=theSize;
     134                 : 
     135              28 :     if(temp){ 
     136              28 :       PRInt32 index=0; 
     137              28 :       for(index=0;index<mCount;++index) {
     138               0 :         temp[aShiftOffset+index]=mEntries[index];
     139                 :       }
     140              28 :       if(mEntries) delete [] mEntries;
     141              28 :       mEntries=temp;
     142                 :     }
     143                 :     else{
     144                 :       //XXX HACK! This is very bad! We failed to get memory.
     145                 :     }
     146                 :   } //if
     147             850 : }
     148                 : 
     149                 : /**
     150                 :  * 
     151                 :  * @update  gess 04/22/99
     152                 :  */
     153             825 : void nsEntryStack::Push(nsCParserNode* aNode,
     154                 :                         nsEntryStack* aStyleStack, 
     155                 :                         bool aRefCntNode) 
     156                 : {
     157             825 :   if(aNode) {
     158             825 :     EnsureCapacityFor(mCount+1);
     159             825 :     mEntries[mCount].mTag = (eHTMLTags)aNode->GetNodeType();
     160             825 :     if (aRefCntNode) {
     161             147 :       aNode->mUseCount++;
     162             147 :       mEntries[mCount].mNode = const_cast<nsCParserNode*>(aNode);
     163             147 :       IF_HOLD(mEntries[mCount].mNode);
     164                 :     }
     165             825 :     mEntries[mCount].mParent=aStyleStack;
     166             825 :     mEntries[mCount++].mStyles=0;
     167                 :   }
     168             825 : }
     169                 : 
     170              25 : void nsEntryStack::PushTag(eHTMLTags aTag)
     171                 : {
     172              25 :   EnsureCapacityFor(mCount + 1);
     173              25 :   mEntries[mCount].mTag = aTag;
     174              25 :   mEntries[mCount].mParent = nsnull;
     175              25 :   mEntries[mCount].mStyles = nsnull;
     176              25 :   ++mCount;
     177              25 : }
     178                 : 
     179                 : 
     180                 : /**
     181                 :  * This method inserts the given node onto the front of this stack
     182                 :  *
     183                 :  * @update  gess 11/10/99
     184                 :  */
     185               0 : void nsEntryStack::PushFront(nsCParserNode* aNode,
     186                 :                              nsEntryStack* aStyleStack, 
     187                 :                              bool aRefCntNode) 
     188                 : {
     189               0 :   if(aNode) {
     190               0 :     if(mCount<mCapacity) {
     191               0 :       PRInt32 index=0; 
     192               0 :       for(index=mCount;index>0;index--) {
     193               0 :         mEntries[index]=mEntries[index-1];
     194                 :       }
     195                 :     }
     196                 :     else {
     197               0 :       EnsureCapacityFor(mCount+1,1);
     198                 :     }
     199               0 :     mEntries[0].mTag = (eHTMLTags)aNode->GetNodeType();
     200               0 :     if (aRefCntNode) {
     201               0 :       aNode->mUseCount++;
     202               0 :       mEntries[0].mNode = const_cast<nsCParserNode*>(aNode);
     203               0 :       IF_HOLD(mEntries[0].mNode);
     204                 :     }
     205               0 :     mEntries[0].mParent=aStyleStack;
     206               0 :     mEntries[0].mStyles=0;
     207               0 :     ++mCount;
     208                 :   }
     209               0 : }
     210                 : 
     211                 : /**
     212                 :  * 
     213                 :  * @update  gess 11/10/99
     214                 :  */
     215               0 : void nsEntryStack::Append(nsEntryStack *aStack) {
     216               0 :   if(aStack) {
     217                 : 
     218               0 :     PRInt32 theCount=aStack->mCount;
     219                 : 
     220               0 :     EnsureCapacityFor(mCount+aStack->mCount,0);
     221                 : 
     222               0 :     PRInt32 theIndex=0;
     223               0 :     for(theIndex=0;theIndex<theCount;++theIndex){
     224               0 :       mEntries[mCount]=aStack->mEntries[theIndex];
     225               0 :       mEntries[mCount++].mParent=0;
     226                 :     }
     227                 :   }
     228               0 : } 
     229                 :  
     230                 : /**
     231                 :  * This method removes the node for the given tag
     232                 :  * from anywhere within this entry stack, and shifts
     233                 :  * other entries down.
     234                 :  * 
     235                 :  * NOTE: It's odd to be removing an element from the middle
     236                 :  *       of a stack, but it's necessary because of how MALFORMED
     237                 :  *       html can be. 
     238                 :  * 
     239                 :  * anIndex: the index within the stack of the tag to be removed
     240                 :  * aTag: the id of the tag to be removed
     241                 :  * @update  gess 02/25/00
     242                 :  */
     243               0 : nsCParserNode* nsEntryStack::Remove(PRInt32 anIndex,
     244                 :                                     eHTMLTags aTag) 
     245                 : {
     246               0 :   nsCParserNode* result = 0;
     247               0 :   if (0 < mCount && anIndex < mCount){
     248               0 :     result = mEntries[anIndex].mNode;
     249               0 :     if (result)
     250               0 :       result->mUseCount--;
     251               0 :     PRInt32 theIndex = 0;
     252               0 :     mCount -= 1;
     253               0 :     for( theIndex = anIndex; theIndex < mCount; ++theIndex){
     254               0 :       mEntries[theIndex] = mEntries[theIndex+1];
     255                 :     }
     256               0 :     mEntries[mCount].mNode = 0;
     257               0 :     mEntries[mCount].mStyles = 0;
     258               0 :     nsEntryStack* theStyleStack = mEntries[anIndex].mParent;
     259               0 :     if (theStyleStack) {
     260                 :       //now we have to tell the residual style stack where this tag
     261                 :       //originated that it's no longer in use.
     262               0 :       PRUint32 scount = theStyleStack->mCount;
     263                 : #ifdef DEBUG_mrbkap
     264                 :       NS_ASSERTION(scount != 0, "RemoveStyles has a bad style stack");
     265                 : #endif
     266               0 :       nsTagEntry *theStyleEntry = theStyleStack->mEntries;
     267               0 :       for (PRUint32 sindex = scount-1;; --sindex) {            
     268               0 :         if (theStyleEntry->mTag == aTag) {
     269                 :           // This tells us that the style is not open at any level.
     270               0 :           theStyleEntry->mParent = nsnull;
     271               0 :           break;
     272                 :         }
     273               0 :         if (sindex == 0) {
     274                 : #ifdef DEBUG_mrbkap
     275                 :           NS_ERROR("Couldn't find the removed style on its parent stack");
     276                 : #endif
     277               0 :           break;
     278                 :         }
     279               0 :         ++theStyleEntry;
     280                 :       }
     281                 :     }
     282                 :   }
     283               0 :   return result;
     284                 : }
     285                 : 
     286                 : /**
     287                 :  * Pops an entry from this style stack. If the entry has a parent stack, it
     288                 :  * updates the entry so that we know not to try to remove it from the parent
     289                 :  * stack since it's no longer open.
     290                 :  */
     291             850 : nsCParserNode* nsEntryStack::Pop(void)
     292                 : {
     293             850 :   nsCParserNode* result = 0;
     294             850 :   if (0 < mCount) {
     295             850 :     result = mEntries[--mCount].mNode;
     296             850 :     if (result)
     297             147 :       result->mUseCount--;
     298             850 :     mEntries[mCount].mNode = 0;
     299             850 :     mEntries[mCount].mStyles = 0;
     300             850 :     nsEntryStack* theStyleStack = mEntries[mCount].mParent;
     301             850 :     if (theStyleStack) {
     302                 :       //now we have to tell the residual style stack where this tag
     303                 :       //originated that it's no longer in use.
     304               0 :       PRUint32 scount = theStyleStack->mCount;
     305                 : 
     306                 :       // XXX If this NS_ENSURE_TRUE fails, it means that the style stack was
     307                 :       //     empty before we were removed.
     308                 : #ifdef DEBUG_mrbkap
     309                 :       NS_ASSERTION(scount != 0, "preventing a potential crash.");
     310                 : #endif
     311               0 :       NS_ENSURE_TRUE(scount != 0, result);
     312                 : 
     313               0 :       nsTagEntry *theStyleEntry = theStyleStack->mEntries;
     314               0 :       for (PRUint32 sindex = scount - 1;; --sindex) {
     315               0 :         if (theStyleEntry->mTag == mEntries[mCount].mTag) {
     316                 :           // This tells us that the style is not open at any level
     317               0 :           theStyleEntry->mParent = nsnull;
     318               0 :           break;
     319                 :         }
     320               0 :         if (sindex == 0) {
     321                 : #ifdef DEBUG_mrbkap
     322                 :           NS_ERROR("Couldn't find the removed style on its parent stack");
     323                 : #endif
     324               0 :           break;
     325                 :         }
     326               0 :         ++theStyleEntry;
     327                 :       }
     328                 :     }
     329                 :   }
     330             850 :   return result;
     331                 : } 
     332                 : 
     333                 : /**
     334                 :  * 
     335                 :  * @update  harishd 04/04/99
     336                 :  * @update  gess 04/21/99
     337                 :  */
     338               0 : eHTMLTags nsEntryStack::First() const 
     339                 : {
     340               0 :   eHTMLTags result=eHTMLTag_unknown;
     341               0 :   if(0<mCount){
     342               0 :     result=mEntries[0].mTag;
     343                 :   }
     344               0 :   return result;
     345                 : }
     346                 : 
     347                 : /**
     348                 :  * 
     349                 :  * @update  harishd 04/04/99
     350                 :  * @update  gess 04/21/99
     351                 :  */
     352              61 : nsCParserNode* nsEntryStack::NodeAt(PRInt32 anIndex) const 
     353                 : {
     354              61 :   nsCParserNode* result=0;
     355              61 :   if((0<mCount) && (anIndex<mCount)) {
     356              61 :     result=mEntries[anIndex].mNode;
     357                 :   }
     358              61 :   return result;
     359                 : }
     360                 : 
     361                 : /**
     362                 :  * 
     363                 :  * @update  harishd 04/04/99
     364                 :  * @update  gess 04/21/99
     365                 :  */
     366            8141 : eHTMLTags nsEntryStack::TagAt(PRInt32 anIndex) const 
     367                 : {
     368            8141 :   eHTMLTags result=eHTMLTag_unknown;
     369            8141 :   if((0<mCount) && (anIndex<mCount)) {
     370            8113 :     result=mEntries[anIndex].mTag;
     371                 :   }
     372            8141 :   return result;
     373                 : }
     374                 : 
     375                 : /**
     376                 :  * 
     377                 :  * @update  gess 04/21/99
     378                 :  */
     379            4463 : nsTagEntry* nsEntryStack::EntryAt(PRInt32 anIndex) const 
     380                 : {
     381            4463 :   nsTagEntry *result=0;
     382            4463 :   if((0<mCount) && (anIndex<mCount)) {
     383            4463 :     result=&mEntries[anIndex];
     384                 :   }
     385            4463 :   return result;
     386                 : }
     387                 : 
     388                 : 
     389                 : /**
     390                 :  * 
     391                 :  * @update  harishd 04/04/99
     392                 :  * @update  gess 04/21/99
     393                 :  */
     394               0 : eHTMLTags nsEntryStack::operator[](PRInt32 anIndex) const 
     395                 : {
     396               0 :   eHTMLTags result=eHTMLTag_unknown;
     397               0 :   if((0<mCount) && (anIndex<mCount)) {
     398               0 :     result=mEntries[anIndex].mTag;
     399                 :   }
     400               0 :   return result;
     401                 : }
     402                 : 
     403                 : 
     404                 : /**
     405                 :  * 
     406                 :  * @update  harishd 04/04/99
     407                 :  * @update  gess 04/21/99
     408                 :  */
     409            3718 : eHTMLTags nsEntryStack::Last(void) const 
     410                 : {
     411            3718 :   eHTMLTags result=eHTMLTag_unknown;
     412            3718 :   if(0<mCount) {
     413            3690 :     result=mEntries[mCount-1].mTag;
     414                 :   }
     415            3718 :   return result;
     416                 : }
     417                 : 
     418                 : nsTagEntry*
     419               0 : nsEntryStack::PopEntry() 
     420                 : {
     421               0 :   nsTagEntry* entry = EntryAt(mCount-1);
     422               0 :   this->Pop();
     423               0 :   return entry;
     424                 : }
     425                 : 
     426               0 : void nsEntryStack::PushEntry(nsTagEntry* aEntry, 
     427                 :                              bool aRefCntNode) 
     428                 : {
     429               0 :   if (aEntry) {
     430               0 :     EnsureCapacityFor(mCount+1);
     431               0 :     mEntries[mCount].mNode   = aEntry->mNode;
     432               0 :     mEntries[mCount].mTag    = aEntry->mTag;
     433               0 :     mEntries[mCount].mParent = aEntry->mParent;
     434               0 :     mEntries[mCount].mStyles = aEntry->mStyles;
     435               0 :     if (aRefCntNode && mEntries[mCount].mNode) {
     436               0 :       mEntries[mCount].mNode->mUseCount++;
     437               0 :       IF_HOLD(mEntries[mCount].mNode);
     438                 :     }
     439               0 :     mCount++;
     440                 :   }
     441               0 : }
     442                 : 
     443                 : /***************************************************************
     444                 :   Now define the dtdcontext class
     445                 :  ***************************************************************/
     446                 : 
     447                 : 
     448                 : /**
     449                 :  * 
     450                 :  * @update      gess 04.21.2000
     451                 :  */
     452              28 : nsDTDContext::nsDTDContext() : mStack()
     453                 : {
     454              28 :   MOZ_COUNT_CTOR(nsDTDContext);
     455              28 :   mResidualStyleCount=0;
     456              28 :   mContextTopIndex=-1;
     457              28 :   mTokenAllocator=0;
     458              28 :   mNodeAllocator=0;
     459                 : 
     460                 : #ifdef DEBUG
     461              28 :   memset(mXTags,0,sizeof(mXTags));
     462                 : #endif
     463              28 : } 
     464                 :  
     465                 : /**
     466                 :  * 
     467                 :  * @update      gess9/10/98
     468                 :  */
     469              56 : nsDTDContext::~nsDTDContext()
     470                 : {
     471              28 :   MOZ_COUNT_DTOR(nsDTDContext);
     472              28 : }
     473                 : 
     474                 : 
     475                 : /**
     476                 :  * 
     477                 :  * @update  gess7/9/98
     478                 :  */
     479             109 : bool nsDTDContext::HasOpenContainer(eHTMLTags aTag) const {
     480             109 :   PRInt32 theIndex=mStack.LastOf(aTag);
     481             109 :   return bool(-1<theIndex);
     482                 : }
     483                 : 
     484                 : /**
     485                 :  * 
     486                 :  * @update  gess7/9/98
     487                 :  */
     488             825 : void nsDTDContext::Push(nsCParserNode* aNode,
     489                 :                         nsEntryStack* aStyleStack, 
     490                 :                         bool aRefCntNode) {
     491             825 :   if(aNode) {
     492                 : #ifdef  NS_DEBUG
     493             825 :     eHTMLTags theTag = (eHTMLTags)aNode->GetNodeType();
     494             825 :     int size = mStack.mCount;
     495             825 :     if (size < eMaxTags)
     496             825 :       mXTags[size] = theTag;
     497                 : #endif
     498             825 :     mStack.Push(aNode, aStyleStack, aRefCntNode);
     499                 :   }
     500             825 : }
     501                 : 
     502              25 : void nsDTDContext::PushTag(eHTMLTags aTag)
     503                 : {
     504                 : #ifdef NS_DEBUG
     505              25 :   if (mStack.mCount < eMaxTags) {
     506              25 :     mXTags[mStack.mCount] = aTag;
     507                 :   }
     508                 : #endif
     509                 : 
     510              25 :   mStack.PushTag(aTag);
     511              25 : }
     512                 : 
     513                 : nsTagEntry*
     514               0 : nsDTDContext::PopEntry()
     515                 : {
     516               0 :   PRInt32 theSize = mStack.mCount;
     517               0 :   if(0<theSize) {
     518                 : #ifdef  NS_DEBUG
     519               0 :     if (theSize <= eMaxTags)
     520               0 :       mXTags[theSize-1]=eHTMLTag_unknown;
     521                 : #endif
     522               0 :     return mStack.PopEntry();
     523                 :   }
     524               0 :   return 0;
     525                 : }
     526                 : 
     527               0 : void nsDTDContext::PushEntry(nsTagEntry* aEntry, 
     528                 :                              bool aRefCntNode)
     529                 : {
     530                 : #ifdef  NS_DEBUG
     531               0 :     int size=mStack.mCount;
     532               0 :     if(size< eMaxTags && aEntry)
     533               0 :       mXTags[size]=aEntry->mTag;
     534                 : #endif
     535               0 :     mStack.PushEntry(aEntry, aRefCntNode);
     536               0 : }
     537                 : 
     538                 : /* This method will move the top entries, in the entry-stack, into dest context.
     539                 :  * @param aDest  - Destination context for the entries.
     540                 :  * @param aCount - Number of entries, on top of the entry-stack, to be moved.
     541                 :  */
     542                 : void 
     543               0 : nsDTDContext::MoveEntries(nsDTDContext& aDest,
     544                 :                           PRInt32 aCount)
     545                 : {
     546               0 :   NS_ASSERTION(aCount > 0 && mStack.mCount >= aCount, "cannot move entries");
     547               0 :   if (aCount > 0 && mStack.mCount >= aCount) {
     548               0 :     while (aCount) {
     549               0 :       aDest.PushEntry(&mStack.mEntries[--mStack.mCount], false);
     550                 : #ifdef  NS_DEBUG
     551               0 :       if (mStack.mCount < eMaxTags) {
     552               0 :         mXTags[mStack.mCount] = eHTMLTag_unknown;
     553                 :       }
     554                 : #endif
     555               0 :       --aCount;
     556                 :     }
     557                 :   }
     558               0 : }
     559                 : 
     560                 : /** 
     561                 :  * @update  gess 11/11/99, 
     562                 :  *          harishd 04/04/99
     563                 :  */
     564             850 : nsCParserNode* nsDTDContext::Pop(nsEntryStack *&aChildStyleStack) {
     565                 : 
     566             850 :   PRInt32         theSize=mStack.mCount;
     567             850 :   nsCParserNode*  result=0;
     568                 : 
     569             850 :   if(0<theSize) {
     570                 : 
     571                 : #ifdef  NS_DEBUG
     572             850 :     if ((theSize>0) && (theSize <= eMaxTags))
     573             850 :       mXTags[theSize-1]=eHTMLTag_unknown;
     574                 : #endif
     575                 : 
     576                 : 
     577             850 :     nsTagEntry* theEntry=mStack.EntryAt(mStack.mCount-1);
     578             850 :     aChildStyleStack=theEntry->mStyles;
     579                 : 
     580             850 :     result=mStack.Pop();
     581             850 :     theEntry->mParent=0;
     582                 :   }
     583                 : 
     584             850 :   return result;
     585                 : }
     586                 :  
     587                 : /**
     588                 :  * 
     589                 :  * @update  harishd 04/07/00
     590                 :  */
     591                 : 
     592               0 : nsCParserNode* nsDTDContext::Pop() {
     593               0 :   nsEntryStack   *theTempStyleStack=0; // This has no use here...
     594               0 :   return Pop(theTempStyleStack);
     595                 : }
     596                 : 
     597                 : /**
     598                 :  * 
     599                 :  * @update  gess7/9/98
     600                 :  */
     601               0 : eHTMLTags nsDTDContext::First(void) const {
     602               0 :   return mStack.First();
     603                 : }
     604                 : 
     605                 : /**
     606                 :  * 
     607                 :  * @update  gess7/9/98
     608                 :  */
     609            8141 : eHTMLTags nsDTDContext::TagAt(PRInt32 anIndex) const {
     610            8141 :   return mStack.TagAt(anIndex);
     611                 : }
     612                 : 
     613                 : /**
     614                 :  * 
     615                 :  * @update  gess7/9/98
     616                 :  */
     617               0 : nsTagEntry* nsDTDContext::LastEntry(void) const {
     618               0 :   return mStack.EntryAt(mStack.mCount-1);
     619                 : }
     620                 : 
     621                 : /**
     622                 :  *  
     623                 :  * @update  gess7/9/98
     624                 :  */
     625            3718 : eHTMLTags nsDTDContext::Last() const {
     626            3718 :   return mStack.Last();
     627                 : }
     628                 : 
     629                 : 
     630                 : /**
     631                 :  * 
     632                 :  * @update  gess7/9/98
     633                 :  */
     634            3613 : nsEntryStack* nsDTDContext::GetStylesAt(PRInt32 anIndex) const {
     635            3613 :   nsEntryStack* result=0;
     636                 : 
     637            3613 :   if(anIndex<mStack.mCount){
     638            3613 :     nsTagEntry* theEntry=mStack.EntryAt(anIndex);
     639            3613 :     if(theEntry) {
     640            3613 :       result=theEntry->mStyles;
     641                 :     }
     642                 :   }
     643            3613 :   return result;
     644                 : }
     645                 : 
     646                 : 
     647                 : /**
     648                 :  * 
     649                 :  * @update  gess 04/28/99
     650                 :  */
     651               0 : void nsDTDContext::PushStyle(nsCParserNode* aNode){
     652                 : 
     653               0 :   nsTagEntry* theEntry=mStack.EntryAt(mStack.mCount-1);
     654               0 :   if(theEntry ) {
     655               0 :     nsEntryStack* theStack=theEntry->mStyles;
     656               0 :     if(!theStack) {
     657               0 :       theStack=theEntry->mStyles=new nsEntryStack();
     658                 :     }
     659               0 :     if(theStack) {
     660               0 :       theStack->Push(aNode);
     661               0 :       ++mResidualStyleCount;
     662                 :     }
     663                 :   } //if
     664               0 : }
     665                 : 
     666                 : 
     667                 : /**
     668                 :  * Call this when you have an EntryStack full of styles
     669                 :  * that you want to push at this level.
     670                 :  * 
     671                 :  * @update  gess 04/28/99
     672                 :  */
     673               0 : void nsDTDContext::PushStyles(nsEntryStack *aStyles){
     674                 : 
     675               0 :   if(aStyles) {
     676               0 :     nsTagEntry* theEntry=mStack.EntryAt(mStack.mCount-1);
     677               0 :     if(theEntry ) {
     678               0 :       nsEntryStack* theStyles=theEntry->mStyles;
     679               0 :       if(!theStyles) {
     680               0 :         theEntry->mStyles=aStyles;
     681                 : 
     682               0 :         PRUint32 scount=aStyles->mCount;
     683               0 :         PRUint32 sindex=0;
     684                 : 
     685               0 :         theEntry=aStyles->mEntries;
     686               0 :         for(sindex=0;sindex<scount;++sindex){            
     687               0 :           theEntry->mParent=0;  //this tells us that the style is not open at any level
     688               0 :           ++theEntry;
     689               0 :           ++mResidualStyleCount;
     690                 :         } //for
     691                 : 
     692                 :       }
     693                 :       else {
     694               0 :         theStyles->Append(aStyles);
     695                 :         //  Delete aStyles since it has been copied to theStyles...
     696               0 :         delete aStyles;
     697               0 :         aStyles=0;
     698                 :       }
     699                 :     } //if(theEntry )
     700               0 :     else if(mStack.mCount==0) {
     701                 :       // If you're here it means that we have hit the rock bottom
     702                 :       // ,of the stack, and there's no need to handle anymore styles.
     703                 :       // Fix for bug 29048
     704               0 :       IF_DELETE(aStyles,mNodeAllocator);
     705                 :     }
     706                 :   }//if(aStyles)
     707               0 : }
     708                 : 
     709                 : 
     710                 : /** 
     711                 :  * 
     712                 :  * @update  gess 04/28/99
     713                 :  */
     714               0 : nsCParserNode* nsDTDContext::PopStyle(void){
     715               0 :   nsCParserNode *result=0;
     716                 : 
     717               0 :   nsTagEntry *theEntry=mStack.EntryAt(mStack.mCount-1);
     718               0 :   if(theEntry && (theEntry->mNode)) {
     719               0 :     nsEntryStack* theStyleStack=theEntry->mParent;
     720               0 :     if(theStyleStack){
     721               0 :       result=theStyleStack->Pop();
     722               0 :       mResidualStyleCount--;
     723                 :     }
     724                 :   } //if
     725               0 :   return result;
     726                 : }
     727                 : 
     728                 : /** 
     729                 :  * 
     730                 :  * @update  gess 04/28/99
     731                 :  */
     732               0 : nsCParserNode* nsDTDContext::PopStyle(eHTMLTags aTag){
     733                 : 
     734               0 :   PRInt32 theLevel=0;
     735               0 :   nsCParserNode* result=0;
     736                 : 
     737               0 :   for(theLevel=mStack.mCount-1;theLevel>0;theLevel--) {
     738               0 :     nsEntryStack *theStack=mStack.mEntries[theLevel].mStyles;
     739               0 :     if(theStack) {
     740               0 :       if(aTag==theStack->Last()) {
     741               0 :         result=theStack->Pop();
     742               0 :         mResidualStyleCount--;
     743               0 :         break; // Fix bug 50710 - Stop after finding a style.
     744                 :       } else {
     745                 :         // NS_ERROR("bad residual style entry");
     746                 :       }
     747                 :     } 
     748                 :   }
     749                 : 
     750               0 :   return result;
     751                 : }
     752                 : 
     753                 : /** 
     754                 :  * 
     755                 :  * This is similar to popstyle, except that it removes the
     756                 :  * style tag given from anywhere in the style stack, and
     757                 :  * not just at the top.
     758                 :  *
     759                 :  * @update  gess 01/26/00
     760                 :  */
     761               0 : void nsDTDContext::RemoveStyle(eHTMLTags aTag){
     762                 :   
     763               0 :   PRInt32 theLevel=mStack.mCount;
     764                 :   
     765               0 :   while (theLevel) {
     766               0 :     nsEntryStack *theStack=GetStylesAt(--theLevel);
     767               0 :     if (theStack) {
     768               0 :       PRInt32 index=theStack->mCount;
     769               0 :       while (index){
     770               0 :         nsTagEntry *theEntry=theStack->EntryAt(--index);
     771               0 :         if (aTag==(eHTMLTags)theEntry->mNode->GetNodeType()) {
     772               0 :           mResidualStyleCount--;
     773               0 :           nsCParserNode* result=theStack->Remove(index,aTag);
     774               0 :           IF_FREE(result, mNodeAllocator);  
     775               0 :           return;
     776                 :         } 
     777                 :       }
     778                 :     } 
     779                 :   }
     780                 : }
     781                 : 
     782                 : /**
     783                 :  * This gets called when the parser module is getting unloaded
     784                 :  * 
     785                 :  * @return  nada
     786                 :  */
     787             263 : void nsDTDContext::ReleaseGlobalObjects(void){
     788             263 : }
     789                 : 
     790                 : 
     791                 : /**************************************************************
     792                 :   Now define the nsTokenAllocator class...
     793                 :  **************************************************************/
     794                 : 
     795                 : static const size_t  kTokenBuckets[]       ={sizeof(CStartToken),sizeof(CAttributeToken),sizeof(CCommentToken),sizeof(CEndToken)};
     796                 : static const PRInt32 kNumTokenBuckets      = sizeof(kTokenBuckets) / sizeof(size_t);
     797                 : static const PRInt32 kInitialTokenPoolSize = NS_SIZE_IN_HEAP(sizeof(CToken)) * 200;
     798                 : 
     799                 : /**
     800                 :  * 
     801                 :  * @update  gess7/25/98
     802                 :  * @param 
     803                 :  */
     804            3345 : nsTokenAllocator::nsTokenAllocator() {
     805                 : 
     806            3345 :   MOZ_COUNT_CTOR(nsTokenAllocator);
     807                 : 
     808            3345 :   mArenaPool.Init("TokenPool", kTokenBuckets, kNumTokenBuckets, kInitialTokenPoolSize);
     809                 : 
     810                 : #ifdef NS_DEBUG
     811            3345 :   int i=0;
     812           43485 :   for(i=0;i<eToken_last-1;++i) {
     813           40140 :     mTotals[i]=0;
     814                 :   }
     815                 : #endif
     816                 : 
     817            3345 : }
     818                 : 
     819                 : /**
     820                 :  * Destructor for the token factory
     821                 :  * @update  gess7/25/98
     822                 :  */
     823            6690 : nsTokenAllocator::~nsTokenAllocator() {
     824                 : 
     825            3345 :   MOZ_COUNT_DTOR(nsTokenAllocator);
     826                 : 
     827            3345 : }
     828                 : 
     829                 : class CTokenFinder: public nsDequeFunctor{
     830                 : public:
     831                 :   CTokenFinder(CToken* aToken) {mToken=aToken;}
     832                 :   virtual void* operator()(void* anObject) {
     833                 :     if(anObject==mToken) {
     834                 :       return anObject;
     835                 :     }
     836                 :     return 0;
     837                 :   }
     838                 :   CToken* mToken;
     839                 : };
     840                 : 
     841                 : /**
     842                 :  * Let's get this code ready to be reused by all the contexts.
     843                 :  * 
     844                 :  * @update      rickg 12June2000
     845                 :  * @param   aType -- tells you the type of token to create
     846                 :  * @param   aTag  -- tells you the type of tag to init with this token
     847                 :  * @param   aString -- gives a default string value for the token
     848                 :  *
     849                 :  * @return  ptr to new token (or 0).
     850                 :  */
     851              53 : CToken* nsTokenAllocator::CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag, const nsAString& aString) {
     852                 : 
     853              53 :   CToken* result=0;
     854                 : 
     855                 : #ifdef  NS_DEBUG
     856              53 :     mTotals[aType-1]++;
     857                 : #endif
     858              53 :   switch(aType){
     859              53 :     case eToken_start:            result=new(mArenaPool) CStartToken(aString, aTag); break;
     860               0 :     case eToken_end:              result=new(mArenaPool) CEndToken(aString, aTag); break;
     861               0 :     case eToken_comment:          result=new(mArenaPool) CCommentToken(aString); break;
     862               0 :     case eToken_entity:           result=new(mArenaPool) CEntityToken(aString); break;
     863               0 :     case eToken_whitespace:       result=new(mArenaPool) CWhitespaceToken(aString); break;
     864               0 :     case eToken_newline:          result=new(mArenaPool) CNewlineToken(); break;
     865               0 :     case eToken_text:             result=new(mArenaPool) CTextToken(aString); break;
     866               0 :     case eToken_attribute:        result=new(mArenaPool) CAttributeToken(aString); break;
     867               0 :     case eToken_instruction:      result=new(mArenaPool) CInstructionToken(aString); break;
     868               0 :     case eToken_cdatasection:     result=new(mArenaPool) CCDATASectionToken(aString); break;
     869               0 :     case eToken_doctypeDecl:      result=new(mArenaPool) CDoctypeDeclToken(aString); break;
     870               0 :     case eToken_markupDecl:       result=new(mArenaPool) CMarkupDeclToken(aString); break;
     871                 :       default:
     872               0 :         NS_ASSERTION(false, "nsDTDUtils::CreateTokenOfType: illegal token type"); 
     873               0 :         break;
     874                 :   }
     875                 : 
     876              53 :   return result;
     877                 : }
     878                 : 
     879                 : /**
     880                 :  * Let's get this code ready to be reused by all the contexts.
     881                 :  * 
     882                 :  * @update      rickg 12June2000
     883                 :  * @param   aType -- tells you the type of token to create
     884                 :  * @param   aTag  -- tells you the type of tag to init with this token
     885                 :  *
     886                 :  * @return  ptr to new token (or 0).
     887                 :  */
     888            3040 : CToken* nsTokenAllocator::CreateTokenOfType(eHTMLTokenTypes aType,eHTMLTags aTag) {
     889                 : 
     890            3040 :   CToken* result=0;
     891                 : 
     892                 : #ifdef  NS_DEBUG
     893            3040 :     mTotals[aType-1]++;
     894                 : #endif
     895            3040 :   switch(aType){
     896             797 :     case eToken_start:            result=new(mArenaPool) CStartToken(aTag); break;
     897             344 :     case eToken_end:              result=new(mArenaPool) CEndToken(aTag); break;
     898              25 :     case eToken_comment:          result=new(mArenaPool) CCommentToken(); break;
     899             732 :     case eToken_attribute:        result=new(mArenaPool) CAttributeToken(); break;
     900               0 :     case eToken_entity:           result=new(mArenaPool) CEntityToken(); break;
     901             281 :     case eToken_whitespace:       result=new(mArenaPool) CWhitespaceToken(); break;
     902             530 :     case eToken_newline:          result=new(mArenaPool) CNewlineToken(); break;
     903             306 :     case eToken_text:             result=new(mArenaPool) CTextToken(); break;
     904               0 :     case eToken_instruction:      result=new(mArenaPool) CInstructionToken(); break;
     905               0 :     case eToken_cdatasection:     result=new(mArenaPool) CCDATASectionToken(aTag); break;
     906              25 :     case eToken_doctypeDecl:      result=new(mArenaPool) CDoctypeDeclToken(aTag); break;
     907               0 :     case eToken_markupDecl:       result=new(mArenaPool) CMarkupDeclToken(); break;
     908                 :     default:
     909               0 :       NS_ASSERTION(false, "nsDTDUtils::CreateTokenOfType: illegal token type"); 
     910               0 :       break;
     911                 :    }
     912                 : 
     913            3040 :   return result;
     914                 : }
     915                 : 
     916                 : #ifdef DEBUG_TRACK_NODES 
     917                 : 
     918                 : static nsCParserNode* gAllNodes[100];
     919                 : static int gAllNodeCount=0;
     920                 : 
     921                 : int FindNode(nsCParserNode *aNode) {
     922                 :   int theIndex=0;
     923                 :   for(theIndex=0;theIndex<gAllNodeCount;++theIndex) {
     924                 :     if(gAllNodes[theIndex]==aNode) {
     925                 :       return theIndex;
     926                 :     }
     927                 :   }
     928                 :   return -1;
     929                 : }
     930                 : 
     931                 : void AddNode(nsCParserNode *aNode) {
     932                 :   if(-1==FindNode(aNode)) {
     933                 :     gAllNodes[gAllNodeCount++]=aNode;
     934                 :   }
     935                 :   else {
     936                 :     //you tried to recycle a node twice!
     937                 :   }
     938                 : }
     939                 : 
     940                 : void RemoveNode(nsCParserNode *aNode) {
     941                 :   int theIndex=FindNode(aNode);
     942                 :   if(-1<theIndex) {
     943                 :     gAllNodes[theIndex]=gAllNodes[--gAllNodeCount];
     944                 :   }
     945                 : }
     946                 : 
     947                 : #endif 
     948                 : 
     949                 : 
     950                 : #ifdef HEAP_ALLOCATED_NODES
     951                 : nsNodeAllocator::nsNodeAllocator():mSharedNodes(0){
     952                 : #ifdef DEBUG_TRACK_NODES
     953                 :   mCount=0;
     954                 : #endif
     955                 : #else 
     956                 :   static const size_t  kNodeBuckets[]       = { sizeof(nsCParserNode), sizeof(nsCParserStartNode) };
     957                 :   static const PRInt32 kNumNodeBuckets      = sizeof(kNodeBuckets) / sizeof(size_t);
     958                 :   static const PRInt32 kInitialNodePoolSize = NS_SIZE_IN_HEAP(sizeof(nsCParserNode)) * 35; // optimal size based on space-trace data
     959              28 : nsNodeAllocator::nsNodeAllocator() {
     960              28 :   mNodePool.Init("NodePool", kNodeBuckets, kNumNodeBuckets, kInitialNodePoolSize);
     961                 : #endif
     962              28 :   MOZ_COUNT_CTOR(nsNodeAllocator);
     963              28 : }
     964                 :   
     965              56 : nsNodeAllocator::~nsNodeAllocator() {
     966              28 :   MOZ_COUNT_DTOR(nsNodeAllocator);
     967                 : 
     968                 : #ifdef HEAP_ALLOCATED_NODES
     969                 :   nsCParserNode* theNode = 0;
     970                 : 
     971                 :   while((theNode=(nsCParserNode*)mSharedNodes.Pop())){
     972                 : #ifdef DEBUG_TRACK_NODES
     973                 :     RemoveNode(theNode);
     974                 : #endif
     975                 :     ::operator delete(theNode); 
     976                 :     theNode=nsnull;
     977                 :   }
     978                 : #ifdef DEBUG_TRACK_NODES
     979                 :   if(mCount) {
     980                 :     printf("**************************\n");
     981                 :     printf("%i out of %i nodes leaked!\n",gAllNodeCount,mCount);
     982                 :     printf("**************************\n");
     983                 :   }
     984                 : #endif
     985                 : #endif
     986              28 : }
     987                 :   
     988            1967 : nsCParserNode* nsNodeAllocator::CreateNode(CToken* aToken,  
     989                 :                                            nsTokenAllocator* aTokenAllocator) 
     990                 : {
     991            1967 :   nsCParserNode* result = 0;
     992                 : #ifdef HEAP_ALLOCATED_NODES
     993                 : #if 0
     994                 :   if(gAllNodeCount!=mSharedNodes.GetSize()) {
     995                 :     int x=10; //this is very BAD!
     996                 :   }
     997                 : #endif
     998                 :   result = static_cast<nsCParserNode*>(mSharedNodes.Pop());
     999                 :   if (result) {
    1000                 :     result->Init(aToken, aTokenAllocator,this);
    1001                 :   }
    1002                 :   else{
    1003                 :     result = nsCParserNode::Create(aToken, aTokenAllocator,this);
    1004                 : #ifdef DEBUG_TRACK_NODES
    1005                 :     ++mCount;
    1006                 :     AddNode(static_cast<nsCParserNode*>(result));
    1007                 : #endif
    1008                 :     IF_HOLD(result);
    1009                 :   }
    1010                 : #else
    1011            1967 :   eHTMLTokenTypes type = aToken ? eHTMLTokenTypes(aToken->GetTokenType()) : eToken_unknown;
    1012            1967 :   switch (type) {
    1013                 :     case eToken_start:
    1014             850 :       result = nsCParserStartNode::Create(aToken, aTokenAllocator,this); 
    1015             850 :       break;
    1016                 :     default :
    1017            1117 :       result = nsCParserNode::Create(aToken, aTokenAllocator,this); 
    1018            1117 :       break;
    1019                 :   }
    1020            1967 :   IF_HOLD(result);
    1021                 : #endif
    1022            1967 :   return result;
    1023                 : }
    1024                 : 
    1025                 : #ifdef DEBUG
    1026               0 : void DebugDumpContainmentRules(nsIDTD& theDTD,const char* aFilename,const char* aTitle) {
    1027               0 : }
    1028                 : #endif

Generated by: LCOV version 1.7