| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /* |
| * $Id$ |
| */ |
| |
| // --------------------------------------------------------------------------- |
| // Includes |
| // --------------------------------------------------------------------------- |
| #include <string.h> |
| #include <xercesc/util/EmptyStackException.hpp> |
| #include <xercesc/util/NoSuchElementException.hpp> |
| #include <xercesc/framework/XMLElementDecl.hpp> |
| #include <xercesc/internal/ElemStack.hpp> |
| #include <xercesc/validators/common/Grammar.hpp> |
| |
| XERCES_CPP_NAMESPACE_BEGIN |
| |
| // --------------------------------------------------------------------------- |
| // ElemStack: Constructors and Destructor |
| // --------------------------------------------------------------------------- |
| ElemStack::ElemStack(MemoryManager* const manager) : |
| |
| fEmptyNamespaceId(0) |
| , fGlobalPoolId(0) |
| , fPrefixPool(109, manager) |
| , fGlobalNamespaces(0) |
| , fStack(0) |
| , fStackCapacity(32) |
| , fStackTop(0) |
| , fUnknownNamespaceId(0) |
| , fXMLNamespaceId(0) |
| , fXMLPoolId(0) |
| , fXMLNSNamespaceId(0) |
| , fXMLNSPoolId(0) |
| , fNamespaceMap(0) |
| , fMemoryManager(manager) |
| { |
| // Do an initial allocation of the stack and zero it out |
| fStack = (StackElem**) fMemoryManager->allocate |
| ( |
| fStackCapacity * sizeof(StackElem*) |
| );//new StackElem*[fStackCapacity]; |
| memset(fStack, 0, fStackCapacity * sizeof(StackElem*)); |
| |
| fNamespaceMap = new (fMemoryManager) ValueVectorOf<PrefMapElem*>(16, fMemoryManager); |
| } |
| |
| ElemStack::~ElemStack() |
| { |
| if(fGlobalNamespaces) |
| { |
| fMemoryManager->deallocate(fGlobalNamespaces->fMap); |
| delete fGlobalNamespaces; |
| } |
| |
| // |
| // Start working from the bottom of the stack and clear it out as we |
| // go up. Once we hit an uninitialized one, we can break out. |
| // |
| for (XMLSize_t stackInd = 0; stackInd < fStackCapacity; stackInd++) |
| { |
| // If this entry has been set, then lets clean it up |
| if (!fStack[stackInd]) |
| break; |
| |
| fMemoryManager->deallocate(fStack[stackInd]->fChildren);//delete [] fStack[stackInd]->fChildren; |
| fMemoryManager->deallocate(fStack[stackInd]->fMap);//delete [] fStack[stackInd]->fMap; |
| fMemoryManager->deallocate(fStack[stackInd]->fSchemaElemName); |
| delete fStack[stackInd]; |
| } |
| |
| // Delete the stack array itself now |
| fMemoryManager->deallocate(fStack);//delete [] fStack; |
| delete fNamespaceMap; |
| } |
| |
| |
| // --------------------------------------------------------------------------- |
| // ElemStack: Stack access |
| // --------------------------------------------------------------------------- |
| XMLSize_t ElemStack::addLevel() |
| { |
| // See if we need to expand the stack |
| if (fStackTop == fStackCapacity) |
| expandStack(); |
| |
| // If this element has not been initialized yet, then initialize it |
| if (!fStack[fStackTop]) |
| { |
| fStack[fStackTop] = new (fMemoryManager) StackElem; |
| fStack[fStackTop]->fChildCapacity = 0; |
| fStack[fStackTop]->fChildren = 0; |
| fStack[fStackTop]->fMapCapacity = 0; |
| fStack[fStackTop]->fMap = 0; |
| fStack[fStackTop]->fSchemaElemName = 0; |
| fStack[fStackTop]->fSchemaElemNameMaxLen = 0; |
| } |
| |
| // Set up the new top row |
| fStack[fStackTop]->fThisElement = 0; |
| fStack[fStackTop]->fReaderNum = 0xFFFFFFFF; |
| fStack[fStackTop]->fChildCount = 0; |
| fStack[fStackTop]->fMapCount = 0; |
| fStack[fStackTop]->fValidationFlag = false; |
| fStack[fStackTop]->fCommentOrPISeen = false; |
| fStack[fStackTop]->fReferenceEscaped = false; |
| fStack[fStackTop]->fCurrentURI = fUnknownNamespaceId; |
| fStack[fStackTop]->fCurrentScope = Grammar::TOP_LEVEL_SCOPE; |
| fStack[fStackTop]->fCurrentGrammar = 0; |
| |
| // Bump the top of stack |
| fStackTop++; |
| |
| return fStackTop-1; |
| } |
| |
| |
| XMLSize_t ElemStack::addLevel(XMLElementDecl* const toSet, const XMLSize_t readerNum) |
| { |
| // See if we need to expand the stack |
| if (fStackTop == fStackCapacity) |
| expandStack(); |
| |
| // If this element has not been initialized yet, then initialize it |
| if (!fStack[fStackTop]) |
| { |
| fStack[fStackTop] = new (fMemoryManager) StackElem; |
| fStack[fStackTop]->fChildCapacity = 0; |
| fStack[fStackTop]->fChildren = 0; |
| fStack[fStackTop]->fMapCapacity = 0; |
| fStack[fStackTop]->fMap = 0; |
| fStack[fStackTop]->fSchemaElemName = 0; |
| fStack[fStackTop]->fSchemaElemNameMaxLen = 0; |
| } |
| |
| // Set up the new top row |
| fStack[fStackTop]->fThisElement = toSet; |
| fStack[fStackTop]->fReaderNum = readerNum; |
| fStack[fStackTop]->fChildCount = 0; |
| fStack[fStackTop]->fMapCount = 0; |
| fStack[fStackTop]->fValidationFlag = false; |
| fStack[fStackTop]->fCommentOrPISeen = false; |
| fStack[fStackTop]->fReferenceEscaped = false; |
| fStack[fStackTop]->fCurrentURI = fUnknownNamespaceId; |
| fStack[fStackTop]->fCurrentScope = Grammar::TOP_LEVEL_SCOPE; |
| fStack[fStackTop]->fCurrentGrammar = 0; |
| |
| // Bump the top of stack |
| fStackTop++; |
| |
| return fStackTop-1; |
| } |
| |
| |
| |
| const ElemStack::StackElem* ElemStack::popTop() |
| { |
| // Watch for an underflow error |
| if (!fStackTop) |
| ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_StackUnderflow, fMemoryManager); |
| |
| fStackTop--; |
| return fStack[fStackTop]; |
| } |
| |
| |
| void |
| ElemStack::setElement(XMLElementDecl* const toSet, const XMLSize_t readerNum) |
| { |
| if (!fStackTop) |
| ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager); |
| |
| fStack[fStackTop - 1]->fThisElement = toSet; |
| fStack[fStackTop - 1]->fReaderNum = readerNum; |
| } |
| |
| |
| // --------------------------------------------------------------------------- |
| // ElemStack: Stack top access |
| // --------------------------------------------------------------------------- |
| XMLSize_t ElemStack::addChild(QName* const child, const bool toParent) |
| { |
| if (!fStackTop) |
| ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager); |
| |
| // |
| // If they want to add to the parent, then we have to have at least two |
| // elements on the stack. |
| // |
| if (toParent && (fStackTop < 2)) |
| ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::ElemStack_NoParentPushed, fMemoryManager); |
| |
| // Get a convenience pointer to the stack top row |
| StackElem* curRow = toParent |
| ? fStack[fStackTop - 2] : fStack[fStackTop - 1]; |
| |
| // See if we need to expand this row's child array |
| if (curRow->fChildCount == curRow->fChildCapacity) |
| { |
| // Increase the capacity by a quarter and allocate a new row |
| const XMLSize_t newCapacity = curRow->fChildCapacity ? |
| (XMLSize_t)(curRow->fChildCapacity * 1.25) : |
| 32; |
| QName** newRow = (QName**) fMemoryManager->allocate |
| ( |
| newCapacity * sizeof(QName*) |
| );//new QName*[newCapacity]; |
| |
| // |
| // Copy over the old contents. We don't have to initialize the new |
| // part because The current child count is used to know how much of |
| // it is valid. |
| // |
| // Only both doing this if there is any current content, since |
| // this code also does the initial faulting in of the array when |
| // both the current capacity and child count are zero. |
| // |
| for (XMLSize_t index = 0; index < curRow->fChildCount; index++) |
| newRow[index] = curRow->fChildren[index]; |
| |
| // Clean up the old children and store the new info |
| fMemoryManager->deallocate(curRow->fChildren);//delete [] curRow->fChildren; |
| curRow->fChildren = newRow; |
| curRow->fChildCapacity = newCapacity; |
| } |
| |
| // Add this id to the end of the row's child id array and bump the count |
| curRow->fChildren[curRow->fChildCount++] = child; |
| |
| // Return the level of the index we just filled (before the bump) |
| return curRow->fChildCount - 1; |
| } |
| |
| const ElemStack::StackElem* ElemStack::topElement() const |
| { |
| if (!fStackTop) |
| ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager); |
| |
| return fStack[fStackTop - 1]; |
| } |
| |
| |
| // --------------------------------------------------------------------------- |
| // ElemStack: Prefix map methods |
| // --------------------------------------------------------------------------- |
| void ElemStack::addGlobalPrefix(const XMLCh* const prefixToAdd |
| , const unsigned int uriId) |
| { |
| if (!fGlobalNamespaces) |
| { |
| fGlobalNamespaces = new (fMemoryManager) StackElem; |
| fGlobalNamespaces->fChildCapacity = 0; |
| fGlobalNamespaces->fChildren = 0; |
| fGlobalNamespaces->fMapCapacity = 0; |
| fGlobalNamespaces->fMap = 0; |
| fGlobalNamespaces->fMapCount = 0; |
| fGlobalNamespaces->fSchemaElemName = 0; |
| fGlobalNamespaces->fSchemaElemNameMaxLen = 0; |
| fGlobalNamespaces->fThisElement = 0; |
| fGlobalNamespaces->fReaderNum = 0xFFFFFFFF; |
| fGlobalNamespaces->fChildCount = 0; |
| fGlobalNamespaces->fValidationFlag = false; |
| fGlobalNamespaces->fCommentOrPISeen = false; |
| fGlobalNamespaces->fReferenceEscaped = false; |
| fGlobalNamespaces->fCurrentURI = fUnknownNamespaceId; |
| fGlobalNamespaces->fCurrentScope = Grammar::TOP_LEVEL_SCOPE; |
| fGlobalNamespaces->fCurrentGrammar = 0; |
| } |
| |
| // Map the prefix to its unique id |
| const unsigned int prefId = fPrefixPool.addOrFind(prefixToAdd); |
| |
| // |
| // Add a new element to the prefix map for this element. If its full, |
| // then expand it out. |
| // |
| if (fGlobalNamespaces->fMapCount == fGlobalNamespaces->fMapCapacity) |
| expandMap(fGlobalNamespaces); |
| |
| // |
| // And now add a new element for this prefix. Watch for the special case |
| // of xmlns=="", and force it to ""=[globalid] |
| // |
| fGlobalNamespaces->fMap[fGlobalNamespaces->fMapCount].fPrefId = prefId; |
| if ((prefId == fGlobalPoolId) && (uriId == fEmptyNamespaceId)) |
| fGlobalNamespaces->fMap[fGlobalNamespaces->fMapCount].fURIId = fEmptyNamespaceId; |
| else |
| fGlobalNamespaces->fMap[fGlobalNamespaces->fMapCount].fURIId = uriId; |
| |
| // Bump the map count now |
| fGlobalNamespaces->fMapCount++; |
| } |
| |
| void ElemStack::addPrefix( const XMLCh* const prefixToAdd |
| , const unsigned int uriId) |
| { |
| if (!fStackTop) |
| ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager); |
| |
| // Get a convenience pointer to the stack top row |
| StackElem* curRow = fStack[fStackTop - 1]; |
| |
| // Map the prefix to its unique id |
| const unsigned int prefId = fPrefixPool.addOrFind(prefixToAdd); |
| |
| // |
| // Add a new element to the prefix map for this element. If its full, |
| // then expand it out. |
| // |
| if (curRow->fMapCount == curRow->fMapCapacity) |
| expandMap(curRow); |
| |
| // |
| // And now add a new element for this prefix. Watch for the special case |
| // of xmlns=="", and force it to ""=[globalid] |
| // |
| curRow->fMap[curRow->fMapCount].fPrefId = prefId; |
| if ((prefId == fGlobalPoolId) && (uriId == fEmptyNamespaceId)) |
| curRow->fMap[curRow->fMapCount].fURIId = fEmptyNamespaceId; |
| else |
| curRow->fMap[curRow->fMapCount].fURIId = uriId; |
| |
| // Bump the map count now |
| curRow->fMapCount++; |
| } |
| |
| |
| unsigned int ElemStack::mapPrefixToURI( const XMLCh* const prefixToMap |
| , bool& unknown) const |
| { |
| // Assume we find it |
| unknown = false; |
| |
| // |
| // Map the prefix to its unique id, from the prefix string pool. If its |
| // not a valid prefix, then its a failure. |
| // |
| unsigned int prefixId = (!prefixToMap || !*prefixToMap)?fGlobalPoolId : fPrefixPool.getId(prefixToMap); |
| if (prefixId == 0) |
| { |
| unknown = true; |
| return fUnknownNamespaceId; |
| } |
| // |
| // Check for the special prefixes 'xml' and 'xmlns' since they cannot |
| // be overridden. |
| // |
| else if (prefixId == fXMLPoolId) |
| return fXMLNamespaceId; |
| else if (prefixId == fXMLNSPoolId) |
| return fXMLNSNamespaceId; |
| |
| // |
| // Start at the stack top and work backwards until we come to some |
| // element that mapped this prefix. |
| // |
| for (XMLSize_t index = fStackTop; index > 0; index--) |
| { |
| // Get a convenience pointer to the current element |
| StackElem* curRow = fStack[index-1]; |
| |
| // Search the map at this level for the passed prefix |
| for (XMLSize_t mapIndex = 0; mapIndex < curRow->fMapCount; mapIndex++) |
| { |
| if (curRow->fMap[mapIndex].fPrefId == prefixId) |
| return curRow->fMap[mapIndex].fURIId; |
| } |
| } |
| // If the prefix wasn't found, try in the global namespaces |
| if(fGlobalNamespaces) |
| { |
| for (XMLSize_t mapIndex = 0; mapIndex < fGlobalNamespaces->fMapCount; mapIndex++) |
| { |
| if (fGlobalNamespaces->fMap[mapIndex].fPrefId == prefixId) |
| return fGlobalNamespaces->fMap[mapIndex].fURIId; |
| } |
| } |
| |
| // |
| // If the prefix is an empty string, then we will return the special |
| // global namespace id. This can be overridden, but no one has or we |
| // would have not gotten here. |
| // |
| if (!*prefixToMap) |
| return fEmptyNamespaceId; |
| |
| // Oh well, don't have a clue so return the unknown id |
| unknown = true; |
| return fUnknownNamespaceId; |
| } |
| |
| |
| ValueVectorOf<PrefMapElem*>* ElemStack::getNamespaceMap() const |
| { |
| fNamespaceMap->removeAllElements(); |
| |
| // Start at the stack top and work backwards until we come to some |
| // element that mapped this prefix. |
| for (XMLSize_t index = fStackTop; index > 0; index--) |
| { |
| // Get a convenience pointer to the current element |
| StackElem* curRow = fStack[index-1]; |
| |
| // If no prefixes mapped at this level, then go the next one |
| if (!curRow->fMapCount) |
| continue; |
| |
| // Search the map at this level for the passed prefix |
| for (XMLSize_t mapIndex = 0; mapIndex < curRow->fMapCount; mapIndex++) |
| fNamespaceMap->addElement(&(curRow->fMap[mapIndex])); |
| } |
| // Add the global namespaces |
| if(fGlobalNamespaces) |
| { |
| for (XMLSize_t mapIndex = 0; mapIndex < fGlobalNamespaces->fMapCount; mapIndex++) |
| fNamespaceMap->addElement(&(fGlobalNamespaces->fMap[mapIndex])); |
| } |
| |
| return fNamespaceMap; |
| } |
| |
| // --------------------------------------------------------------------------- |
| // ElemStack: Miscellaneous methods |
| // --------------------------------------------------------------------------- |
| void ElemStack::reset( const unsigned int emptyId |
| , const unsigned int unknownId |
| , const unsigned int xmlId |
| , const unsigned int xmlNSId) |
| { |
| if(fGlobalNamespaces) |
| { |
| fMemoryManager->deallocate(fGlobalNamespaces->fMap); |
| delete fGlobalNamespaces; |
| fGlobalNamespaces = 0; |
| } |
| |
| // Reset the stack top to clear the stack |
| fStackTop = 0; |
| |
| // if first time, put in the standard prefixes |
| if (fXMLPoolId == 0) { |
| |
| fGlobalPoolId = fPrefixPool.addOrFind(XMLUni::fgZeroLenString); |
| fXMLPoolId = fPrefixPool.addOrFind(XMLUni::fgXMLString); |
| fXMLNSPoolId = fPrefixPool.addOrFind(XMLUni::fgXMLNSString); |
| } |
| |
| // And store the new special URI ids |
| fEmptyNamespaceId = emptyId; |
| fUnknownNamespaceId = unknownId; |
| fXMLNamespaceId = xmlId; |
| fXMLNSNamespaceId = xmlNSId; |
| } |
| |
| |
| // --------------------------------------------------------------------------- |
| // ElemStack: Private helpers |
| // --------------------------------------------------------------------------- |
| void ElemStack::expandMap(StackElem* const toExpand) |
| { |
| // For convenience get the old map size |
| const XMLSize_t oldCap = toExpand->fMapCapacity; |
| |
| // |
| // Expand the capacity by 25%, or initialize it to 16 if its currently |
| // empty. Then allocate a new temp buffer. |
| // |
| const XMLSize_t newCapacity = oldCap ? |
| (XMLSize_t )(oldCap * 1.25) : 16; |
| PrefMapElem* newMap = (PrefMapElem*) fMemoryManager->allocate |
| ( |
| newCapacity * sizeof(PrefMapElem) |
| );//new PrefMapElem[newCapacity]; |
| |
| // |
| // Copy over the old stuff. We DON'T have to zero out the new stuff |
| // since this is a by value map and the current map index controls what |
| // is relevant. |
| // |
| memcpy(newMap, toExpand->fMap, oldCap * sizeof(PrefMapElem)); |
| |
| // Delete the old map and store the new stuff |
| fMemoryManager->deallocate(toExpand->fMap);//delete [] toExpand->fMap; |
| toExpand->fMap = newMap; |
| toExpand->fMapCapacity = newCapacity; |
| } |
| |
| void ElemStack::expandStack() |
| { |
| // Expand the capacity by 25% and allocate a new buffer |
| const XMLSize_t newCapacity = (XMLSize_t)(fStackCapacity * 1.25); |
| StackElem** newStack = (StackElem**) fMemoryManager->allocate |
| ( |
| newCapacity * sizeof(StackElem*) |
| );//new StackElem*[newCapacity]; |
| |
| // Copy over the old stuff |
| memcpy(newStack, fStack, fStackCapacity * sizeof(StackElem*)); |
| |
| // |
| // And zero out the new stuff. Though we use a stack top, we reuse old |
| // stack contents so we need to know if elements have been initially |
| // allocated or not as we push new stuff onto the stack. |
| // |
| memset |
| ( |
| &newStack[fStackCapacity] |
| , 0 |
| , (newCapacity - fStackCapacity) * sizeof(StackElem*) |
| ); |
| |
| // Delete the old array and update our members |
| fMemoryManager->deallocate(fStack);//delete [] fStack; |
| fStack = newStack; |
| fStackCapacity = newCapacity; |
| } |
| |
| |
| |
| // --------------------------------------------------------------------------- |
| // WFElemStack: Constructors and Destructor |
| // --------------------------------------------------------------------------- |
| WFElemStack::WFElemStack(MemoryManager* const manager) : |
| |
| fEmptyNamespaceId(0) |
| , fGlobalPoolId(0) |
| , fStackCapacity(32) |
| , fStackTop(0) |
| , fUnknownNamespaceId(0) |
| , fXMLNamespaceId(0) |
| , fXMLPoolId(0) |
| , fXMLNSNamespaceId(0) |
| , fXMLNSPoolId(0) |
| , fMapCapacity(0) |
| , fMap(0) |
| , fStack(0) |
| , fPrefixPool(109, manager) |
| , fMemoryManager(manager) |
| { |
| // Do an initial allocation of the stack and zero it out |
| fStack = (StackElem**) fMemoryManager->allocate |
| ( |
| fStackCapacity * sizeof(StackElem*) |
| );//new StackElem*[fStackCapacity]; |
| memset(fStack, 0, fStackCapacity * sizeof(StackElem*)); |
| } |
| |
| WFElemStack::~WFElemStack() |
| { |
| // |
| // Start working from the bottom of the stack and clear it out as we |
| // go up. Once we hit an uninitialized one, we can break out. |
| // |
| for (XMLSize_t stackInd = 0; stackInd < fStackCapacity; stackInd++) |
| { |
| // If this entry has been set, then lets clean it up |
| if (!fStack[stackInd]) |
| break; |
| |
| fMemoryManager->deallocate(fStack[stackInd]->fThisElement);//delete [] fStack[stackInd]->fThisElement; |
| delete fStack[stackInd]; |
| } |
| |
| if (fMap) |
| fMemoryManager->deallocate(fMap);//delete [] fMap; |
| |
| // Delete the stack array itself now |
| fMemoryManager->deallocate(fStack);//delete [] fStack; |
| } |
| |
| |
| // --------------------------------------------------------------------------- |
| // WFElemStack: Stack access |
| // --------------------------------------------------------------------------- |
| XMLSize_t WFElemStack::addLevel() |
| { |
| // See if we need to expand the stack |
| if (fStackTop == fStackCapacity) |
| expandStack(); |
| |
| |
| // If this element has not been initialized yet, then initialize it |
| if (!fStack[fStackTop]) |
| { |
| fStack[fStackTop] = new (fMemoryManager) StackElem; |
| fStack[fStackTop]->fThisElement = 0; |
| fStack[fStackTop]->fElemMaxLength = 0; |
| } |
| |
| // Set up the new top row |
| fStack[fStackTop]->fReaderNum = 0xFFFFFFFF; |
| fStack[fStackTop]->fCurrentURI = fUnknownNamespaceId; |
| fStack[fStackTop]->fTopPrefix = -1; |
| |
| if (fStackTop != 0) |
| fStack[fStackTop]->fTopPrefix = fStack[fStackTop - 1]->fTopPrefix; |
| |
| // Bump the top of stack |
| fStackTop++; |
| |
| return fStackTop-1; |
| } |
| |
| |
| XMLSize_t |
| WFElemStack::addLevel(const XMLCh* const toSet, |
| const unsigned int toSetLen, |
| const unsigned int readerNum) |
| { |
| // See if we need to expand the stack |
| if (fStackTop == fStackCapacity) |
| expandStack(); |
| |
| // If this element has not been initialized yet, then initialize it |
| if (!fStack[fStackTop]) |
| { |
| fStack[fStackTop] = new (fMemoryManager) StackElem; |
| fStack[fStackTop]->fThisElement = 0; |
| fStack[fStackTop]->fElemMaxLength = 0; |
| } |
| |
| // Set up the new top row |
| fStack[fStackTop]->fCurrentURI = fUnknownNamespaceId; |
| fStack[fStackTop]->fTopPrefix = -1; |
| |
| // And store the new stuff |
| if (toSetLen > fStack[fStackTop]->fElemMaxLength) { |
| |
| fMemoryManager->deallocate(fStack[fStackTop]->fThisElement);//delete [] fStack[fStackTop]->fThisElement; |
| fStack[fStackTop]->fElemMaxLength = toSetLen; |
| fStack[fStackTop]->fThisElement = (XMLCh*) fMemoryManager->allocate |
| ( |
| (toSetLen + 1) * sizeof(XMLCh) |
| );//new XMLCh[toSetLen + 1]; |
| } |
| |
| XMLString::moveChars(fStack[fStackTop]->fThisElement, toSet, toSetLen + 1); |
| fStack[fStackTop]->fReaderNum = readerNum; |
| |
| if (fStackTop != 0) |
| fStack[fStackTop]->fTopPrefix = fStack[fStackTop - 1]->fTopPrefix; |
| |
| // Bump the top of stack |
| fStackTop++; |
| |
| return fStackTop-1; |
| } |
| |
| |
| |
| const WFElemStack::StackElem* WFElemStack::popTop() |
| { |
| // Watch for an underflow error |
| if (!fStackTop) |
| ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_StackUnderflow, fMemoryManager); |
| |
| fStackTop--; |
| return fStack[fStackTop]; |
| } |
| |
| |
| void |
| WFElemStack::setElement(const XMLCh* const toSet, |
| const unsigned int toSetLen, |
| const unsigned int readerNum) |
| { |
| if (!fStackTop) |
| ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager); |
| |
| if (toSetLen > fStack[fStackTop - 1]->fElemMaxLength) { |
| |
| fMemoryManager->deallocate(fStack[fStackTop - 1]->fThisElement);//delete [] fStack[fStackTop - 1]->fThisElement; |
| fStack[fStackTop - 1]->fElemMaxLength = toSetLen; |
| fStack[fStackTop - 1]->fThisElement = (XMLCh*) fMemoryManager->allocate |
| ( |
| (toSetLen + 1) * sizeof(XMLCh) |
| );//new XMLCh[toSetLen + 1]; |
| } |
| |
| XMLString::moveChars(fStack[fStackTop - 1]->fThisElement, toSet, toSetLen + 1); |
| fStack[fStackTop - 1]->fReaderNum = readerNum; |
| } |
| |
| |
| // --------------------------------------------------------------------------- |
| // WFElemStack: Stack top access |
| // --------------------------------------------------------------------------- |
| const WFElemStack::StackElem* WFElemStack::topElement() const |
| { |
| if (!fStackTop) |
| ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager); |
| |
| return fStack[fStackTop - 1]; |
| } |
| |
| |
| // --------------------------------------------------------------------------- |
| // WFElemStack: Prefix map methods |
| // --------------------------------------------------------------------------- |
| void WFElemStack::addPrefix( const XMLCh* const prefixToAdd |
| , const unsigned int uriId) |
| { |
| if (!fStackTop) |
| ThrowXMLwithMemMgr(EmptyStackException, XMLExcepts::ElemStack_EmptyStack, fMemoryManager); |
| |
| // Get a convenience pointer to the stack top row |
| StackElem* curRow = fStack[fStackTop - 1]; |
| |
| // Map the prefix to its unique id |
| const unsigned int prefId = fPrefixPool.addOrFind(prefixToAdd); |
| |
| // |
| // Add a new element to the prefix map for this element. If its full, |
| // then expand it out. |
| // |
| if ((unsigned int)curRow->fTopPrefix + 1 == fMapCapacity) |
| expandMap(); |
| |
| // |
| // And now add a new element for this prefix. Watch for the special case |
| // of xmlns=="", and force it to ""=[globalid] |
| // |
| fMap[curRow->fTopPrefix + 1].fPrefId = prefId; |
| if ((prefId == fGlobalPoolId) && (uriId == fEmptyNamespaceId)) |
| fMap[curRow->fTopPrefix + 1].fURIId = fEmptyNamespaceId; |
| else |
| fMap[curRow->fTopPrefix + 1].fURIId = uriId; |
| |
| // Bump the map count now |
| curRow->fTopPrefix++; |
| } |
| |
| |
| unsigned int WFElemStack::mapPrefixToURI( const XMLCh* const prefixToMap |
| , bool& unknown) const |
| { |
| // Assume we find it |
| unknown = false; |
| |
| // |
| // Map the prefix to its unique id, from the prefix string pool. If its |
| // not a valid prefix, then its a failure. |
| // |
| unsigned int prefixId = fPrefixPool.getId(prefixToMap); |
| if (!prefixId) |
| { |
| unknown = true; |
| return fUnknownNamespaceId; |
| } |
| |
| // |
| // Check for the special prefixes 'xml' and 'xmlns' since they cannot |
| // be overridden. |
| // |
| if (prefixId == fXMLPoolId) |
| return fXMLNamespaceId; |
| else if (prefixId == fXMLNSPoolId) |
| return fXMLNSNamespaceId; |
| |
| // |
| // Start at the stack top and work backwards until we come to some |
| // element that mapped this prefix. |
| // |
| // Get a convenience pointer to the stack top row |
| StackElem* curRow = fStack[fStackTop - 1]; |
| for (int mapIndex = curRow->fTopPrefix; mapIndex >=0; mapIndex--) |
| { |
| if (fMap[mapIndex].fPrefId == prefixId) |
| return fMap[mapIndex].fURIId; |
| } |
| |
| // |
| // If the prefix is an empty string, then we will return the special |
| // global namespace id. This can be overridden, but no one has or we |
| // would have not gotten here. |
| // |
| if (!*prefixToMap) |
| return fEmptyNamespaceId; |
| |
| // Oh well, don't have a clue so return the unknown id |
| unknown = true; |
| return fUnknownNamespaceId; |
| } |
| |
| |
| // --------------------------------------------------------------------------- |
| // WFElemStack: Miscellaneous methods |
| // --------------------------------------------------------------------------- |
| void WFElemStack::reset( const unsigned int emptyId |
| , const unsigned int unknownId |
| , const unsigned int xmlId |
| , const unsigned int xmlNSId) |
| { |
| // Reset the stack top to clear the stack |
| fStackTop = 0; |
| |
| // if first time, put in the standard prefixes |
| if (fXMLPoolId == 0) { |
| |
| fGlobalPoolId = fPrefixPool.addOrFind(XMLUni::fgZeroLenString); |
| fXMLPoolId = fPrefixPool.addOrFind(XMLUni::fgXMLString); |
| fXMLNSPoolId = fPrefixPool.addOrFind(XMLUni::fgXMLNSString); |
| } |
| |
| // And store the new special URI ids |
| fEmptyNamespaceId = emptyId; |
| fUnknownNamespaceId = unknownId; |
| fXMLNamespaceId = xmlId; |
| fXMLNSNamespaceId = xmlNSId; |
| } |
| |
| |
| // --------------------------------------------------------------------------- |
| // WFElemStack: Private helpers |
| // --------------------------------------------------------------------------- |
| void WFElemStack::expandMap() |
| { |
| // |
| // Expand the capacity by 25%, or initialize it to 16 if its currently |
| // empty. Then allocate a new temp buffer. |
| // |
| const XMLSize_t newCapacity = fMapCapacity ? |
| (XMLSize_t)(fMapCapacity * 1.25) : 16; |
| PrefMapElem* newMap = (PrefMapElem*) fMemoryManager->allocate |
| ( |
| newCapacity * sizeof(PrefMapElem) |
| );//new PrefMapElem[newCapacity]; |
| |
| // |
| // Copy over the old stuff. We DON'T have to zero out the new stuff |
| // since this is a by value map and the current map index controls what |
| // is relevant. |
| // |
| if (fMapCapacity) { |
| |
| memcpy(newMap, fMap, fMapCapacity * sizeof(PrefMapElem)); |
| fMemoryManager->deallocate(fMap);//delete [] fMap; |
| } |
| |
| fMap = newMap; |
| fMapCapacity = newCapacity; |
| } |
| |
| void WFElemStack::expandStack() |
| { |
| // Expand the capacity by 25% and allocate a new buffer |
| const XMLSize_t newCapacity = (XMLSize_t)(fStackCapacity * 1.25); |
| StackElem** newStack = (StackElem**) fMemoryManager->allocate |
| ( |
| newCapacity * sizeof(StackElem*) |
| );//new StackElem*[newCapacity]; |
| |
| // Copy over the old stuff |
| memcpy(newStack, fStack, fStackCapacity * sizeof(StackElem*)); |
| |
| // |
| // And zero out the new stuff. Though we use a stack top, we reuse old |
| // stack contents so we need to know if elements have been initially |
| // allocated or not as we push new stuff onto the stack. |
| // |
| memset |
| ( |
| &newStack[fStackCapacity] |
| , 0 |
| , (newCapacity - fStackCapacity) * sizeof(StackElem*) |
| ); |
| |
| // Delete the old array and update our members |
| fMemoryManager->deallocate(fStack);//delete [] fStack; |
| fStack = newStack; |
| fStackCapacity = newCapacity; |
| } |
| |
| |
| XERCES_CPP_NAMESPACE_END |