ElemStack.cpp
上传用户:zhuqijet
上传日期:2013-06-25
资源大小:10074k
文件大小:31k
源码类别:

词法分析

开发平台:

Visual C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
  5.  * reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  *
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  *
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in
  16.  *    the documentation and/or other materials provided with the
  17.  *    distribution.
  18.  *
  19.  * 3. The end-user documentation included with the redistribution,
  20.  *    if any, must include the following acknowledgment:
  21.  *       "This product includes software developed by the
  22.  *        Apache Software Foundation (http://www.apache.org/)."
  23.  *    Alternately, this acknowledgment may appear in the software itself,
  24.  *    if and wherever such third-party acknowledgments normally appear.
  25.  *
  26.  * 4. The names "Xerces" and "Apache Software Foundation" must
  27.  *    not be used to endorse or promote products derived from this
  28.  *    software without prior written permission. For written
  29.  *    permission, please contact apache@apache.org.
  30.  *
  31.  * 5. Products derived from this software may not be called "Apache",
  32.  *    nor may "Apache" appear in their name, without prior written
  33.  *    permission of the Apache Software Foundation.
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38.  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42.  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44.  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45.  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46.  * SUCH DAMAGE.
  47.  * ====================================================================
  48.  *
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Software Foundation, and was
  51.  * originally based on software copyright (c) 1999, International
  52.  * Business Machines, Inc., http://www.ibm.com .  For more information
  53.  * on the Apache Software Foundation, please see
  54.  * <http://www.apache.org/>.
  55.  */
  56. /*
  57.  * $Log: ElemStack.cpp,v $
  58.  * Revision 1.7  2003/05/18 14:02:04  knoaman
  59.  * Memory manager implementation: pass per instance manager.
  60.  *
  61.  * Revision 1.6  2003/05/16 21:36:57  knoaman
  62.  * Memory manager implementation: Modify constructors to pass in the memory manager.
  63.  *
  64.  * Revision 1.5  2003/05/15 18:26:29  knoaman
  65.  * Partial implementation of the configurable memory manager.
  66.  *
  67.  * Revision 1.4  2003/01/02 16:38:00  knoaman
  68.  * Some cleanup.
  69.  *
  70.  * Revision 1.3  2002/12/04 02:23:50  knoaman
  71.  * Scanner re-organization.
  72.  *
  73.  * Revision 1.2  2002/11/04 14:58:18  tng
  74.  * C++ Namespace Support.
  75.  *
  76.  * Revision 1.1.1.1  2002/02/01 22:21:57  peiyongz
  77.  * sane_include
  78.  *
  79.  * Revision 1.17  2001/12/12 14:29:50  tng
  80.  * Remove obsolete code in ElemStack which can help performance.
  81.  *
  82.  * Revision 1.16  2001/08/29 16:42:27  tng
  83.  * No need to new the child QName in ElemStack addChild.  Remove it for performance gain.
  84.  *
  85.  * Revision 1.15  2001/08/07 13:47:47  tng
  86.  * Schema: Fix unmatched end tag for qualified/unqualifed start tag.
  87.  *
  88.  * Revision 1.14  2001/06/18 21:33:57  peiyongz
  89.  * Memory leak fix: to addlevel(), by Erik Rydgren.
  90.  *
  91.  * Revision 1.13  2001/06/12 19:08:27  peiyongz
  92.  * Memory leak: fixed by Erik Rydgren
  93.  *
  94.  * Revision 1.12  2001/05/28 20:55:19  tng
  95.  * Schema: Store Grammar in ElemStack as well.
  96.  *
  97.  * Revision 1.11  2001/05/11 13:26:16  tng
  98.  * Copyright update.
  99.  *
  100.  * Revision 1.10  2001/05/03 20:34:28  tng
  101.  * Schema: SchemaValidator update
  102.  *
  103.  * Revision 1.9  2001/04/19 18:16:57  tng
  104.  * Schema: SchemaValidator update, and use QName in Content Model
  105.  *
  106.  * Revision 1.8  2001/02/16 17:58:02  tng
  107.  * use EmptyNamespaceId for attribute, GlobalNamespaceId for element.
  108.  *
  109.  * Revision 1.7  2000/07/05 05:20:17  roddey
  110.  * Fixed a memory leak when namespaces are enabled.
  111.  *
  112.  * Revision 1.6  2000/05/15 22:31:15  andyh
  113.  * Replace #include<memory.h> with <string.h> everywhere.
  114.  *
  115.  * Revision 1.5  2000/03/02 19:54:28  roddey
  116.  * This checkin includes many changes done while waiting for the
  117.  * 1.1.0 code to be finished. I can't list them all here, but a list is
  118.  * available elsewhere.
  119.  *
  120.  * Revision 1.4  2000/02/08 19:38:58  roddey
  121.  * xmlns:xxx="" should affect the mapping of the prefixes of sibling attributes,
  122.  * which was not being done.
  123.  *
  124.  * Revision 1.3  2000/02/06 07:47:52  rahulj
  125.  * Year 2K copyright swat.
  126.  *
  127.  * Revision 1.2  2000/01/19 00:55:45  roddey
  128.  * Changes to get rid of dependence on old utils standard streams classes
  129.  * and a small fix in the progressive parseFirst() call.
  130.  *
  131.  * Revision 1.1.1.1  1999/11/09 01:08:04  twl
  132.  * Initial checkin
  133.  *
  134.  * Revision 1.4  1999/11/08 20:44:41  rahul
  135.  * Swat for adding in Product name and CVS comment log variable.
  136.  *
  137.  */
  138. // ---------------------------------------------------------------------------
  139. //  Includes
  140. // ---------------------------------------------------------------------------
  141. #include <string.h>
  142. #include <xercesc/util/EmptyStackException.hpp>
  143. #include <xercesc/util/NoSuchElementException.hpp>
  144. #include <xercesc/framework/XMLElementDecl.hpp>
  145. #include <xercesc/internal/ElemStack.hpp>
  146. #include <xercesc/validators/common/Grammar.hpp>
  147. XERCES_CPP_NAMESPACE_BEGIN
  148. // ---------------------------------------------------------------------------
  149. //  ElemStack: Constructors and Destructor
  150. // ---------------------------------------------------------------------------
  151. ElemStack::ElemStack(MemoryManager* const manager) :
  152.     fEmptyNamespaceId(0)
  153.     , fGlobalPoolId(0)
  154.     , fPrefixPool(109, manager)
  155.     , fStack(0)
  156.     , fStackCapacity(32)
  157.     , fStackTop(0)
  158.     , fUnknownNamespaceId(0)
  159.     , fXMLNamespaceId(0)
  160.     , fXMLPoolId(0)
  161.     , fXMLNSNamespaceId(0)
  162.     , fXMLNSPoolId(0)
  163.     , fMemoryManager(manager)
  164. {
  165.     // Do an initial allocation of the stack and zero it out
  166.     fStack = (StackElem**) fMemoryManager->allocate
  167.     (
  168.         fStackCapacity * sizeof(StackElem*)
  169.     );//new StackElem*[fStackCapacity];
  170.     memset(fStack, 0, fStackCapacity * sizeof(StackElem*));
  171. }
  172. ElemStack::~ElemStack()
  173. {
  174.     //
  175.     //  Start working from the bottom of the stack and clear it out as we
  176.     //  go up. Once we hit an uninitialized one, we can break out.
  177.     //
  178.     for (unsigned int stackInd = 0; stackInd < fStackCapacity; stackInd++)
  179.     {
  180.         // If this entry has been set, then lets clean it up
  181.         if (!fStack[stackInd])
  182.             break;
  183.         fMemoryManager->deallocate(fStack[stackInd]->fChildren);//delete [] fStack[stackInd]->fChildren;
  184.         fMemoryManager->deallocate(fStack[stackInd]->fMap);//delete [] fStack[stackInd]->fMap;
  185.         delete fStack[stackInd];
  186.     }
  187.     // Delete the stack array itself now
  188.     fMemoryManager->deallocate(fStack);//delete [] fStack;
  189. }
  190. // ---------------------------------------------------------------------------
  191. //  ElemStack: Stack access
  192. // ---------------------------------------------------------------------------
  193. unsigned int ElemStack::addLevel()
  194. {
  195.     // See if we need to expand the stack
  196.     if (fStackTop == fStackCapacity)
  197.         expandStack();
  198.     // If this element has not been initialized yet, then initialize it
  199.     if (!fStack[fStackTop])
  200.     {
  201.         fStack[fStackTop] = new (fMemoryManager) StackElem;
  202.         fStack[fStackTop]->fChildCapacity = 0;
  203.         fStack[fStackTop]->fChildren = 0;
  204.         fStack[fStackTop]->fMapCapacity = 0;
  205.         fStack[fStackTop]->fMap = 0;
  206.     }
  207.     // Set up the new top row
  208.     fStack[fStackTop]->fThisElement = 0;
  209.     fStack[fStackTop]->fReaderNum = 0xFFFFFFFF;
  210.     fStack[fStackTop]->fChildCount = 0;
  211.     fStack[fStackTop]->fMapCount = 0;
  212.     fStack[fStackTop]->fValidationFlag = false;
  213.     fStack[fStackTop]->fCurrentURI = fUnknownNamespaceId;
  214.     fStack[fStackTop]->fCurrentScope = Grammar::TOP_LEVEL_SCOPE;
  215.     fStack[fStackTop]->fCurrentGrammar = 0;
  216.     // Bump the top of stack
  217.     fStackTop++;
  218.     return fStackTop-1;
  219. }
  220. unsigned int
  221. ElemStack::addLevel(XMLElementDecl* const toSet, const unsigned int readerNum)
  222. {
  223.     // See if we need to expand the stack
  224.     if (fStackTop == fStackCapacity)
  225.         expandStack();
  226.     // If this element has not been initialized yet, then initialize it
  227.     if (!fStack[fStackTop])
  228.     {
  229.         fStack[fStackTop] = new (fMemoryManager) StackElem;
  230.         fStack[fStackTop]->fChildCapacity = 0;
  231.         fStack[fStackTop]->fChildren = 0;
  232.         fStack[fStackTop]->fMapCapacity = 0;
  233.         fStack[fStackTop]->fMap = 0;
  234.     }
  235.     // Set up the new top row
  236.     fStack[fStackTop]->fThisElement = toSet;
  237.     fStack[fStackTop]->fReaderNum = readerNum;
  238.     fStack[fStackTop]->fChildCount = 0;
  239.     fStack[fStackTop]->fMapCount = 0;
  240.     fStack[fStackTop]->fValidationFlag = false;
  241.     fStack[fStackTop]->fCurrentURI = fUnknownNamespaceId;
  242.     fStack[fStackTop]->fCurrentScope = Grammar::TOP_LEVEL_SCOPE;
  243.     fStack[fStackTop]->fCurrentGrammar = 0;
  244.     // Bump the top of stack
  245.     fStackTop++;
  246.     return fStackTop-1;
  247. }
  248. const ElemStack::StackElem* ElemStack::popTop()
  249. {
  250.     // Watch for an underflow error
  251.     if (!fStackTop)
  252.         ThrowXML(EmptyStackException, XMLExcepts::ElemStack_StackUnderflow);
  253.     fStackTop--;
  254.     return fStack[fStackTop];
  255. }
  256. void
  257. ElemStack::setElement(XMLElementDecl* const toSet, const unsigned int readerNum)
  258. {
  259.     if (!fStackTop)
  260.         ThrowXML(EmptyStackException, XMLExcepts::ElemStack_EmptyStack);
  261.     fStack[fStackTop - 1]->fThisElement = toSet;
  262.     fStack[fStackTop - 1]->fReaderNum = readerNum;
  263. }
  264. // ---------------------------------------------------------------------------
  265. //  ElemStack: Stack top access
  266. // ---------------------------------------------------------------------------
  267. unsigned int ElemStack::addChild(QName* const child, const bool toParent)
  268. {
  269.     if (!fStackTop)
  270.         ThrowXML(EmptyStackException, XMLExcepts::ElemStack_EmptyStack);
  271.     //
  272.     //  If they want to add to the parent, then we have to have at least two
  273.     //  elements on the stack.
  274.     //
  275.     if (toParent && (fStackTop < 2))
  276.         ThrowXML(NoSuchElementException, XMLExcepts::ElemStack_NoParentPushed);
  277.     // Get a convenience pointer to the stack top row
  278.     StackElem* curRow = toParent
  279.                         ? fStack[fStackTop - 2] : fStack[fStackTop - 1];
  280.     // See if we need to expand this row's child array
  281.     if (curRow->fChildCount == curRow->fChildCapacity)
  282.     {
  283.         // Increase the capacity by a quarter and allocate a new row
  284.         const unsigned int newCapacity = curRow->fChildCapacity ?
  285.                                          (unsigned int)(curRow->fChildCapacity * 1.25) :
  286.                                          32;
  287.         QName** newRow = (QName**) fMemoryManager->allocate
  288.         (
  289.             newCapacity * sizeof(QName*)
  290.         );//new QName*[newCapacity];
  291.         //
  292.         //  Copy over the old contents. We don't have to initialize the new
  293.         //  part because The current child count is used to know how much of
  294.         //  it is valid.
  295.         //
  296.         //  Only both doing this if there is any current content, since
  297.         //  this code also does the initial faulting in of the array when
  298.         //  both the current capacity and child count are zero.
  299.         //
  300.         if (curRow->fChildCount)
  301.         {
  302.              unsigned int index = 0;
  303.              for (; index < curRow->fChildCount; index++)
  304.                  newRow[index] = curRow->fChildren[index];
  305.         }
  306.         // Clean up the old children and store the new info
  307.         fMemoryManager->deallocate(curRow->fChildren);//delete [] curRow->fChildren;
  308.         curRow->fChildren = newRow;
  309.         curRow->fChildCapacity = newCapacity;
  310.     }
  311.     // Add this id to the end of the row's child id array and bump the count
  312.     curRow->fChildren[curRow->fChildCount++] = child;
  313.     // Return the level of the index we just filled (before the bump)
  314.     return curRow->fChildCount - 1;
  315. }
  316. const ElemStack::StackElem* ElemStack::topElement() const
  317. {
  318.     if (!fStackTop)
  319.         ThrowXML(EmptyStackException, XMLExcepts::ElemStack_EmptyStack);
  320.     return fStack[fStackTop - 1];
  321. }
  322. // ---------------------------------------------------------------------------
  323. //  ElemStack: Prefix map methods
  324. // ---------------------------------------------------------------------------
  325. void ElemStack::addPrefix(  const   XMLCh* const    prefixToAdd
  326.                             , const unsigned int    uriId)
  327. {
  328.     if (!fStackTop)
  329.         ThrowXML(EmptyStackException, XMLExcepts::ElemStack_EmptyStack);
  330.     // Get a convenience pointer to the stack top row
  331.     StackElem* curRow = fStack[fStackTop - 1];
  332.     // Map the prefix to its unique id
  333.     const unsigned int prefId = fPrefixPool.addOrFind(prefixToAdd);
  334.     //
  335.     //  Add a new element to the prefix map for this element. If its full,
  336.     //  then expand it out.
  337.     //
  338.     if (curRow->fMapCount == curRow->fMapCapacity)
  339.         expandMap(curRow);
  340.     //
  341.     //  And now add a new element for this prefix. Watch for the special case
  342.     //  of xmlns=="", and force it to ""=[globalid]
  343.     //
  344.     curRow->fMap[curRow->fMapCount].fPrefId = prefId;
  345.     if ((prefId == fGlobalPoolId) && (uriId == fEmptyNamespaceId))
  346.         curRow->fMap[curRow->fMapCount].fURIId = fEmptyNamespaceId;
  347.     else
  348.         curRow->fMap[curRow->fMapCount].fURIId = uriId;
  349.     // Bump the map count now
  350.     curRow->fMapCount++;
  351. }
  352. unsigned int ElemStack::mapPrefixToURI( const   XMLCh* const    prefixToMap
  353.                                         , const MapModes        mode
  354.                                         ,       bool&           unknown) const
  355. {
  356.     // Assume we find it
  357.     unknown = false;
  358.     //
  359.     //  Map the prefix to its unique id, from the prefix string pool. If its
  360.     //  not a valid prefix, then its a failure.
  361.     //
  362.     unsigned int prefixId = fPrefixPool.getId(prefixToMap);
  363.     if (!prefixId)
  364.     {
  365.         unknown = true;
  366.         return fUnknownNamespaceId;
  367.     }
  368.     //
  369.     //  If the prefix is empty, and we are in attribute mode, then we assign
  370.     //  it to the empty namespace because the default namespace does not
  371.     //  apply to attributes.
  372.     //
  373.     if (!*prefixToMap && (mode == Mode_Attribute))
  374.         return fEmptyNamespaceId;
  375.     //
  376.     //  Check for the special prefixes 'xml' and 'xmlns' since they cannot
  377.     //  be overridden.
  378.     //
  379.     if (prefixId == fXMLPoolId)
  380.         return fXMLNamespaceId;
  381.     else if (prefixId == fXMLNSPoolId)
  382.         return fXMLNSNamespaceId;
  383.     //
  384.     //  Start at the stack top and work backwards until we come to some
  385.     //  element that mapped this prefix.
  386.     //
  387.     int startAt = (int)(fStackTop - 1);
  388.     for (int index = startAt; index >= 0; index--)
  389.     {
  390.         // Get a convenience pointer to the current element
  391.         StackElem* curRow = fStack[index];
  392.         // If no prefixes mapped at this level, then go the next one
  393.         if (!curRow->fMapCount)
  394.             continue;
  395.         // Search the map at this level for the passed prefix
  396.         for (unsigned int mapIndex = 0; mapIndex < curRow->fMapCount; mapIndex++)
  397.         {
  398.             if (curRow->fMap[mapIndex].fPrefId == prefixId)
  399.                 return curRow->fMap[mapIndex].fURIId;
  400.         }
  401.     }
  402.     //
  403.     //  If the prefix is an empty string, then we will return the special
  404.     //  global namespace id. This can be overridden, but no one has or we
  405.     //  would have not gotten here.
  406.     //
  407.     if (!*prefixToMap)
  408.         return fEmptyNamespaceId;
  409.     // Oh well, don't have a clue so return the unknown id
  410.     unknown = true;
  411.     return fUnknownNamespaceId;
  412. }
  413. // ---------------------------------------------------------------------------
  414. //  ElemStack: Miscellaneous methods
  415. // ---------------------------------------------------------------------------
  416. void ElemStack::reset(  const   unsigned int    emptyId
  417.                         , const unsigned int    unknownId
  418.                         , const unsigned int    xmlId
  419.                         , const unsigned int    xmlNSId)
  420. {
  421.     // Reset the stack top to clear the stack
  422.     fStackTop = 0;
  423.     // if first time, put in the standard prefixes
  424.     if (fXMLPoolId == 0) {
  425.         fGlobalPoolId = fPrefixPool.addOrFind(XMLUni::fgZeroLenString);
  426.         fXMLPoolId = fPrefixPool.addOrFind(XMLUni::fgXMLString);
  427.         fXMLNSPoolId = fPrefixPool.addOrFind(XMLUni::fgXMLNSString);
  428.     }
  429.     // And store the new special URI ids
  430.     fEmptyNamespaceId = emptyId;
  431.     fUnknownNamespaceId = unknownId;
  432.     fXMLNamespaceId = xmlId;
  433.     fXMLNSNamespaceId = xmlNSId;
  434. }
  435. // ---------------------------------------------------------------------------
  436. //  ElemStack: Private helpers
  437. // ---------------------------------------------------------------------------
  438. void ElemStack::expandMap(StackElem* const toExpand)
  439. {
  440.     // For convenience get the old map size
  441.     const unsigned int oldCap = toExpand->fMapCapacity;
  442.     //
  443.     //  Expand the capacity by 25%, or initialize it to 16 if its currently
  444.     //  empty. Then allocate a new temp buffer.
  445.     //
  446.     const unsigned int newCapacity = oldCap ?
  447.                                      (unsigned int)(oldCap * 1.25) : 16;
  448.     PrefMapElem* newMap = (PrefMapElem*) fMemoryManager->allocate
  449.     (
  450.         newCapacity * sizeof(PrefMapElem)
  451.     );//new PrefMapElem[newCapacity];
  452.     //
  453.     //  Copy over the old stuff. We DON'T have to zero out the new stuff
  454.     //  since this is a by value map and the current map index controls what
  455.     //  is relevant.
  456.     //
  457.     memcpy(newMap, toExpand->fMap, oldCap * sizeof(PrefMapElem));
  458.     // Delete the old map and store the new stuff
  459.     fMemoryManager->deallocate(toExpand->fMap);//delete [] toExpand->fMap;
  460.     toExpand->fMap = newMap;
  461.     toExpand->fMapCapacity = newCapacity;
  462. }
  463. void ElemStack::expandStack()
  464. {
  465.     // Expand the capacity by 25% and allocate a new buffer
  466.     const unsigned int newCapacity = (unsigned int)(fStackCapacity * 1.25);
  467.     StackElem** newStack = (StackElem**) fMemoryManager->allocate
  468.     (
  469.         newCapacity * sizeof(StackElem*)
  470.     );//new StackElem*[newCapacity];
  471.     // Copy over the old stuff
  472.     memcpy(newStack, fStack, fStackCapacity * sizeof(StackElem*));
  473.     //
  474.     //  And zero out the new stuff. Though we use a stack top, we reuse old
  475.     //  stack contents so we need to know if elements have been initially
  476.     //  allocated or not as we push new stuff onto the stack.
  477.     //
  478.     memset
  479.     (
  480.         &newStack[fStackCapacity]
  481.         , 0
  482.         , (newCapacity - fStackCapacity) * sizeof(StackElem*)
  483.     );
  484.     // Delete the old array and update our members
  485.     fMemoryManager->deallocate(fStack);//delete [] fStack;
  486.     fStack = newStack;
  487.     fStackCapacity = newCapacity;
  488. }
  489. // ---------------------------------------------------------------------------
  490. //  WFElemStack: Constructors and Destructor
  491. // ---------------------------------------------------------------------------
  492. WFElemStack::WFElemStack(MemoryManager* const manager) :
  493.     fEmptyNamespaceId(0)
  494.     , fGlobalPoolId(0)
  495.     , fStackCapacity(32)
  496.     , fStackTop(0)
  497.     , fUnknownNamespaceId(0)
  498.     , fXMLNamespaceId(0)
  499.     , fXMLPoolId(0)
  500.     , fXMLNSNamespaceId(0)
  501.     , fXMLNSPoolId(0)
  502.     , fMapCapacity(0)
  503.     , fMap(0)
  504.     , fStack(0)
  505.     , fPrefixPool(109, manager)
  506.     , fMemoryManager(manager)
  507. {
  508.     // Do an initial allocation of the stack and zero it out
  509.     fStack = (StackElem**) fMemoryManager->allocate
  510.     (
  511.         fStackCapacity * sizeof(StackElem*)
  512.     );//new StackElem*[fStackCapacity];
  513.     memset(fStack, 0, fStackCapacity * sizeof(StackElem*));
  514. }
  515. WFElemStack::~WFElemStack()
  516. {
  517.     //
  518.     //  Start working from the bottom of the stack and clear it out as we
  519.     //  go up. Once we hit an uninitialized one, we can break out.
  520.     //
  521.     for (unsigned int stackInd = 0; stackInd < fStackCapacity; stackInd++)
  522.     {
  523.         // If this entry has been set, then lets clean it up
  524.         if (!fStack[stackInd])
  525.             break;
  526.         fMemoryManager->deallocate(fStack[stackInd]->fThisElement);//delete [] fStack[stackInd]->fThisElement;
  527.         delete fStack[stackInd];
  528.     }
  529.     if (fMap)
  530.         fMemoryManager->deallocate(fMap);//delete [] fMap;
  531.     // Delete the stack array itself now
  532.     fMemoryManager->deallocate(fStack);//delete [] fStack;
  533. }
  534. // ---------------------------------------------------------------------------
  535. //  WFElemStack: Stack access
  536. // ---------------------------------------------------------------------------
  537. unsigned int WFElemStack::addLevel()
  538. {
  539.     // See if we need to expand the stack
  540.     if (fStackTop == fStackCapacity)
  541.         expandStack();
  542.     
  543.     // If this element has not been initialized yet, then initialize it
  544.     if (!fStack[fStackTop])
  545.     {
  546.         fStack[fStackTop] = new (fMemoryManager) StackElem;
  547.         fStack[fStackTop]->fThisElement = 0;
  548.         fStack[fStackTop]->fElemMaxLength = 0;
  549.     }
  550.     // Set up the new top row
  551.     fStack[fStackTop]->fReaderNum = 0xFFFFFFFF;
  552.     fStack[fStackTop]->fCurrentURI = fUnknownNamespaceId;
  553.     fStack[fStackTop]->fTopPrefix = -1;
  554.     if (fStackTop != 0)
  555.         fStack[fStackTop]->fTopPrefix = fStack[fStackTop - 1]->fTopPrefix;
  556.     // Bump the top of stack
  557.     fStackTop++;
  558.     return fStackTop-1;
  559. }
  560. unsigned int
  561. WFElemStack::addLevel(const XMLCh* const toSet,
  562.                       const unsigned int toSetLen,
  563.                       const unsigned int readerNum)
  564. {
  565.     // See if we need to expand the stack
  566.     if (fStackTop == fStackCapacity)
  567.         expandStack();
  568.     // If this element has not been initialized yet, then initialize it
  569.     if (!fStack[fStackTop])
  570.     {
  571.         fStack[fStackTop] = new (fMemoryManager) StackElem;
  572.         fStack[fStackTop]->fThisElement = 0;
  573.         fStack[fStackTop]->fElemMaxLength = 0;
  574.     }
  575.     // Set up the new top row
  576.     fStack[fStackTop]->fCurrentURI = fUnknownNamespaceId;
  577.     fStack[fStackTop]->fTopPrefix = -1;
  578.     // And store the new stuff
  579.     if (toSetLen > fStack[fStackTop]->fElemMaxLength) {
  580.         fMemoryManager->deallocate(fStack[fStackTop]->fThisElement);//delete [] fStack[fStackTop]->fThisElement;
  581.         fStack[fStackTop]->fElemMaxLength = toSetLen;
  582.         fStack[fStackTop]->fThisElement = (XMLCh*) fMemoryManager->allocate
  583.         (
  584.             (toSetLen + 1) * sizeof(XMLCh)
  585.         );//new XMLCh[toSetLen + 1];
  586.     }
  587.     XMLString::moveChars(fStack[fStackTop]->fThisElement, toSet, toSetLen + 1);
  588.     fStack[fStackTop]->fReaderNum = readerNum;
  589.     if (fStackTop != 0)
  590.         fStack[fStackTop]->fTopPrefix = fStack[fStackTop - 1]->fTopPrefix;
  591.     // Bump the top of stack
  592.     fStackTop++;
  593.     return fStackTop-1;
  594. }
  595. const WFElemStack::StackElem* WFElemStack::popTop()
  596. {
  597.     // Watch for an underflow error
  598.     if (!fStackTop)
  599.         ThrowXML(EmptyStackException, XMLExcepts::ElemStack_StackUnderflow);
  600.     fStackTop--;
  601.     return fStack[fStackTop];
  602. }
  603. void
  604. WFElemStack::setElement(const XMLCh* const toSet,
  605.                       const unsigned int toSetLen,
  606.                       const unsigned int readerNum)
  607. {
  608.     if (!fStackTop)
  609.         ThrowXML(EmptyStackException, XMLExcepts::ElemStack_EmptyStack);
  610.     if (toSetLen > fStack[fStackTop - 1]->fElemMaxLength) {
  611.         fMemoryManager->deallocate(fStack[fStackTop - 1]->fThisElement);//delete [] fStack[fStackTop - 1]->fThisElement;
  612.         fStack[fStackTop - 1]->fElemMaxLength = toSetLen;
  613.         fStack[fStackTop - 1]->fThisElement = (XMLCh*) fMemoryManager->allocate
  614.         (
  615.             (toSetLen + 1) * sizeof(XMLCh)
  616.         );//new XMLCh[toSetLen + 1];
  617.     }
  618.     XMLString::moveChars(fStack[fStackTop - 1]->fThisElement, toSet, toSetLen + 1);
  619.     fStack[fStackTop - 1]->fReaderNum = readerNum;
  620. }
  621. // ---------------------------------------------------------------------------
  622. //  WFElemStack: Stack top access
  623. // ---------------------------------------------------------------------------
  624. const WFElemStack::StackElem* WFElemStack::topElement() const
  625. {
  626.     if (!fStackTop)
  627.         ThrowXML(EmptyStackException, XMLExcepts::ElemStack_EmptyStack);
  628.     return fStack[fStackTop - 1];
  629. }
  630. // ---------------------------------------------------------------------------
  631. //  WFElemStack: Prefix map methods
  632. // ---------------------------------------------------------------------------
  633. void WFElemStack::addPrefix(  const   XMLCh* const    prefixToAdd
  634.                               , const unsigned int    uriId)
  635. {
  636.     if (!fStackTop)
  637.         ThrowXML(EmptyStackException, XMLExcepts::ElemStack_EmptyStack);
  638.     // Get a convenience pointer to the stack top row
  639.     StackElem* curRow = fStack[fStackTop - 1];
  640.     // Map the prefix to its unique id
  641.     const unsigned int prefId = fPrefixPool.addOrFind(prefixToAdd);
  642.     //
  643.     //  Add a new element to the prefix map for this element. If its full,
  644.     //  then expand it out.
  645.     //
  646.     if ((unsigned int)curRow->fTopPrefix + 1 == fMapCapacity)
  647.         expandMap();
  648.     //
  649.     //  And now add a new element for this prefix. Watch for the special case
  650.     //  of xmlns=="", and force it to ""=[globalid]
  651.     //
  652.     fMap[curRow->fTopPrefix + 1].fPrefId = prefId;
  653.     if ((prefId == fGlobalPoolId) && (uriId == fEmptyNamespaceId))
  654.         fMap[curRow->fTopPrefix + 1].fURIId = fEmptyNamespaceId;
  655.     else
  656.         fMap[curRow->fTopPrefix + 1].fURIId = uriId;
  657.     // Bump the map count now
  658.     curRow->fTopPrefix++;
  659. }
  660. unsigned int WFElemStack::mapPrefixToURI( const   XMLCh* const    prefixToMap
  661.                                           , const MapModes        mode
  662.                                           ,       bool&           unknown) const
  663. {
  664.     // Assume we find it
  665.     unknown = false;
  666.     //
  667.     //  Map the prefix to its unique id, from the prefix string pool. If its
  668.     //  not a valid prefix, then its a failure.
  669.     //
  670.     unsigned int prefixId = fPrefixPool.getId(prefixToMap);
  671.     if (!prefixId)
  672.     {
  673.         unknown = true;
  674.         return fUnknownNamespaceId;
  675.     }
  676.     //
  677.     //  If the prefix is empty, and we are in attribute mode, then we assign
  678.     //  it to the empty namespace because the default namespace does not
  679.     //  apply to attributes.
  680.     //
  681.     if (!*prefixToMap && (mode == Mode_Attribute))
  682.         return fEmptyNamespaceId;
  683.     //
  684.     //  Check for the special prefixes 'xml' and 'xmlns' since they cannot
  685.     //  be overridden.
  686.     //
  687.     if (prefixId == fXMLPoolId)
  688.         return fXMLNamespaceId;
  689.     else if (prefixId == fXMLNSPoolId)
  690.         return fXMLNSNamespaceId;
  691.     //
  692.     //  Start at the stack top and work backwards until we come to some
  693.     //  element that mapped this prefix.
  694.     //
  695.     //  Get a convenience pointer to the stack top row
  696.     StackElem* curRow = fStack[fStackTop - 1];
  697.     for (int mapIndex = curRow->fTopPrefix; mapIndex >=0; mapIndex--)
  698.     {
  699.         if (fMap[mapIndex].fPrefId == prefixId)
  700.             return fMap[mapIndex].fURIId;
  701.     }
  702.     //
  703.     //  If the prefix is an empty string, then we will return the special
  704.     //  global namespace id. This can be overridden, but no one has or we
  705.     //  would have not gotten here.
  706.     //
  707.     if (!*prefixToMap)
  708.         return fEmptyNamespaceId;
  709.     // Oh well, don't have a clue so return the unknown id
  710.     unknown = true;
  711.     return fUnknownNamespaceId;
  712. }
  713. // ---------------------------------------------------------------------------
  714. //  WFElemStack: Miscellaneous methods
  715. // ---------------------------------------------------------------------------
  716. void WFElemStack::reset(  const   unsigned int    emptyId
  717.                           , const unsigned int    unknownId
  718.                           , const unsigned int    xmlId
  719.                           , const unsigned int    xmlNSId)
  720. {
  721.     // Reset the stack top to clear the stack
  722.     fStackTop = 0;
  723.     // if first time, put in the standard prefixes
  724.     if (fXMLPoolId == 0) {
  725.         fGlobalPoolId = fPrefixPool.addOrFind(XMLUni::fgZeroLenString);
  726.         fXMLPoolId = fPrefixPool.addOrFind(XMLUni::fgXMLString);
  727.         fXMLNSPoolId = fPrefixPool.addOrFind(XMLUni::fgXMLNSString);
  728.     }
  729.     // And store the new special URI ids
  730.     fEmptyNamespaceId = emptyId;
  731.     fUnknownNamespaceId = unknownId;
  732.     fXMLNamespaceId = xmlId;
  733.     fXMLNSNamespaceId = xmlNSId;
  734. }
  735. // ---------------------------------------------------------------------------
  736. //  WFElemStack: Private helpers
  737. // ---------------------------------------------------------------------------
  738. void WFElemStack::expandMap()
  739. {
  740.     //
  741.     //  Expand the capacity by 25%, or initialize it to 16 if its currently
  742.     //  empty. Then allocate a new temp buffer.
  743.     //
  744.     const unsigned int newCapacity = fMapCapacity ?
  745.                                      (unsigned int)(fMapCapacity * 1.25) : 16;
  746.     PrefMapElem* newMap = (PrefMapElem*) fMemoryManager->allocate
  747.     (
  748.         newCapacity * sizeof(PrefMapElem)
  749.     );//new PrefMapElem[newCapacity];
  750.     //
  751.     //  Copy over the old stuff. We DON'T have to zero out the new stuff
  752.     //  since this is a by value map and the current map index controls what
  753.     //  is relevant.
  754.     //
  755.     if (fMapCapacity) {
  756.         memcpy(newMap, fMap, fMapCapacity * sizeof(PrefMapElem));
  757.         fMemoryManager->deallocate(fMap);//delete [] fMap;
  758.     }
  759.     fMap = newMap;
  760.     fMapCapacity = newCapacity;
  761. }
  762. void WFElemStack::expandStack()
  763. {
  764.     // Expand the capacity by 25% and allocate a new buffer
  765.     const unsigned int newCapacity = (unsigned int)(fStackCapacity * 1.25);
  766.     StackElem** newStack = (StackElem**) fMemoryManager->allocate
  767.     (
  768.         newCapacity * sizeof(StackElem*)
  769.     );//new StackElem*[newCapacity];
  770.     // Copy over the old stuff
  771.     memcpy(newStack, fStack, fStackCapacity * sizeof(StackElem*));
  772.     //
  773.     //  And zero out the new stuff. Though we use a stack top, we reuse old
  774.     //  stack contents so we need to know if elements have been initially
  775.     //  allocated or not as we push new stuff onto the stack.
  776.     //
  777.     memset
  778.     (
  779.         &newStack[fStackCapacity]
  780.         , 0
  781.         , (newCapacity - fStackCapacity) * sizeof(StackElem*)
  782.     );
  783.     // Delete the old array and update our members
  784.     fMemoryManager->deallocate(fStack);//delete [] fStack;
  785.     fStack = newStack;
  786.     fStackCapacity = newCapacity;
  787. }
  788. XERCES_CPP_NAMESPACE_END