GME  13
ElemStack.cpp
Go to the documentation of this file.
00001 /*
00002  * Licensed to the Apache Software Foundation (ASF) under one or more
00003  * contributor license agreements.  See the NOTICE file distributed with
00004  * this work for additional information regarding copyright ownership.
00005  * The ASF licenses this file to You under the Apache License, Version 2.0
00006  * (the "License"); you may not use this file except in compliance with
00007  * the License.  You may obtain a copy of the License at
00008  * 
00009  *      http://www.apache.org/licenses/LICENSE-2.0
00010  * 
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 /*
00019  * $Id: ElemStack.cpp 830538 2009-10-28 13:41:11Z amassari $
00020  */
00021 
00022 // ---------------------------------------------------------------------------
00023 //  Includes
00024 // ---------------------------------------------------------------------------
00025 #include <string.h>
00026 #include <xercesc/util/EmptyStackException.hpp>
00027 #include <xercesc/util/NoSuchElementException.hpp>
00028 #include <xercesc/framework/XMLElementDecl.hpp>
00029 #include <xercesc/internal/ElemStack.hpp>
00030 #include <xercesc/validators/common/Grammar.hpp>
00031 
00032 XERCES_CPP_NAMESPACE_BEGIN
00033 
00034 // ---------------------------------------------------------------------------
00035 //  ElemStack: Constructors and Destructor
00036 // ---------------------------------------------------------------------------
00037 ElemStack::ElemStack(MemoryManager* const manager) :
00038 
00039     fEmptyNamespaceId(0)
00040     , fGlobalPoolId(0)
00041     , fPrefixPool(109, manager)
00042     , fGlobalNamespaces(0)
00043     , fStack(0)
00044     , fStackCapacity(32)
00045     , fStackTop(0)
00046     , fUnknownNamespaceId(0)
00047     , fXMLNamespaceId(0)
00048     , fXMLPoolId(0)
00049     , fXMLNSNamespaceId(0)
00050     , fXMLNSPoolId(0)
00051     , fNamespaceMap(0)
00052     , fMemoryManager(manager)
00053 {
00054     // Do an initial allocation of the stack and zero it out
00055     fStack = (StackElem**) fMemoryManager->allocate
00056     (
00057         fStackCapacity * sizeof(StackElem*)
00058     );//new StackElem*[fStackCapacity];
00059     memset(fStack, 0, fStackCapacity * sizeof(StackElem*));
00060 
00061     fNamespaceMap = new (fMemoryManager) ValueVectorOf<PrefMapElem*>(16, fMemoryManager);
00062 }
00063 
00064 ElemStack::~ElemStack()
00065 {
00066     if(fGlobalNamespaces)
00067     {
00068         fMemoryManager->deallocate(fGlobalNamespaces->fMap);
00069         delete fGlobalNamespaces;
00070     }
00071 
00072     //
00073     //  Start working from the bottom of the stack and clear it out as we
00074     //  go up. Once we hit an uninitialized one, we can break out.
00075     //
00076     for (XMLSize_t stackInd = 0; stackInd < fStackCapacity; stackInd++)
00077     {
00078         // If this entry has been set, then lets clean it up
00079         if (!fStack[stackInd])
00080             break;
00081 
00082         fMemoryManager->deallocate(fStack[stackInd]->fChildren);//delete [] fStack[stackInd]->fChildren;
00083         fMemoryManager->deallocate(fStack[stackInd]->fMap);//delete [] fStack[stackInd]->fMap;
00084         fMemoryManager->deallocate(fStack[stackInd]->fSchemaElemName);
00085         delete fStack[stackInd];
00086     }
00087 
00088     // Delete the stack array itself now
00089     fMemoryManager->deallocate(fStack);//delete [] fStack;
00090     delete fNamespaceMap;
00091 }
00092 
00093 
00094 // ---------------------------------------------------------------------------
00095 //  ElemStack: Stack access
00096 // ---------------------------------------------------------------------------
00097 XMLSize_t ElemStack::addLevel()
00098 {
00099     // See if we need to expand the stack
00100     if (fStackTop == fStackCapacity)
00101         expandStack();
00102 
00103     // If this element has not been initialized yet, then initialize it
00104     if (!fStack[fStackTop])
00105     {
00106         fStack[fStackTop] = new (fMemoryManager) StackElem;
00107         fStack[fStackTop]->fChildCapacity = 0;
00108         fStack[fStackTop]->fChildren = 0;
00109         fStack[fStackTop]->fMapCapacity = 0;
00110         fStack[fStackTop]->fMap = 0;
00111         fStack[fStackTop]->fSchemaElemName = 0;
00112         fStack[fStackTop]->fSchemaElemNameMaxLen = 0;
00113     }
00114 
00115     // Set up the new top row
00116     fStack[fStackTop]->fThisElement = 0;
00117     fStack[fStackTop]->fReaderNum = 0xFFFFFFFF;
00118     fStack[fStackTop]->fChildCount = 0;
00119     fStack[fStackTop]->fMapCount = 0;
00120     fStack[fStackTop]->fValidationFlag = false;
00121     fStack[fStackTop]->fCommentOrPISeen = false;
00122     fStack[fStackTop]->fReferenceEscaped = false;
00123     fStack[fStackTop]->fCurrentURI = fUnknownNamespaceId;
00124     fStack[fStackTop]->fCurrentScope = Grammar::TOP_LEVEL_SCOPE;
00125     fStack[fStackTop]->fCurrentGrammar = 0;
00126 
00127     // Bump the top of stack
00128     fStackTop++;
00129 
00130     return fStackTop-1;
00131 }
00132 
00133 
00134 XMLSize_t ElemStack::addLevel(XMLElementDecl* const toSet, const XMLSize_t readerNum)
00135 {
00136     // See if we need to expand the stack
00137     if (fStackTop == fStackCapacity)
00138         expandStack();
00139 
00140     // If this element has not been initialized yet, then initialize it
00141     if (!fStack[fStackTop])
00142     {
00143         fStack[fStackTop] = new (fMemoryManager) StackElem;
00144         fStack[fStackTop]->fChildCapacity = 0;
00145         fStack[fStackTop]->fChildren = 0;
00146         fStack[fStackTop]->fMapCapacity = 0;
00147         fStack[fStackTop]->fMap = 0;
00148         fStack[fStackTop]->fSchemaElemName = 0;
00149         fStack[fStackTop]->fSchemaElemNameMaxLen = 0;
00150     }
00151 
00152     // Set up the new top row
00153     fStack[fStackTop]->fThisElement = toSet;
00154     fStack[fStackTop]->fReaderNum = readerNum;
00155     fStack[fStackTop]->fChildCount = 0;
00156     fStack[fStackTop]->fMapCount = 0;
00157     fStack[fStackTop]->fValidationFlag = false;
00158     fStack[fStackTop]->fCommentOrPISeen = false;
00159     fStack[fStackTop]->fReferenceEscaped = false;
00160     fStack[fStackTop]->fCurrentURI = fUnknownNamespaceId;
00161     fStack[fStackTop]->fCurrentScope = Grammar::TOP_LEVEL_SCOPE;
00162     fStack[fStackTop]->fCurrentGrammar = 0;
00163 
00164     // Bump the top of stack
00165     fStackTop++;
00166 
00167     return fStackTop-1;
00168 }
00169 
00170 
00171 
00172 const ElemStack::StackElem* ElemStack::popTop()
00173 {
00174     // Watch for an underflow error
00175     if (!fStackTop)
00176         ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_StackUnderflow, fMemoryManager);
00177 
00178     fStackTop--;
00179     return fStack[fStackTop];
00180 }
00181 
00182 
00183 void
00184 ElemStack::setElement(XMLElementDecl* const toSet, const XMLSize_t readerNum)
00185 {
00186     if (!fStackTop)
00187         ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager);
00188 
00189     fStack[fStackTop - 1]->fThisElement = toSet;
00190     fStack[fStackTop - 1]->fReaderNum = readerNum;
00191 }
00192 
00193 
00194 // ---------------------------------------------------------------------------
00195 //  ElemStack: Stack top access
00196 // ---------------------------------------------------------------------------
00197 XMLSize_t ElemStack::addChild(QName* const child, const bool toParent)
00198 {
00199     if (!fStackTop)
00200         ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager);
00201 
00202     //
00203     //  If they want to add to the parent, then we have to have at least two
00204     //  elements on the stack.
00205     //
00206     if (toParent && (fStackTop < 2))
00207         ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::ElemStack_NoParentPushed, fMemoryManager);
00208 
00209     // Get a convenience pointer to the stack top row
00210     StackElem* curRow = toParent
00211                         ? fStack[fStackTop - 2] : fStack[fStackTop - 1];
00212 
00213     // See if we need to expand this row's child array
00214     if (curRow->fChildCount == curRow->fChildCapacity)
00215     {
00216         // Increase the capacity by a quarter and allocate a new row
00217         const XMLSize_t newCapacity = curRow->fChildCapacity ?
00218                                       (XMLSize_t)(curRow->fChildCapacity * 1.25) :
00219                                       32;
00220         QName** newRow = (QName**) fMemoryManager->allocate
00221         (
00222             newCapacity * sizeof(QName*)
00223         );//new QName*[newCapacity];
00224 
00225         //
00226         //  Copy over the old contents. We don't have to initialize the new
00227         //  part because The current child count is used to know how much of
00228         //  it is valid.
00229         //
00230         //  Only both doing this if there is any current content, since
00231         //  this code also does the initial faulting in of the array when
00232         //  both the current capacity and child count are zero.
00233         //
00234         for (XMLSize_t index = 0; index < curRow->fChildCount; index++)
00235             newRow[index] = curRow->fChildren[index];
00236 
00237         // Clean up the old children and store the new info
00238         fMemoryManager->deallocate(curRow->fChildren);//delete [] curRow->fChildren;
00239         curRow->fChildren = newRow;
00240         curRow->fChildCapacity = newCapacity;
00241     }
00242 
00243     // Add this id to the end of the row's child id array and bump the count
00244     curRow->fChildren[curRow->fChildCount++] = child;
00245 
00246     // Return the level of the index we just filled (before the bump)
00247     return curRow->fChildCount - 1;
00248 }
00249 
00250 const ElemStack::StackElem* ElemStack::topElement() const
00251 {
00252     if (!fStackTop)
00253         ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager);
00254 
00255     return fStack[fStackTop - 1];
00256 }
00257 
00258 
00259 // ---------------------------------------------------------------------------
00260 //  ElemStack: Prefix map methods
00261 // ---------------------------------------------------------------------------
00262 void ElemStack::addGlobalPrefix(const XMLCh* const    prefixToAdd
00263                               , const unsigned int    uriId)
00264 {
00265     if (!fGlobalNamespaces)
00266     {
00267         fGlobalNamespaces = new (fMemoryManager) StackElem;
00268         fGlobalNamespaces->fChildCapacity = 0;
00269         fGlobalNamespaces->fChildren = 0;
00270         fGlobalNamespaces->fMapCapacity = 0;
00271         fGlobalNamespaces->fMap = 0;
00272         fGlobalNamespaces->fMapCount = 0;
00273         fGlobalNamespaces->fSchemaElemName = 0;
00274         fGlobalNamespaces->fSchemaElemNameMaxLen = 0;
00275         fGlobalNamespaces->fThisElement = 0;
00276         fGlobalNamespaces->fReaderNum = 0xFFFFFFFF;
00277         fGlobalNamespaces->fChildCount = 0;
00278         fGlobalNamespaces->fValidationFlag = false;
00279         fGlobalNamespaces->fCommentOrPISeen = false;
00280         fGlobalNamespaces->fReferenceEscaped = false;
00281         fGlobalNamespaces->fCurrentURI = fUnknownNamespaceId;
00282         fGlobalNamespaces->fCurrentScope = Grammar::TOP_LEVEL_SCOPE;
00283         fGlobalNamespaces->fCurrentGrammar = 0;
00284     }
00285 
00286     // Map the prefix to its unique id
00287     const unsigned int prefId = fPrefixPool.addOrFind(prefixToAdd);
00288 
00289     //
00290     //  Add a new element to the prefix map for this element. If its full,
00291     //  then expand it out.
00292     //
00293     if (fGlobalNamespaces->fMapCount == fGlobalNamespaces->fMapCapacity)
00294         expandMap(fGlobalNamespaces);
00295 
00296     //
00297     //  And now add a new element for this prefix. Watch for the special case
00298     //  of xmlns=="", and force it to ""=[globalid]
00299     //
00300     fGlobalNamespaces->fMap[fGlobalNamespaces->fMapCount].fPrefId = prefId;
00301     if ((prefId == fGlobalPoolId) && (uriId == fEmptyNamespaceId))
00302         fGlobalNamespaces->fMap[fGlobalNamespaces->fMapCount].fURIId = fEmptyNamespaceId;
00303     else
00304         fGlobalNamespaces->fMap[fGlobalNamespaces->fMapCount].fURIId = uriId;
00305 
00306     // Bump the map count now
00307     fGlobalNamespaces->fMapCount++;
00308 }
00309 
00310 void ElemStack::addPrefix(  const   XMLCh* const    prefixToAdd
00311                             , const unsigned int    uriId)
00312 {
00313     if (!fStackTop)
00314         ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager);
00315 
00316     // Get a convenience pointer to the stack top row
00317     StackElem* curRow = fStack[fStackTop - 1];
00318 
00319     // Map the prefix to its unique id
00320     const unsigned int prefId = fPrefixPool.addOrFind(prefixToAdd);
00321 
00322     //
00323     //  Add a new element to the prefix map for this element. If its full,
00324     //  then expand it out.
00325     //
00326     if (curRow->fMapCount == curRow->fMapCapacity)
00327         expandMap(curRow);
00328 
00329     //
00330     //  And now add a new element for this prefix. Watch for the special case
00331     //  of xmlns=="", and force it to ""=[globalid]
00332     //
00333     curRow->fMap[curRow->fMapCount].fPrefId = prefId;
00334     if ((prefId == fGlobalPoolId) && (uriId == fEmptyNamespaceId))
00335         curRow->fMap[curRow->fMapCount].fURIId = fEmptyNamespaceId;
00336     else
00337         curRow->fMap[curRow->fMapCount].fURIId = uriId;
00338 
00339     // Bump the map count now
00340     curRow->fMapCount++;
00341 }
00342 
00343 
00344 unsigned int ElemStack::mapPrefixToURI( const   XMLCh* const    prefixToMap
00345                                         ,       bool&           unknown) const
00346 {
00347     // Assume we find it
00348     unknown = false;
00349 
00350     //
00351     //  Map the prefix to its unique id, from the prefix string pool. If its
00352     //  not a valid prefix, then its a failure.
00353     //
00354     unsigned int prefixId = (!prefixToMap || !*prefixToMap)?fGlobalPoolId : fPrefixPool.getId(prefixToMap);
00355     if (prefixId == 0)
00356     {
00357         unknown = true;
00358         return fUnknownNamespaceId;
00359     }
00360     //
00361     //  Check for the special prefixes 'xml' and 'xmlns' since they cannot
00362     //  be overridden.
00363     //
00364     else if (prefixId == fXMLPoolId)
00365         return fXMLNamespaceId;
00366     else if (prefixId == fXMLNSPoolId)
00367         return fXMLNSNamespaceId;
00368 
00369     //
00370     //  Start at the stack top and work backwards until we come to some
00371     //  element that mapped this prefix.
00372     //
00373     for (XMLSize_t index = fStackTop; index > 0; index--)
00374     {
00375         // Get a convenience pointer to the current element
00376         StackElem* curRow = fStack[index-1];
00377 
00378         // Search the map at this level for the passed prefix
00379         for (XMLSize_t mapIndex = 0; mapIndex < curRow->fMapCount; mapIndex++)
00380         {
00381             if (curRow->fMap[mapIndex].fPrefId == prefixId)
00382                 return curRow->fMap[mapIndex].fURIId;
00383         }
00384     }
00385     //  If the prefix wasn't found, try in the global namespaces
00386     if(fGlobalNamespaces)
00387     {
00388         for (XMLSize_t mapIndex = 0; mapIndex < fGlobalNamespaces->fMapCount; mapIndex++)
00389         {
00390             if (fGlobalNamespaces->fMap[mapIndex].fPrefId == prefixId)
00391                 return fGlobalNamespaces->fMap[mapIndex].fURIId;
00392         }
00393     }
00394 
00395     //
00396     //  If the prefix is an empty string, then we will return the special
00397     //  global namespace id. This can be overridden, but no one has or we
00398     //  would have not gotten here.
00399     //
00400     if (!*prefixToMap)
00401         return fEmptyNamespaceId;
00402 
00403     // Oh well, don't have a clue so return the unknown id
00404     unknown = true;
00405     return fUnknownNamespaceId;
00406 }
00407 
00408 
00409 ValueVectorOf<PrefMapElem*>* ElemStack::getNamespaceMap() const
00410 {
00411     fNamespaceMap->removeAllElements();
00412 
00413     //  Start at the stack top and work backwards until we come to some
00414     //  element that mapped this prefix.
00415     for (XMLSize_t index = fStackTop; index > 0; index--)
00416     {
00417         // Get a convenience pointer to the current element
00418         StackElem* curRow = fStack[index-1];
00419 
00420         // If no prefixes mapped at this level, then go the next one
00421         if (!curRow->fMapCount)
00422             continue;
00423 
00424         // Search the map at this level for the passed prefix
00425         for (XMLSize_t mapIndex = 0; mapIndex < curRow->fMapCount; mapIndex++)
00426             fNamespaceMap->addElement(&(curRow->fMap[mapIndex]));
00427     }
00428     //  Add the global namespaces
00429     if(fGlobalNamespaces)
00430     {
00431         for (XMLSize_t mapIndex = 0; mapIndex < fGlobalNamespaces->fMapCount; mapIndex++)
00432             fNamespaceMap->addElement(&(fGlobalNamespaces->fMap[mapIndex]));
00433     }
00434 
00435     return fNamespaceMap;
00436 }
00437 
00438 // ---------------------------------------------------------------------------
00439 //  ElemStack: Miscellaneous methods
00440 // ---------------------------------------------------------------------------
00441 void ElemStack::reset(  const   unsigned int    emptyId
00442                         , const unsigned int    unknownId
00443                         , const unsigned int    xmlId
00444                         , const unsigned int    xmlNSId)
00445 {
00446     if(fGlobalNamespaces)
00447     {
00448         fMemoryManager->deallocate(fGlobalNamespaces->fMap);
00449         delete fGlobalNamespaces;
00450         fGlobalNamespaces = 0;
00451     }
00452 
00453     // Reset the stack top to clear the stack
00454     fStackTop = 0;
00455 
00456     // if first time, put in the standard prefixes
00457     if (fXMLPoolId == 0) {
00458 
00459         fGlobalPoolId = fPrefixPool.addOrFind(XMLUni::fgZeroLenString);
00460         fXMLPoolId = fPrefixPool.addOrFind(XMLUni::fgXMLString);
00461         fXMLNSPoolId = fPrefixPool.addOrFind(XMLUni::fgXMLNSString);
00462     }
00463 
00464     // And store the new special URI ids
00465     fEmptyNamespaceId = emptyId;
00466     fUnknownNamespaceId = unknownId;
00467     fXMLNamespaceId = xmlId;
00468     fXMLNSNamespaceId = xmlNSId;
00469 }
00470 
00471 
00472 // ---------------------------------------------------------------------------
00473 //  ElemStack: Private helpers
00474 // ---------------------------------------------------------------------------
00475 void ElemStack::expandMap(StackElem* const toExpand)
00476 {
00477     // For convenience get the old map size
00478     const XMLSize_t oldCap = toExpand->fMapCapacity;
00479 
00480     //
00481     //  Expand the capacity by 25%, or initialize it to 16 if its currently
00482     //  empty. Then allocate a new temp buffer.
00483     //
00484     const XMLSize_t  newCapacity = oldCap ?
00485                                      (XMLSize_t )(oldCap * 1.25) : 16;
00486     PrefMapElem* newMap = (PrefMapElem*) fMemoryManager->allocate
00487     (
00488         newCapacity * sizeof(PrefMapElem)
00489     );//new PrefMapElem[newCapacity];
00490 
00491     //
00492     //  Copy over the old stuff. We DON'T have to zero out the new stuff
00493     //  since this is a by value map and the current map index controls what
00494     //  is relevant.
00495     //
00496     memcpy(newMap, toExpand->fMap, oldCap * sizeof(PrefMapElem));
00497 
00498     // Delete the old map and store the new stuff
00499     fMemoryManager->deallocate(toExpand->fMap);//delete [] toExpand->fMap;
00500     toExpand->fMap = newMap;
00501     toExpand->fMapCapacity = newCapacity;
00502 }
00503 
00504 void ElemStack::expandStack()
00505 {
00506     // Expand the capacity by 25% and allocate a new buffer
00507     const XMLSize_t newCapacity = (XMLSize_t)(fStackCapacity * 1.25);
00508     StackElem** newStack = (StackElem**) fMemoryManager->allocate
00509     (
00510         newCapacity * sizeof(StackElem*)
00511     );//new StackElem*[newCapacity];
00512 
00513     // Copy over the old stuff
00514     memcpy(newStack, fStack, fStackCapacity * sizeof(StackElem*));
00515 
00516     //
00517     //  And zero out the new stuff. Though we use a stack top, we reuse old
00518     //  stack contents so we need to know if elements have been initially
00519     //  allocated or not as we push new stuff onto the stack.
00520     //
00521     memset
00522     (
00523         &newStack[fStackCapacity]
00524         , 0
00525         , (newCapacity - fStackCapacity) * sizeof(StackElem*)
00526     );
00527 
00528     // Delete the old array and update our members
00529     fMemoryManager->deallocate(fStack);//delete [] fStack;
00530     fStack = newStack;
00531     fStackCapacity = newCapacity;
00532 }
00533 
00534 
00535 
00536 // ---------------------------------------------------------------------------
00537 //  WFElemStack: Constructors and Destructor
00538 // ---------------------------------------------------------------------------
00539 WFElemStack::WFElemStack(MemoryManager* const manager) :
00540 
00541     fEmptyNamespaceId(0)
00542     , fGlobalPoolId(0)
00543     , fStackCapacity(32)
00544     , fStackTop(0)
00545     , fUnknownNamespaceId(0)
00546     , fXMLNamespaceId(0)
00547     , fXMLPoolId(0)
00548     , fXMLNSNamespaceId(0)
00549     , fXMLNSPoolId(0)
00550     , fMapCapacity(0)
00551     , fMap(0)
00552     , fStack(0)
00553     , fPrefixPool(109, manager)
00554     , fMemoryManager(manager)
00555 {
00556     // Do an initial allocation of the stack and zero it out
00557     fStack = (StackElem**) fMemoryManager->allocate
00558     (
00559         fStackCapacity * sizeof(StackElem*)
00560     );//new StackElem*[fStackCapacity];
00561     memset(fStack, 0, fStackCapacity * sizeof(StackElem*));
00562 }
00563 
00564 WFElemStack::~WFElemStack()
00565 {
00566     //
00567     //  Start working from the bottom of the stack and clear it out as we
00568     //  go up. Once we hit an uninitialized one, we can break out.
00569     //
00570     for (XMLSize_t stackInd = 0; stackInd < fStackCapacity; stackInd++)
00571     {
00572         // If this entry has been set, then lets clean it up
00573         if (!fStack[stackInd])
00574             break;
00575 
00576         fMemoryManager->deallocate(fStack[stackInd]->fThisElement);//delete [] fStack[stackInd]->fThisElement;
00577         delete fStack[stackInd];
00578     }
00579 
00580     if (fMap)
00581         fMemoryManager->deallocate(fMap);//delete [] fMap;
00582 
00583     // Delete the stack array itself now
00584     fMemoryManager->deallocate(fStack);//delete [] fStack;
00585 }
00586 
00587 
00588 // ---------------------------------------------------------------------------
00589 //  WFElemStack: Stack access
00590 // ---------------------------------------------------------------------------
00591 XMLSize_t WFElemStack::addLevel()
00592 {
00593     // See if we need to expand the stack
00594     if (fStackTop == fStackCapacity)
00595         expandStack();
00596 
00597     
00598     // If this element has not been initialized yet, then initialize it
00599     if (!fStack[fStackTop])
00600     {
00601         fStack[fStackTop] = new (fMemoryManager) StackElem;
00602         fStack[fStackTop]->fThisElement = 0;
00603         fStack[fStackTop]->fElemMaxLength = 0;
00604     }
00605 
00606     // Set up the new top row
00607     fStack[fStackTop]->fReaderNum = 0xFFFFFFFF;
00608     fStack[fStackTop]->fCurrentURI = fUnknownNamespaceId;
00609     fStack[fStackTop]->fTopPrefix = -1;
00610 
00611     if (fStackTop != 0)
00612         fStack[fStackTop]->fTopPrefix = fStack[fStackTop - 1]->fTopPrefix;
00613 
00614     // Bump the top of stack
00615     fStackTop++;
00616 
00617     return fStackTop-1;
00618 }
00619 
00620 
00621 XMLSize_t
00622 WFElemStack::addLevel(const XMLCh* const toSet,
00623                       const unsigned int toSetLen,
00624                       const unsigned int readerNum)
00625 {
00626     // See if we need to expand the stack
00627     if (fStackTop == fStackCapacity)
00628         expandStack();
00629 
00630     // If this element has not been initialized yet, then initialize it
00631     if (!fStack[fStackTop])
00632     {
00633         fStack[fStackTop] = new (fMemoryManager) StackElem;
00634         fStack[fStackTop]->fThisElement = 0;
00635         fStack[fStackTop]->fElemMaxLength = 0;
00636     }
00637 
00638     // Set up the new top row
00639     fStack[fStackTop]->fCurrentURI = fUnknownNamespaceId;
00640     fStack[fStackTop]->fTopPrefix = -1;
00641 
00642     // And store the new stuff
00643     if (toSetLen > fStack[fStackTop]->fElemMaxLength) {
00644 
00645         fMemoryManager->deallocate(fStack[fStackTop]->fThisElement);//delete [] fStack[fStackTop]->fThisElement;
00646         fStack[fStackTop]->fElemMaxLength = toSetLen;
00647         fStack[fStackTop]->fThisElement = (XMLCh*) fMemoryManager->allocate
00648         (
00649             (toSetLen + 1) * sizeof(XMLCh)
00650         );//new XMLCh[toSetLen + 1];
00651     }
00652 
00653     XMLString::moveChars(fStack[fStackTop]->fThisElement, toSet, toSetLen + 1);
00654     fStack[fStackTop]->fReaderNum = readerNum;
00655 
00656     if (fStackTop != 0)
00657         fStack[fStackTop]->fTopPrefix = fStack[fStackTop - 1]->fTopPrefix;
00658 
00659     // Bump the top of stack
00660     fStackTop++;
00661 
00662     return fStackTop-1;
00663 }
00664 
00665 
00666 
00667 const WFElemStack::StackElem* WFElemStack::popTop()
00668 {
00669     // Watch for an underflow error
00670     if (!fStackTop)
00671         ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_StackUnderflow, fMemoryManager);
00672 
00673     fStackTop--;
00674     return fStack[fStackTop];
00675 }
00676 
00677 
00678 void
00679 WFElemStack::setElement(const XMLCh* const toSet,
00680                       const unsigned int toSetLen,
00681                       const unsigned int readerNum)
00682 {
00683     if (!fStackTop)
00684         ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager);
00685 
00686     if (toSetLen > fStack[fStackTop - 1]->fElemMaxLength) {
00687 
00688         fMemoryManager->deallocate(fStack[fStackTop - 1]->fThisElement);//delete [] fStack[fStackTop - 1]->fThisElement;
00689         fStack[fStackTop - 1]->fElemMaxLength = toSetLen;
00690         fStack[fStackTop - 1]->fThisElement = (XMLCh*) fMemoryManager->allocate
00691         (
00692             (toSetLen + 1) * sizeof(XMLCh)
00693         );//new XMLCh[toSetLen + 1];
00694     }
00695 
00696     XMLString::moveChars(fStack[fStackTop - 1]->fThisElement, toSet, toSetLen + 1);
00697     fStack[fStackTop - 1]->fReaderNum = readerNum;
00698 }
00699 
00700 
00701 // ---------------------------------------------------------------------------
00702 //  WFElemStack: Stack top access
00703 // ---------------------------------------------------------------------------
00704 const WFElemStack::StackElem* WFElemStack::topElement() const
00705 {
00706     if (!fStackTop)
00707         ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager);
00708 
00709     return fStack[fStackTop - 1];
00710 }
00711 
00712 
00713 // ---------------------------------------------------------------------------
00714 //  WFElemStack: Prefix map methods
00715 // ---------------------------------------------------------------------------
00716 void WFElemStack::addPrefix(  const   XMLCh* const    prefixToAdd
00717                               , const unsigned int    uriId)
00718 {
00719     if (!fStackTop)
00720         ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager);
00721 
00722     // Get a convenience pointer to the stack top row
00723     StackElem* curRow = fStack[fStackTop - 1];
00724 
00725     // Map the prefix to its unique id
00726     const unsigned int prefId = fPrefixPool.addOrFind(prefixToAdd);
00727 
00728     //
00729     //  Add a new element to the prefix map for this element. If its full,
00730     //  then expand it out.
00731     //
00732     if ((unsigned int)curRow->fTopPrefix + 1 == fMapCapacity)
00733         expandMap();
00734 
00735     //
00736     //  And now add a new element for this prefix. Watch for the special case
00737     //  of xmlns=="", and force it to ""=[globalid]
00738     //
00739     fMap[curRow->fTopPrefix + 1].fPrefId = prefId;
00740     if ((prefId == fGlobalPoolId) && (uriId == fEmptyNamespaceId))
00741         fMap[curRow->fTopPrefix + 1].fURIId = fEmptyNamespaceId;
00742     else
00743         fMap[curRow->fTopPrefix + 1].fURIId = uriId;
00744 
00745     // Bump the map count now
00746     curRow->fTopPrefix++;
00747 }
00748 
00749 
00750 unsigned int WFElemStack::mapPrefixToURI( const   XMLCh* const    prefixToMap
00751                                           ,       bool&           unknown) const
00752 {
00753     // Assume we find it
00754     unknown = false;
00755 
00756     //
00757     //  Map the prefix to its unique id, from the prefix string pool. If its
00758     //  not a valid prefix, then its a failure.
00759     //
00760     unsigned int prefixId = fPrefixPool.getId(prefixToMap);
00761     if (!prefixId)
00762     {
00763         unknown = true;
00764         return fUnknownNamespaceId;
00765     }
00766 
00767     //
00768     //  Check for the special prefixes 'xml' and 'xmlns' since they cannot
00769     //  be overridden.
00770     //
00771     if (prefixId == fXMLPoolId)
00772         return fXMLNamespaceId;
00773     else if (prefixId == fXMLNSPoolId)
00774         return fXMLNSNamespaceId;
00775 
00776     //
00777     //  Start at the stack top and work backwards until we come to some
00778     //  element that mapped this prefix.
00779     //
00780     //  Get a convenience pointer to the stack top row
00781     StackElem* curRow = fStack[fStackTop - 1];
00782     for (int mapIndex = curRow->fTopPrefix; mapIndex >=0; mapIndex--)
00783     {
00784         if (fMap[mapIndex].fPrefId == prefixId)
00785             return fMap[mapIndex].fURIId;
00786     }
00787 
00788     //
00789     //  If the prefix is an empty string, then we will return the special
00790     //  global namespace id. This can be overridden, but no one has or we
00791     //  would have not gotten here.
00792     //
00793     if (!*prefixToMap)
00794         return fEmptyNamespaceId;
00795 
00796     // Oh well, don't have a clue so return the unknown id
00797     unknown = true;
00798     return fUnknownNamespaceId;
00799 }
00800 
00801 
00802 // ---------------------------------------------------------------------------
00803 //  WFElemStack: Miscellaneous methods
00804 // ---------------------------------------------------------------------------
00805 void WFElemStack::reset(  const   unsigned int    emptyId
00806                           , const unsigned int    unknownId
00807                           , const unsigned int    xmlId
00808                           , const unsigned int    xmlNSId)
00809 {
00810     // Reset the stack top to clear the stack
00811     fStackTop = 0;
00812 
00813     // if first time, put in the standard prefixes
00814     if (fXMLPoolId == 0) {
00815 
00816         fGlobalPoolId = fPrefixPool.addOrFind(XMLUni::fgZeroLenString);
00817         fXMLPoolId = fPrefixPool.addOrFind(XMLUni::fgXMLString);
00818         fXMLNSPoolId = fPrefixPool.addOrFind(XMLUni::fgXMLNSString);
00819     }
00820 
00821     // And store the new special URI ids
00822     fEmptyNamespaceId = emptyId;
00823     fUnknownNamespaceId = unknownId;
00824     fXMLNamespaceId = xmlId;
00825     fXMLNSNamespaceId = xmlNSId;
00826 }
00827 
00828 
00829 // ---------------------------------------------------------------------------
00830 //  WFElemStack: Private helpers
00831 // ---------------------------------------------------------------------------
00832 void WFElemStack::expandMap()
00833 {
00834     //
00835     //  Expand the capacity by 25%, or initialize it to 16 if its currently
00836     //  empty. Then allocate a new temp buffer.
00837     //
00838     const XMLSize_t newCapacity = fMapCapacity ?
00839                                   (XMLSize_t)(fMapCapacity * 1.25) : 16;
00840     PrefMapElem* newMap = (PrefMapElem*) fMemoryManager->allocate
00841     (
00842         newCapacity * sizeof(PrefMapElem)
00843     );//new PrefMapElem[newCapacity];
00844 
00845     //
00846     //  Copy over the old stuff. We DON'T have to zero out the new stuff
00847     //  since this is a by value map and the current map index controls what
00848     //  is relevant.
00849     //
00850     if (fMapCapacity) {
00851 
00852         memcpy(newMap, fMap, fMapCapacity * sizeof(PrefMapElem));
00853         fMemoryManager->deallocate(fMap);//delete [] fMap;
00854     }
00855 
00856     fMap = newMap;
00857     fMapCapacity = newCapacity;
00858 }
00859 
00860 void WFElemStack::expandStack()
00861 {
00862     // Expand the capacity by 25% and allocate a new buffer
00863     const XMLSize_t newCapacity = (XMLSize_t)(fStackCapacity * 1.25);
00864     StackElem** newStack = (StackElem**) fMemoryManager->allocate
00865     (
00866         newCapacity * sizeof(StackElem*)
00867     );//new StackElem*[newCapacity];
00868 
00869     // Copy over the old stuff
00870     memcpy(newStack, fStack, fStackCapacity * sizeof(StackElem*));
00871 
00872     //
00873     //  And zero out the new stuff. Though we use a stack top, we reuse old
00874     //  stack contents so we need to know if elements have been initially
00875     //  allocated or not as we push new stuff onto the stack.
00876     //
00877     memset
00878     (
00879         &newStack[fStackCapacity]
00880         , 0
00881         , (newCapacity - fStackCapacity) * sizeof(StackElem*)
00882     );
00883 
00884     // Delete the old array and update our members
00885     fMemoryManager->deallocate(fStack);//delete [] fStack;
00886     fStack = newStack;
00887     fStackCapacity = newCapacity;
00888 }
00889 
00890 
00891 XERCES_CPP_NAMESPACE_END