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]

Reply via email to