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]