knoaman 2002/12/03 18:23:50 Modified: c/src/xercesc/internal ElemStack.hpp ElemStack.cpp Log: Scanner re-organization. Revision Changes Path 1.3 +202 -0 xml-xerces/c/src/xercesc/internal/ElemStack.hpp Index: ElemStack.hpp =================================================================== RCS file: /home/cvs/xml-xerces/c/src/xercesc/internal/ElemStack.hpp,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- ElemStack.hpp 4 Nov 2002 14:58:18 -0000 1.2 +++ ElemStack.hpp 4 Dec 2002 02:23:50 -0000 1.3 @@ -56,6 +56,9 @@ /* * $Log$ + * Revision 1.3 2002/12/04 02:23:50 knoaman + * Scanner re-organization. + * * Revision 1.2 2002/11/04 14:58:18 tng * C++ Namespace Support. * @@ -336,6 +339,185 @@ }; +class XMLPARSER_EXPORT WFElemStack +{ +public : + // ----------------------------------------------------------------------- + // Class specific data types + // + // These really should be private, but some of the compilers we have to + // support are too dumb to deal with that. + // + // PrefMapElem + // fURIId is the id of the URI from the validator's URI map. The + // fPrefId is the id of the prefix from our own prefix pool. The + // namespace stack consists of these elements. + // + // StackElem + // fThisElement is the basic element decl for the current element. + // The fRowCapacity is how large fChildIds has grown so far. + // fChildCount is how many of them are valid right now. + // + // The fMapCapacity is how large fMap has grown so far. fMapCount + // is how many of them are valid right now. + // + // Note that we store the reader number we were in when we found the + // start tag. We'll use this at the end tag to test for unbalanced + // markup in entities. + // + // MapModes + // When a prefix is mapped to a namespace id, it matters whether the + // QName being mapped is an attribute or name. Attributes are not + // affected by an sibling xmlns attributes, whereas elements are + // affected by its own xmlns attributes. + // ----------------------------------------------------------------------- + struct PrefMapElem + { + unsigned int fPrefId; + unsigned int fURIId; + }; + + struct StackElem + { + int fTopPrefix; + unsigned int fCurrentURI; + unsigned int fReaderNum; + unsigned int fElemMaxLength; + XMLCh* fThisElement; + }; + + enum MapModes + { + Mode_Attribute + , Mode_Element + }; + + + // ----------------------------------------------------------------------- + // Constructors and Destructor + // ----------------------------------------------------------------------- + WFElemStack(); + ~WFElemStack(); + + + // ----------------------------------------------------------------------- + // Stack access + // ----------------------------------------------------------------------- + unsigned int addLevel(); + unsigned int addLevel(const XMLCh* const toSet, const unsigned int toSetLen, + const unsigned int readerNum); + const StackElem* popTop(); + + + // ----------------------------------------------------------------------- + // Stack top access + // ----------------------------------------------------------------------- + const StackElem* topElement() const; + void setElement(const XMLCh* const toSet, const unsigned int toSetLen, + const unsigned int readerNum); + + void setCurrentURI(unsigned int uri); + unsigned int getCurrentURI(); + + // ----------------------------------------------------------------------- + // Prefix map methods + // ----------------------------------------------------------------------- + void addPrefix + ( + const XMLCh* const prefixToAdd + , const unsigned int uriId + ); + unsigned int mapPrefixToURI + ( + const XMLCh* const prefixToMap + , const MapModes mode + , bool& unknown + ) const; + + + // ----------------------------------------------------------------------- + // Miscellaneous methods + // ----------------------------------------------------------------------- + bool isEmpty() const; + void reset + ( + const unsigned int emptyId + , const unsigned int unknownId + , const unsigned int xmlId + , const unsigned int xmlNSId + ); + + +private : + // ----------------------------------------------------------------------- + // Unimplemented constructors and operators + // ----------------------------------------------------------------------- + WFElemStack(const WFElemStack&); + void operator=(const WFElemStack&); + + + // ----------------------------------------------------------------------- + // Private helper methods + // ----------------------------------------------------------------------- + void expandMap(); + void expandStack(); + + + // ----------------------------------------------------------------------- + // Data members + // + // fEmptyNamespaceId + // This is the special URI id for the "" namespace, which is magic + // because of the xmlns="" operation. + // + // fGlobalPoolId + // This is a special URI id that is returned when the namespace + // prefix is "" and no one has explicitly mapped that prefix to an + // explicit URI (or when they explicitly clear any such mapping, + // which they can also do.) And also its prefix pool id, which is + // stored here for fast access. + // + // fPrefixPool + // This is the prefix pool where prefixes are hashed and given unique + // ids. These ids are used to track prefixes in the element stack. + // + // fStack + // fStackCapacity + // fStackTop + // This the stack array. Its an array of pointers to StackElem + // structures. The capacity is the current high water mark of the + // stack. The top is the current top of stack (i.e. the part of it + // being used.) + // + // fUnknownNamespaceId + // This is the URI id for the special URI that is assigned to any + // prefix which has not been mapped. This lets us keep going after + // issuing the error. + // + // fXMLNamespaceId + // fXMLPoolId + // fXMLNSNamespaceId + // fXMLNSPoolId + // These are the URI ids for the special URIs that are assigned to + // the 'xml' and 'xmlns' namespaces. And also its prefix pool id, + // which is stored here for fast access. + // ----------------------------------------------------------------------- + unsigned int fEmptyNamespaceId; + unsigned int fGlobalPoolId; + unsigned int fStackCapacity; + unsigned int fStackTop; + unsigned int fUnknownNamespaceId; + unsigned int fXMLNamespaceId; + unsigned int fXMLPoolId; + unsigned int fXMLNSNamespaceId; + unsigned int fXMLNSPoolId; + unsigned int fMapCapacity; + PrefMapElem* fMap; + StackElem** fStack; + XMLStringPool fPrefixPool; +}; + + // --------------------------------------------------------------------------- // ElemStack: Miscellaneous methods // --------------------------------------------------------------------------- @@ -387,6 +569,26 @@ fStack[fStackTop-1]->fCurrentURI = uri; return; } + +// --------------------------------------------------------------------------- +// WFElemStack: Miscellaneous methods +// --------------------------------------------------------------------------- +inline bool WFElemStack::isEmpty() const +{ + return (fStackTop == 0); +} + +inline unsigned int WFElemStack::getCurrentURI() +{ + return fStack[fStackTop-1]->fCurrentURI; +} + +inline void WFElemStack::setCurrentURI(unsigned int uri) +{ + fStack[fStackTop-1]->fCurrentURI = uri; + return; +} + XERCES_CPP_NAMESPACE_END 1.3 +352 -0 xml-xerces/c/src/xercesc/internal/ElemStack.cpp Index: ElemStack.cpp =================================================================== RCS file: /home/cvs/xml-xerces/c/src/xercesc/internal/ElemStack.cpp,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- ElemStack.cpp 4 Nov 2002 14:58:18 -0000 1.2 +++ ElemStack.cpp 4 Dec 2002 02:23:50 -0000 1.3 @@ -56,6 +56,9 @@ /* * $Log$ + * Revision 1.3 2002/12/04 02:23:50 knoaman + * Scanner re-organization. + * * Revision 1.2 2002/11/04 14:58:18 tng * C++ Namespace Support. * @@ -528,5 +531,354 @@ fStack = newStack; fStackCapacity = newCapacity; } + + + +// --------------------------------------------------------------------------- +// WFElemStack: Constructors and Destructor +// --------------------------------------------------------------------------- +WFElemStack::WFElemStack() : + + fEmptyNamespaceId(0) + , fGlobalPoolId(0) + , fStackCapacity(32) + , fStackTop(0) + , fUnknownNamespaceId(0) + , fXMLNamespaceId(0) + , fXMLPoolId(0) + , fXMLNSNamespaceId(0) + , fXMLNSPoolId(0) + , fMapCapacity(0) + , fMap(0) + , fStack(0) +{ + // Do an initial allocation of the stack and zero it out + fStack = 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 (unsigned int stackInd = 0; stackInd < fStackCapacity; stackInd++) + { + // If this entry has been set, then lets clean it up + if (!fStack[stackInd]) + break; + + delete [] fStack[stackInd]->fThisElement; + delete fStack[stackInd]; + } + + if (fMap) + delete [] fMap; + + // Delete the stack array itself now + delete [] fStack; +} + + +// --------------------------------------------------------------------------- +// WFElemStack: Stack access +// --------------------------------------------------------------------------- +unsigned int 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 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; +} + + +unsigned int +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 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) { + + delete [] fStack[fStackTop]->fThisElement; + fStack[fStackTop]->fElemMaxLength = toSetLen; + fStack[fStackTop]->fThisElement = 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) + ThrowXML(EmptyStackException, XMLExcepts::ElemStack_StackUnderflow); + + fStackTop--; + return fStack[fStackTop]; +} + + +void +WFElemStack::setElement(const XMLCh* const toSet, + const unsigned int toSetLen, + const unsigned int readerNum) +{ + if (!fStackTop) + ThrowXML(EmptyStackException, XMLExcepts::ElemStack_EmptyStack); + + if (toSetLen > fStack[fStackTop - 1]->fElemMaxLength) { + + delete [] fStack[fStackTop - 1]->fThisElement; + fStack[fStackTop - 1]->fElemMaxLength = toSetLen; + fStack[fStackTop - 1]->fThisElement = 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) + ThrowXML(EmptyStackException, XMLExcepts::ElemStack_EmptyStack); + + return fStack[fStackTop - 1]; +} + + +// --------------------------------------------------------------------------- +// WFElemStack: Prefix map methods +// --------------------------------------------------------------------------- +void WFElemStack::addPrefix( const XMLCh* const prefixToAdd + , const unsigned int uriId) +{ + if (!fStackTop) + ThrowXML(EmptyStackException, XMLExcepts::ElemStack_EmptyStack); + + // 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 + , const MapModes mode + , 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; + } + + // + // If the prefix is empty, and we are in attribute mode, then we assign + // it to the empty namespace because the default namespace does not + // apply to attributes. + // + if (!*prefixToMap && (mode == Mode_Attribute)) + return fEmptyNamespaceId; + + // + // 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 unsigned int newCapacity = fMapCapacity ? + (unsigned int)(fMapCapacity * 1.25) : 16; + PrefMapElem* newMap = 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)); + delete [] fMap; + } + + fMap = newMap; + fMapCapacity = newCapacity; +} + +void WFElemStack::expandStack() +{ + // Expand the capacity by 25% and allocate a new buffer + const unsigned int newCapacity = (unsigned int)(fStackCapacity * 1.25); + StackElem** newStack = 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 + delete [] fStack; + fStack = newStack; + fStackCapacity = newCapacity; +} + XERCES_CPP_NAMESPACE_END
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]