Logo Search packages:      
Sourcecode: xalan version File versions  Download package

XalanSourceTreeDocument.cpp

/*
 * Copyright 1999-2004 The Apache Software Foundation.
 *
 * Licensed 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.
 */
#include "XalanSourceTreeDocument.hpp"



#include <xercesc/sax/AttributeList.hpp>
#include <xercesc/sax2/Attributes.hpp>



#include <xalanc/XalanDOM/XalanDOMException.hpp>



#include <xalanc/PlatformSupport/PrefixResolver.hpp>
#include <xalanc/PlatformSupport/XalanUnicode.hpp>



#include <xalanc/DOMSupport/DOMServices.hpp>



#include "XalanSourceTreeHelper.hpp"



XALAN_CPP_NAMESPACE_BEGIN



static const XalanDOMString         s_emptyString(XalanMemMgrs::getDummyMemMgr());



bool    XalanSourceTreeDocument::s_poolAllTextNodes = false;



XalanSourceTreeDocument::XalanSourceTreeDocument(
            MemoryManagerType&  theManager,
                  bool                    fPoolAllText,
                  block_size_type         theNamesStringPoolBlockSize,
                  bucket_count_type theNamesStringPoolBucketCount,
                  bucket_size_type  theNamesStringPoolBucketSize,
                  block_size_type         theValuesStringPoolBlockSize,
                  bucket_count_type theValuesStringPoolBucketCount,
                  bucket_size_type  theValuesStringPoolBucketSize) :
      XalanDocument(),
      m_firstChild(0),
      m_documentElement(0),
      m_attributeAllocator(theManager, eDefaultAttributeAllocatorBlockSize),
      m_attributeNSAllocator(theManager, eDefaultAttributeNSAllocatorBlockSize),
      m_commentAllocator(theManager, eDefaultCommentAllocatorBlockSize),
      m_elementAAllocator(theManager, eDefaultElementAllocatorBlockSize),
      m_elementANSAllocator(theManager, eDefaultElementNSAllocatorBlockSize),
      m_elementNAAllocator(theManager, eDefaultElementAllocatorBlockSize),
      m_elementNANSAllocator(theManager, eDefaultElementNSAllocatorBlockSize),
      m_piAllocator(theManager, eDefaultPIAllocatorBlockSize),
      m_textAllocator(theManager, eDefaultTextAllocatorBlockSize),
      m_textIWSAllocator(theManager, eDefaultTextIWSAllocatorBlockSize),
      m_namesStringPool(theManager, theNamesStringPoolBlockSize, theNamesStringPoolBucketCount, theNamesStringPoolBucketSize),
      m_valuesStringPool(theManager, theValuesStringPoolBlockSize, theValuesStringPoolBucketCount, theValuesStringPoolBucketSize),
      m_attributesVector(theManager),
      m_nextIndexValue(2),
      m_poolAllText(fPoolAllText),
      m_elementsByID(theManager),
      m_unparsedEntityURIs(theManager),
      m_nonPooledStrings(theManager, theValuesStringPoolBlockSize),
      m_stringBuffer(theManager)
{
}

XalanSourceTreeDocument*
XalanSourceTreeDocument::create( 
            MemoryManagerType&  theManager,
                  bool                    fPoolAllText,
                  block_size_type         theNamesStringPoolBlockSize ,
                  bucket_count_type theNamesStringPoolBucketCount,
                  bucket_size_type  theNamesStringPoolBucketSize,
                  block_size_type         theValuesStringPoolBlockSize,
                  bucket_count_type theValuesStringPoolBucketCount,
                  bucket_size_type  theValuesStringPoolBucketSize)
{
        typedef XalanSourceTreeDocument ThisType;
        
        XalanMemMgrAutoPtr<ThisType, false> theGuard( theManager , (ThisType*)theManager.allocate(sizeof(ThisType)));

        ThisType* theResult = theGuard.get();

        new (theResult) ThisType(theManager,
                                 fPoolAllText,
                                 theNamesStringPoolBlockSize,
                                 theNamesStringPoolBucketCount,
                                 theNamesStringPoolBucketSize,
                                 theValuesStringPoolBlockSize,
                                 theValuesStringPoolBucketCount,
                                 theValuesStringPoolBucketSize); 
        theGuard.release();

        return theResult;
}

XalanSourceTreeDocument::XalanSourceTreeDocument(
            MemoryManagerType&      theManager,
                  allocator_size_type           theAttributeBlockSize,
                  allocator_size_type           theAttributeNSBlockSize,
                  allocator_size_type           theCommentBlockSize,
                  allocator_size_type           theElementBlockSize,
                  allocator_size_type           theElementNSBlockSize,
                  allocator_size_type           thePIBlockSize,
                  allocator_size_type           theTextBlockSize,
                  allocator_size_type           theTextIWSBlockSize,
                  bool                          fPoolAllText) :
      XalanDocument(),
      m_firstChild(0),
      m_documentElement(0),
      m_attributeAllocator(theManager, theAttributeBlockSize),
      m_attributeNSAllocator(theManager, theAttributeNSBlockSize),
      m_commentAllocator(theManager, theCommentBlockSize),
      m_elementAAllocator(theManager, theElementBlockSize),
      m_elementANSAllocator(theManager, theElementNSBlockSize),
      m_elementNAAllocator(theManager, theElementBlockSize),
      m_elementNANSAllocator(theManager, theElementNSBlockSize),
      m_piAllocator(theManager, thePIBlockSize),
      m_textAllocator(theManager, theTextBlockSize),
      m_textIWSAllocator(theManager, theTextIWSBlockSize),
      m_namesStringPool(theManager, eDefaultNamesStringPoolBlockSize, eDefaultNamesStringPoolBucketCount, eDefaultNamesStringPoolBucketSize),
      m_valuesStringPool(theManager, eDefaultValuesStringPoolBlockSize, eDefaultValuesStringPoolBucketCount, eDefaultValuesStringPoolBucketSize),
      m_attributesVector(theManager),
      m_nextIndexValue(2),
      m_poolAllText(fPoolAllText),
      m_elementsByID(theManager),
      m_unparsedEntityURIs(theManager),
      m_nonPooledStrings(theManager, eDefaultValuesStringPoolBlockSize),
      m_stringBuffer(theManager)
{
}



XalanSourceTreeDocument::~XalanSourceTreeDocument()
{
}



const XalanDOMString&
XalanSourceTreeDocument::getNodeName() const
{
      return s_nameString;
}



const XalanDOMString&
XalanSourceTreeDocument::getNodeValue() const
{
      return s_emptyString;
}



XalanSourceTreeDocument::NodeType
XalanSourceTreeDocument::getNodeType() const
{
      return DOCUMENT_NODE;
}



XalanNode*
XalanSourceTreeDocument::getParentNode() const
{
      return 0;
}



const XalanNodeList*
XalanSourceTreeDocument::getChildNodes() const
{
      throw XalanDOMException(XalanDOMException::NOT_SUPPORTED_ERR);

      // Dummy return value...
      return 0;
}



XalanNode*
XalanSourceTreeDocument::getFirstChild() const
{
      return m_firstChild;
}



XalanNode*
XalanSourceTreeDocument::getLastChild() const
{
      return m_documentElement;
}



XalanNode*
XalanSourceTreeDocument::getPreviousSibling() const
{
      return 0;
}



XalanNode*
XalanSourceTreeDocument::getNextSibling() const
{
      return 0;
}



const XalanNamedNodeMap*
XalanSourceTreeDocument::getAttributes() const
{
      return 0;
}



XalanDocument*
XalanSourceTreeDocument::getOwnerDocument() const
{
      return 0;
}



#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
XalanNode*
#else
XalanSourceTreeDocument*
#endif
XalanSourceTreeDocument::cloneNode(bool         /* deep */) const
{
      throw XalanDOMException(XalanDOMException::NOT_SUPPORTED_ERR);

      // Dummy return value...
      return 0;
}



XalanNode*
XalanSourceTreeDocument::insertBefore(
                  XalanNode*  /* newChild */,
                  XalanNode*  /* refChild */)
{
      throw XalanDOMException(XalanDOMException::NO_MODIFICATION_ALLOWED_ERR);

      // Dummy return value...
      return 0;
}



XalanNode*
XalanSourceTreeDocument::replaceChild(
                  XalanNode*  /* newChild */,
                  XalanNode*  /* oldChild */)
{
      throw XalanDOMException(XalanDOMException::NO_MODIFICATION_ALLOWED_ERR);

      // Dummy return value...
      return 0;
}



XalanNode*
XalanSourceTreeDocument::removeChild(XalanNode*  /* oldChild */)
{
      throw XalanDOMException(XalanDOMException::NO_MODIFICATION_ALLOWED_ERR);

      // Dummy return value...
      return 0;
}



XalanNode*
XalanSourceTreeDocument::appendChild(XalanNode*       /* newChild */)
{
      throw XalanDOMException(XalanDOMException::NO_MODIFICATION_ALLOWED_ERR);

      // Dummy return value...
      return 0;
}



bool
XalanSourceTreeDocument::hasChildNodes() const
{
      return m_documentElement != 0 ? true : false;
}



void
XalanSourceTreeDocument::setNodeValue(const XalanDOMString&       /* nodeValue */)
{
      throw XalanDOMException(XalanDOMException::NO_MODIFICATION_ALLOWED_ERR);
}



void
XalanSourceTreeDocument::normalize()
{
      throw XalanDOMException(XalanDOMException::NO_MODIFICATION_ALLOWED_ERR);
}


bool
XalanSourceTreeDocument::isSupported(
                  const XalanDOMString&   /* feature */,
                  const XalanDOMString&   /* version */) const
{
      return false;
}



const XalanDOMString&
XalanSourceTreeDocument::getNamespaceURI() const
{
      return s_emptyString;
}



const XalanDOMString&
XalanSourceTreeDocument::getPrefix() const
{
      return s_emptyString;
}



const XalanDOMString&
XalanSourceTreeDocument::getLocalName() const
{
      return s_nameString;
}



void
XalanSourceTreeDocument::setPrefix(const XalanDOMString&    /* prefix */)
{
      throw XalanDOMException(XalanDOMException::NO_MODIFICATION_ALLOWED_ERR);
}



bool
XalanSourceTreeDocument::isIndexed() const
{
      return true;
}



XalanSourceTreeDocument::IndexType
XalanSourceTreeDocument::getIndex() const
{
      return 1;
}



XalanElement*
XalanSourceTreeDocument::createElement(const XalanDOMString&      /* tagName */)
{
      throw XalanDOMException(XalanDOMException::NOT_SUPPORTED_ERR);

      // Dummy return value...
      return 0;
}



XalanDocumentFragment*
XalanSourceTreeDocument::createDocumentFragment()
{
      throw XalanDOMException(XalanDOMException::NOT_SUPPORTED_ERR);

      // Dummy return value...
      return 0;
}



XalanText*
XalanSourceTreeDocument::createTextNode(const XalanDOMString&     /* data */)
{
      throw XalanDOMException(XalanDOMException::NOT_SUPPORTED_ERR);

      // Dummy return value...
      return 0;
}



XalanComment*
XalanSourceTreeDocument::createComment(const XalanDOMString&      /* data */)
{
      throw XalanDOMException(XalanDOMException::NOT_SUPPORTED_ERR);

      // Dummy return value...
      return 0;
}



XalanCDATASection*
XalanSourceTreeDocument::createCDATASection(const XalanDOMString& /* data */)
{
      throw XalanDOMException(XalanDOMException::NOT_SUPPORTED_ERR);

      // Dummy return value...
      return 0;
}



XalanProcessingInstruction*
XalanSourceTreeDocument::createProcessingInstruction(
                  const XalanDOMString&   /* target */,
                  const XalanDOMString&   /* data */)
{
      throw XalanDOMException(XalanDOMException::NOT_SUPPORTED_ERR);

      // Dummy return value...
      return 0;
}



XalanAttr*
XalanSourceTreeDocument::createAttribute(const XalanDOMString&    /* name */)
{
      throw XalanDOMException(XalanDOMException::NOT_SUPPORTED_ERR);

      // Dummy return value...
      return 0;
}



XalanEntityReference*
XalanSourceTreeDocument::createEntityReference(const XalanDOMString&    /* name */)
{
      throw XalanDOMException(XalanDOMException::NOT_SUPPORTED_ERR);

      // Dummy return value...
      return 0;
}



XalanDocumentType*
XalanSourceTreeDocument::getDoctype() const
{
      return 0;
}




XalanDOMImplementation*
XalanSourceTreeDocument::getImplementation() const
{
      return 0;
}



XalanElement*
XalanSourceTreeDocument::getDocumentElement() const
{
      return m_documentElement;
}



XalanNodeList*
XalanSourceTreeDocument::getElementsByTagName(const XalanDOMString&           /* tagname */) const
{
      throw XalanDOMException(XalanDOMException::NOT_SUPPORTED_ERR);

      return 0;
}



XalanNode*
XalanSourceTreeDocument::importNode(
                  XalanNode*  /* importedNode */,
                  bool        /* deep */)
{
      throw XalanDOMException(XalanDOMException::NO_MODIFICATION_ALLOWED_ERR);

      return 0;
}



XalanElement*
XalanSourceTreeDocument::createElementNS(
                  const XalanDOMString&   /* namespaceURI */,
                  const XalanDOMString&   /* qualifiedName */)
{
      throw XalanDOMException(XalanDOMException::NOT_SUPPORTED_ERR);

      return 0;
}



XalanAttr*
XalanSourceTreeDocument::createAttributeNS(
                  const XalanDOMString&   /* namespaceURI */,
                  const XalanDOMString&   /* qualifiedName */)
{
      throw XalanDOMException(XalanDOMException::NOT_SUPPORTED_ERR);

      return 0;
}



XalanNodeList*
XalanSourceTreeDocument::getElementsByTagNameNS(
                  const XalanDOMString&   /* namespaceURI */,
                  const XalanDOMString&   /* localName */) const
{
      throw XalanDOMException(XalanDOMException::NOT_SUPPORTED_ERR);

      // Dummy return value...
      return 0;
}



XalanElement*
XalanSourceTreeDocument::getElementById(const XalanDOMString&     elementId) const
{
      const ElementByIDMapType::const_iterator  i =
            m_elementsByID.find(c_wstr(elementId));

      if (i == m_elementsByID.end())
      {
            return 0;
      }
      else
      {
            return (*i).second;
      }
}



static bool
hasXMLNamespaceAttribute(const AttributeListType&     attrs)
{
      const unsigned int      theLength = attrs.getLength();

      for (unsigned int i = 0; i < theLength; ++i)
      {
            const XalanDOMChar* const     theName =
                  attrs.getName(i);
            assert(theName != 0);

            if(equals(theName, DOMServices::s_XMLNamespacePrefix) == true)
            {
                  return true;
            }
      }

      return false;
}



static bool
hasXMLNamespaceAttribute(const AttributesType&  attrs)
{
      const unsigned int      theLength = attrs.getLength();

      for (unsigned int i = 0; i < theLength; ++i)
      {
            const XalanDOMChar* const     theName =
                  attrs.getQName(i);
            assert(theName != 0);

            if(equals(theName, DOMServices::s_XMLNamespacePrefix) == true)
            {
                  return true;
            }
      }

      return false;
}



size_t
XalanSourceTreeDocument::createAttributes(
                  XalanSourceTreeAttr**         theAttributeVector,
                  const AttributeListType&      attrs,
                  size_t                                    theStartIndex,
                  XalanSourceTreeElement*       theOwnerElement,
                  bool                                fCreateNamespaces,
                  const PrefixResolver*         thePrefixResolver)
{
      const unsigned int      theSAXAttributeCount = attrs.getLength();

      // Now, create the attributes...
      for(unsigned int i = 0; i < theSAXAttributeCount; ++i)
      {
            const XalanDOMChar* const     theName =
                  attrs.getName(i);
            assert(theName != 0);

            const bool  isNamespaceNode = startsWith(theName, DOMServices::s_XMLNamespaceWithSeparator) == true ||
                                    theName == DOMServices::s_XMLNamespace;

            if ((isNamespaceNode == true && fCreateNamespaces == true) ||
                  (isNamespaceNode == false && fCreateNamespaces == false))
            {
                  const XalanDOMChar* const     theValue =
                        attrs.getValue(i);
                  assert(theValue != 0);

                  if (thePrefixResolver == 0)
                  {
                        theAttributeVector[theStartIndex] =
                              m_attributeAllocator.create(
                                    m_namesStringPool.get(theName),
                                    m_valuesStringPool.get(theValue),
                                    theOwnerElement,
                                    m_nextIndexValue++);

                        assert(theAttributeVector[theStartIndex] != 0);
                  }
                  else
                  {
                const XalanDOMChar*    theLocalName = 0;

                        const XalanDOMString* const         theNamespace =
                              getNamespaceForPrefix(
                                          theName,
                                          *thePrefixResolver,
                                          m_stringBuffer,
                                          false,
                            &theLocalName);

                        if (theNamespace == 0 || length(*theNamespace) == 0)
                        {
                              // the prefix was returned by getNamespaceForPrefix()...
                              assert(length(m_stringBuffer) == 0);

                              theAttributeVector[theStartIndex] =
                                    m_attributeAllocator.create(
                                          m_namesStringPool.get(theName),
                                          m_valuesStringPool.get(theValue),
                                          theOwnerElement,
                                          m_nextIndexValue++);

                              assert(theAttributeVector[theStartIndex] != 0);
                        }
                        else
                        {
                    assert(theLocalName != 0);

                              theAttributeVector[theStartIndex] =
                                    m_attributeNSAllocator.create(
                                                m_namesStringPool.get(theName),
                                                m_namesStringPool.get(theLocalName),
                                                m_namesStringPool.get(*theNamespace),
                                                // This is the prefix...
                                                m_namesStringPool.get(m_stringBuffer),
                                                m_valuesStringPool.get(theValue),
                                                theOwnerElement,
                                                m_nextIndexValue++);
                        }
                  }

                  ++theStartIndex;
            }
      }

      return theStartIndex;
}



XalanSourceTreeElement*
XalanSourceTreeDocument::createElementNode(
                  const XalanDOMChar*                 name,
                  const AttributeListType&      attrs,
                  XalanNode*                          theParentNode,
                  XalanNode*                          thePreviousSibling,
                  XalanNode*                          theNextSibling,
                  bool                                fAddXMLNamespaceAttribute)
{
      // We might have typedef'ed this to something smaller than unsigned int.
      AttributesCountType           theAttributeCount = AttributesCountType(attrs.getLength());

      // assert that we didn't lose anything...
      assert(theAttributeCount == attrs.getLength());

      if (fAddXMLNamespaceAttribute == true)
      {
            if (hasXMLNamespaceAttribute(attrs) == true)
            {
                  fAddXMLNamespaceAttribute = false;
            }
            else
            {
                  ++theAttributeCount;
            }
      }

      XalanSourceTreeAttr**         theAttributeVector = 0;
      XalanSourceTreeElement*       theNewElement = 0;

      if (theAttributeCount == 0)
      {
            theNewElement = m_elementNAAllocator.create(
                        m_namesStringPool.get(name),
                        this,
                        theParentNode,
                        thePreviousSibling,
                        theNextSibling,
                        m_nextIndexValue++);
      }
      else
      {
            theAttributeVector = m_attributesVector.allocate(theAttributeCount);

            theNewElement = m_elementAAllocator.create(
                        m_namesStringPool.get(name),
                        this,
                        theAttributeVector,
                        theAttributeCount,
                        theParentNode,
                        thePreviousSibling,
                        theNextSibling,
                        m_nextIndexValue++);
      }
      assert(theNewElement != 0);

      size_t      theIndex = 0;

      if (fAddXMLNamespaceAttribute == true)
      {
            // The constructor parameters for AttrNS are:
            //
            // name
            // local name
            // namespace URI
            // prefix
            // value
            // owner element
            // index
            //
            theAttributeVector[theIndex] =
                        m_attributeNSAllocator.create(
                                    m_namesStringPool.get(DOMServices::s_XMLNamespacePrefix),
                                    m_namesStringPool.get(DOMServices::s_XMLString),
                                    m_namesStringPool.get(DOMServices::s_XMLNamespacePrefixURI),
                                    m_namesStringPool.get(DOMServices::s_XMLNamespace),
                                    m_valuesStringPool.get(DOMServices::s_XMLNamespaceURI),
                                    theNewElement,
                                    m_nextIndexValue++);

            assert(theAttributeVector[theIndex] != 0);

            ++theIndex;
      }

      // Create the namespace "nodes" first...
      theIndex = createAttributes(
                        theAttributeVector,
                        attrs,
                        theIndex,
                        theNewElement,
                        true);

      // Now, create the attribute "nodes"...
      theIndex = createAttributes(
                        theAttributeVector,
                        attrs,
                        theIndex,
                        theNewElement,
                        false);

      return theNewElement;
}



XalanSourceTreeElement*
XalanSourceTreeDocument::createElementNode(
                  const XalanDOMChar*                 tagName,
                  const AttributeListType&      attrs,
                  const PrefixResolver&         thePrefixResolver,
                  XalanNode*                          theParentNode,
                  XalanNode*                          thePreviousSibling,
                  XalanNode*                          theNextSibling,
                  bool                                fAddXMLNamespaceAttribute)
{
      // We might have typedef'ed this to something smaller than unsigned int.
      AttributesCountType           theAttributeCount = AttributesCountType(attrs.getLength());

      // assert that we didn't lose anything...
      assert(theAttributeCount == attrs.getLength());

      if (fAddXMLNamespaceAttribute == true)
      {
            if (hasXMLNamespaceAttribute(attrs) == true)
            {
                  fAddXMLNamespaceAttribute = false;
            }
            else
            {
                  ++theAttributeCount;
            }
      }

      XalanSourceTreeAttr** const         theAttributeVector =
            theAttributeCount == 0 ? 0 : m_attributesVector.allocate(theAttributeCount);

      XalanSourceTreeElement* const theNewElement =
            createElementNode(
                  tagName,
                  theAttributeVector,
                  theAttributeCount,
                  theParentNode,
                  thePreviousSibling,
                  theNextSibling,
                  thePrefixResolver);

      assert(theNewElement != 0);

      size_t      theIndex = 0;

      if (fAddXMLNamespaceAttribute == true)
      {
            // The constructor parameters for AttrNS are:
            //
            // name
            // local name
            // namespace URI
            // prefix
            // value
            // owner element
            // index
            //
            theAttributeVector[theIndex] =
                        m_attributeNSAllocator.create(
                                    m_namesStringPool.get(DOMServices::s_XMLNamespacePrefix),
                                    m_namesStringPool.get(DOMServices::s_XMLString),
                                    m_namesStringPool.get(DOMServices::s_XMLNamespacePrefixURI),
                                    m_namesStringPool.get(DOMServices::s_XMLNamespace),
                                    m_valuesStringPool.get(DOMServices::s_XMLNamespaceURI),
                                    theNewElement,
                                    m_nextIndexValue++);

            assert(theAttributeVector[theIndex] != 0);

            ++theIndex;
      }

      // Create the namespace "nodes" first...
      theIndex = createAttributes(
                        theAttributeVector,
                        attrs,
                        theIndex,
                        theNewElement,
                        true,
                &thePrefixResolver);

      // Now, create the attribute "nodes"...
      theIndex = createAttributes(
                        theAttributeVector,
                        attrs,
                        theIndex,
                        theNewElement,
                        false,
                &thePrefixResolver);

      return theNewElement;
}



inline const XalanDOMString&
getElementNodePrefix(
            MemoryManagerType&          theManager,
                  const XalanDOMChar*                 qname,
                  XalanDOMStringPool*                 theStringPool,
                  XalanDOMString::size_type     theLength,              
                  XalanDOMString::size_type     theColonIndex)
{
      if(theColonIndex == theLength)
      {
            return theStringPool->get(XalanDOMString( theManager)); 
      }
      else
      {
            return theStringPool->get(qname, theColonIndex);
      }
}



XalanSourceTreeElement*
XalanSourceTreeDocument::createElementNode(
                  const XalanDOMChar*           uri,
                  const XalanDOMChar*           localname,
                  const XalanDOMChar*           qname,
                  const AttributesType&   attrs,
                  XalanNode*                    theParentNode,
                  XalanNode*                    thePreviousSibling,
                  XalanNode*                    theNextSibling,
                  bool                          fAddXMLNamespaceAttribute)
{

      // We might have typedef'ed this to something smaller than unsigned int.
      AttributesCountType           theAttributeCount = AttributesCountType(attrs.getLength());

      // assert that we didn't lose anything...
      assert(theAttributeCount == attrs.getLength());

      if (fAddXMLNamespaceAttribute == true)
      {
            if (hasXMLNamespaceAttribute(attrs) == true)
            {
                  fAddXMLNamespaceAttribute = false;
            }
            else
            {
                  ++theAttributeCount;
            }
      }

      XalanSourceTreeAttr**         theAttributeVector = 0;
      XalanSourceTreeElement*       theNewElement = 0;

      const XalanDOMString::size_type           theColonIndex = indexOf(qname, XalanUnicode::charColon);
      const XalanDOMString::size_type           theLength = length(qname);

      if (theAttributeCount == 0)
      {

            theNewElement = m_elementNANSAllocator.create(
                        m_namesStringPool.get(qname),
                        m_namesStringPool.get(localname),
                        m_namesStringPool.get(uri),
                        // This is the prefix...
                        getElementNodePrefix( getMemoryManager() , qname, &m_namesStringPool, theLength, theColonIndex),
                        this,
                        theParentNode,
                        thePreviousSibling,
                        theNextSibling,
                        m_nextIndexValue++);
      }
      else
      {
            theAttributeVector = m_attributesVector.allocate(theAttributeCount);

            theNewElement = m_elementANSAllocator.create(
                        m_namesStringPool.get(qname),
                        m_namesStringPool.get(localname),
                        m_namesStringPool.get(uri),
                        // This is the prefix...
                        getElementNodePrefix( getMemoryManager() ,qname, &m_namesStringPool, theLength, theColonIndex),
                        this,
                        theAttributeVector,
                        theAttributeCount,
                        theParentNode,
                        thePreviousSibling,
                        theNextSibling,
                        m_nextIndexValue++);

            createAttributes(attrs, theAttributeVector, theNewElement, fAddXMLNamespaceAttribute);
      }

      return theNewElement;
}



XalanSourceTreeElement*
XalanSourceTreeDocument::createElementNode(
                  const XalanDOMChar*           name,
                  const AttributesType&   attrs,
                  XalanNode*                    theParentNode,
                  XalanNode*                    thePreviousSibling,
                  XalanNode*                    theNextSibling,
                  bool                          fAddXMLNamespaceAttribute)
{
      assert(indexOf(name, XalanUnicode::charColon) == length(name));

      // We might have typedef'ed this to something smaller than unsigned int.
      AttributesCountType           theAttributeCount = AttributesCountType(attrs.getLength());

      // assert that we didn't lose anything...
      assert(theAttributeCount == attrs.getLength());

      if (fAddXMLNamespaceAttribute == true)
      {
            if (hasXMLNamespaceAttribute(attrs) == true)
            {
                  fAddXMLNamespaceAttribute = false;
            }
            else
            {
                  ++theAttributeCount;
            }
      }

      XalanSourceTreeAttr**         theAttributeVector = 0;
      XalanSourceTreeElement*       theNewElement = 0;

      if (theAttributeCount == 0)
      {
            theNewElement = m_elementNAAllocator.create(
                        m_namesStringPool.get(name),
                        this,
                        theParentNode,
                        thePreviousSibling,
                        theNextSibling,
                        m_nextIndexValue++);
      }
      else
      {
            theAttributeVector = m_attributesVector.allocate(theAttributeCount);

            theNewElement = m_elementAAllocator.create(
                        m_namesStringPool.get(name),
                        this,
                        theAttributeVector,
                        theAttributeCount,
                        theParentNode,
                        thePreviousSibling,
                        theNextSibling,
                        m_nextIndexValue++);

            createAttributes(attrs, theAttributeVector, theNewElement, fAddXMLNamespaceAttribute);
      }

      return theNewElement;
}



XalanSourceTreeComment*
XalanSourceTreeDocument::createCommentNode(
                  const XalanDOMChar*                 data,
                  XalanDOMString::size_type     length,
                  XalanNode*                          theParentNode,
                  XalanNode*                          thePreviousSibling,
                  XalanNode*                          theNextSibling)
{
      return m_commentAllocator.create(
                        m_valuesStringPool.get(data, length),
                        this,
                        theParentNode,
                        thePreviousSibling,
                        theNextSibling,
                        m_nextIndexValue++);
}



XalanSourceTreeProcessingInstruction*
XalanSourceTreeDocument::createProcessingInstructionNode(
                  const XalanDOMChar*           target,
                  const XalanDOMChar*           data,
                  XalanNode*                    theParentNode,
                  XalanNode*                    thePreviousSibling,
                  XalanNode*                    theNextSibling)
{
      assert(target != 0);
      assert(data != 0);

      return m_piAllocator.create(
                        m_namesStringPool.get(target),
                        m_valuesStringPool.get(data),
                        this,
                        theParentNode,
                        thePreviousSibling,
                        theNextSibling,
                        m_nextIndexValue++);
}



inline const XalanDOMString&
XalanSourceTreeDocument::getTextNodeString(
                  const XalanDOMChar*                 chars,
                  XalanDOMString::size_type     length)
{
      if (m_poolAllText == true)
      {
            return m_valuesStringPool.get(chars, length);
      }
      else
      {
            XalanDOMString* const   theString =
                        m_nonPooledStrings.create(chars, length);
        assert(theString != 0);

            return *theString;
      }
}



const XalanDOMString*
XalanSourceTreeDocument::getNamespaceForPrefix(
                  const XalanDOMChar*           theName,
                  const PrefixResolver&   thePrefixResolver,
                  XalanDOMString&               thePrefix,
                  bool                          fUseDefault,
            const XalanDOMChar**    theLocalName)
{
      const XalanDOMString::size_type           theLength = length(theName);
      const XalanDOMString::size_type           theColonIndex = indexOf(theName, XalanUnicode::charColon);

      if (theColonIndex != theLength)
      {
            // Get the prefix from theName...
            assign(thePrefix, theName, theColonIndex);
            assert(length(thePrefix) != 0);

        if (theLocalName != 0)
        {
            *theLocalName = theName + theColonIndex + 1;
        }

            return thePrefixResolver.getNamespaceForPrefix(thePrefix);
      }
      else
      {
            clear(thePrefix);

        if (theLocalName != 0)
        {
            *theLocalName = theName;
        }

            if (fUseDefault == false)
            {
                  return 0;
            }
            else
            {
                  return thePrefixResolver.getNamespaceForPrefix(s_emptyString);
            }
      }
}



XalanSourceTreeText*
XalanSourceTreeDocument::createTextNode(
                  const XalanDOMChar*                 chars,
                  XalanDOMString::size_type     length,
                  XalanNode*                          theParentNode,
                  XalanNode*                          thePreviousSibling,
                  XalanNode*                          theNextSibling)
{
      assert(chars != 0);

      if (isXMLWhitespace(chars, 0, length) == true)
      {
            const XalanDOMString&   theString = m_valuesStringPool.get(chars, length);

            return m_textIWSAllocator.create(
                        theString,
                        theParentNode,
                        thePreviousSibling,
                        theNextSibling,
                        m_nextIndexValue++);
      }
      else
      {
            return m_textAllocator.create(
                        getTextNodeString(chars, length),
                        theParentNode,
                        thePreviousSibling,
                        theNextSibling,
                        m_nextIndexValue++);
      }
}



XalanSourceTreeText*
XalanSourceTreeDocument::createTextIWSNode(
                  const XalanDOMChar*                 chars,
                  XalanDOMString::size_type     length,
                  XalanNode*                          theParentNode,
                  XalanNode*                          thePreviousSibling,
                  XalanNode*                          theNextSibling)
{
      assert(chars != 0);

      return m_textIWSAllocator.create(
                  m_valuesStringPool.get(chars, length),
                  theParentNode,
                  thePreviousSibling,
                  theNextSibling,
                  m_nextIndexValue++);
}



void
XalanSourceTreeDocument::unparsedEntityDeclaration(
                  const XalanDOMChar*           name,
                  const XalanDOMChar*           /* publicId */,
                  const XalanDOMChar*           systemId,
                  const XalanDOMChar*           /* notationName */)
{
      m_unparsedEntityURIs[XalanDOMString(name, getMemoryManager())] = XalanDOMString(systemId, getMemoryManager());
}



const XalanDOMString&
XalanSourceTreeDocument::getUnparsedEntityURI(const XalanDOMString&           theName) const
{
      const UnparsedEntityURIMapType::const_iterator  i =
            m_unparsedEntityURIs.find(theName);

      if (i != m_unparsedEntityURIs.end())
      {
            return (*i).second;
      }
      else
      {
            return s_emptyString;
      }
}



XalanSourceTreeAttr*
XalanSourceTreeDocument::createAttribute(
                  const XalanDOMChar*                 theName,
                  const XalanDOMChar*                 theValue,
                  XalanSourceTreeElement*       theOwnerElement,
                  const PrefixResolver&         thePrefixResolver)
{
      // Get the namespace for the theName.  Since attributes do not use
      // the default namespace, make sure we don't get it...
      const XalanDOMString* const         theNamespace =
            getNamespaceForPrefix(
                        theName,
                        thePrefixResolver,
                        m_stringBuffer,
                        false);

      assert(theNamespace == 0 && length(m_stringBuffer) == 0 ||
               theNamespace != 0 && length(m_stringBuffer) != 0);

      if (theNamespace == 0 || length(*theNamespace) == 0)
      {
            return m_attributeAllocator.create(
                        m_namesStringPool.get(theName),
                        m_valuesStringPool.get(theValue),
                        theOwnerElement,
                        m_nextIndexValue++);
      }
      else
      {
            // There must be a prefix, so we don't have to check to see if
            // we got one...

            // The constructor parameters for AttrNS are:
            //
            // name
            // local name
            // namespace URI
            // prefix
            // value
            // owner element
            // index
            //
            return m_attributeNSAllocator.create(
                        m_namesStringPool.get(theName),
                        m_namesStringPool.get(theName + length(m_stringBuffer) + 1),
                        m_namesStringPool.get(*theNamespace),
                        // This is the prefix...
                        m_namesStringPool.get(m_stringBuffer),
                        m_valuesStringPool.get(theValue),
                        theOwnerElement,
                        m_nextIndexValue++);
      }
}



XalanSourceTreeElement*
XalanSourceTreeDocument::createElementNode(
                  const XalanDOMChar*           theTagName,
                  XalanSourceTreeAttr**   theAttributeVector,
                  AttributesCountType           theAttributeCount,
                  XalanNode*                    theParentNode,
                  XalanNode*                    thePreviousSibling,
                  XalanNode*                    theNextSibling,
                  const PrefixResolver&   thePrefixResolver)
{
      const XalanDOMString* const         theNamespace =
            getNamespaceForPrefix(
                        theTagName,
                        thePrefixResolver,
                        m_stringBuffer,
                        true);

      if (theNamespace == 0 || length(*theNamespace) == 0)
      {
            // the prefix was returned by getNamespaceForPrefix()...
            assert(length(m_stringBuffer) == 0);

            if (theAttributeCount == 0)
            {
                  return m_elementNAAllocator.create(
                              m_namesStringPool.get(theTagName),
                              this,
                              theParentNode,
                              thePreviousSibling,
                              theNextSibling,
                              m_nextIndexValue++);
            }
            else
            {
                  return m_elementAAllocator.create(
                              m_namesStringPool.get(theTagName),
                              this,
                              theAttributeVector,
                              theAttributeCount,
                              theParentNode,
                              thePreviousSibling,
                              theNextSibling,
                              m_nextIndexValue++);
            }
      }
      else
      {
            // We need figure out if there's a prefix on theTagName.  If not,
            // the local name is the same as the tag name.  Otherwise, we need
            // to remove the prefix and the ':' that separates them.  If
            // m_stringBuffer is of length 0, there's no prefix.
            const XalanDOMString::size_type           thePrefixLength = length(m_stringBuffer);

            const XalanDOMChar* const                 theLocalName =
                  thePrefixLength == 0 ? theTagName : theTagName + thePrefixLength + 1;

            // The constructor parameters for ElementNS are:
            //
            // tag name
            // local name
            // namespace URI
            // prefix
            // owner document
            // attributes
            // attribute count
            // parent element
            // previous sibling
            // next sibling
            // index
            //
            if (theAttributeCount == 0)
            {
                  return m_elementNANSAllocator.create(
                              m_namesStringPool.get(theTagName),
                              m_namesStringPool.get(theLocalName),
                              m_namesStringPool.get(*theNamespace),
                              m_namesStringPool.get(m_stringBuffer),
                              this,
                              theParentNode,
                              thePreviousSibling,
                              theNextSibling,
                              m_nextIndexValue++);
            }
            else
            {
                  return m_elementANSAllocator.create(
                              m_namesStringPool.get(theTagName),
                              m_namesStringPool.get(theLocalName),
                              m_namesStringPool.get(*theNamespace),
                              m_namesStringPool.get(m_stringBuffer),
                              this,
                              theAttributeVector,
                              theAttributeCount,
                              theParentNode,
                              thePreviousSibling,
                              theNextSibling,
                              m_nextIndexValue++);
            }
      }
}



size_t
XalanSourceTreeDocument::createAttributes(
                  XalanSourceTreeAttr**         theAttributeVector,
                  const AttributesType&         theAttributes,
                  size_t                                    theStartIndex,
                  XalanSourceTreeElement*       theOwnerElement,
                  bool                                fCreateNamespaces)
{
      const unsigned int      theSAXAttributeCount = theAttributes.getLength();

      // Now, create the attributes...
      for(unsigned int i = 0; i < theSAXAttributeCount; ++i)
      {
            const XalanDOMChar* const     theQName =
                  theAttributes.getQName(i);
            assert(theQName != 0);

            const bool  isNamespaceNode = startsWith(theQName, DOMServices::s_XMLNamespaceWithSeparator) == true ||
                                    theQName == DOMServices::s_XMLNamespace;

            if ((isNamespaceNode == true && fCreateNamespaces == true) ||
                  (isNamespaceNode == false && fCreateNamespaces == false))
            {
                  const XalanDOMChar* const     theValue =
                        theAttributes.getValue(i);
                  assert(theValue != 0);

                  const XalanDOMChar* const     theURI =
                        theAttributes.getURI(i);
                  assert(theURI != 0);

                  if (length(theURI) == 0)
                  {
                        theAttributeVector[theStartIndex] =
                              m_attributeAllocator.create(
                                    m_namesStringPool.get(theQName),
                                    m_valuesStringPool.get(theValue),
                                    theOwnerElement,
                                    m_nextIndexValue++);
                  }
                  else
                  {
                        const XalanDOMChar* const     theLocalName =
                              theAttributes.getLocalName(i);
                        assert(theLocalName != 0);

                        const XalanDOMString::size_type           theColonIndex = indexOf(theQName, XalanUnicode::charColon);
                        assert(theColonIndex != length(theQName));

                        // The constructor parameters for AttrNS are:
                        //
                        // name
                        // local name
                        // namespace URI
                        // prefix
                        // value
                        // owner element
                        // index
                        //
                        theAttributeVector[theStartIndex] =
                              m_attributeNSAllocator.create(
                                          m_namesStringPool.get(theQName),
                                          m_namesStringPool.get(theLocalName),
                                          m_namesStringPool.get(theURI),
                                          // This is the prefix...
                                          m_namesStringPool.get(theQName, theColonIndex),
                                          m_valuesStringPool.get(theValue),
                                          theOwnerElement,
                                          m_nextIndexValue++);
                  }

                  // OK, now let's see if we have an ID attribute...
                  const XalanDOMChar*           theType =
                        theAttributes.getType(i);

                  // Look for an attribute that was declared as type ID in the DTD.
                  // Note that we can just save a pointer to the attribute's XalanDOMString
                  // data, since the attribute is guaranteed to exist for as long as the
                  // document does.
                  if (*theType == XalanUnicode::charLetter_I &&
                        *++theType == XalanUnicode::charLetter_D &&
                        *++theType == 0)
                  {
                        // The XPath says that if there are duplicate IDs, the first node is
                        // always returned, so use insert(), rather than []
                        m_elementsByID.insert(
                              ElementByIDMapType::value_type(
                                    c_wstr(theAttributeVector[theStartIndex]->getValue()),
                                    theOwnerElement));
                  }

                  ++theStartIndex;
            }
      }

      return theStartIndex;
}



void
XalanSourceTreeDocument::createAttributes(
                  const AttributesType&         theAttributes,
                  XalanSourceTreeAttr**         theAttributeVector,
                  XalanSourceTreeElement*       theOwnerElement,
                  bool                                fAddXMLNamespaceAttribute)
{
      size_t      theIndex = 0;

      if (fAddXMLNamespaceAttribute == true)
      {
            // The constructor parameters for AttrNS are:
            //
            // name
            // local name
            // namespace URI
            // prefix
            // value
            // owner element
            // index
            //
            theAttributeVector[theIndex] =
                        m_attributeNSAllocator.create(
                                    m_namesStringPool.get(DOMServices::s_XMLNamespacePrefix),
                                    m_namesStringPool.get(DOMServices::s_XMLString),
                                    m_namesStringPool.get(DOMServices::s_XMLNamespacePrefixURI),
                                    m_namesStringPool.get(DOMServices::s_XMLNamespace),
                                    m_valuesStringPool.get(DOMServices::s_XMLNamespaceURI),
                                    theOwnerElement,
                                    m_nextIndexValue++);

            ++theIndex;
      }

      // Create the namespace "nodes" first...
      theIndex = createAttributes(
                        theAttributeVector,
                        theAttributes,
                        theIndex,
                        theOwnerElement,
                        true);

      // Now, create the attribute "nodes"...
      theIndex = createAttributes(
                        theAttributeVector,
                        theAttributes,
                        theIndex,
                        theOwnerElement,
                        false);
}



void
XalanSourceTreeDocument::appendChildNode(XalanSourceTreeComment*  theChild)
{
      XalanSourceTreeHelper::appendSibling(this, m_firstChild, theChild);
}



void
XalanSourceTreeDocument::appendChildNode(XalanSourceTreeElement*  theChild)
{
      if (m_documentElement != 0)
      {
            throw XalanDOMException(XalanDOMException::HIERARCHY_REQUEST_ERR);
      }
      else
      {
            m_documentElement = theChild;

            XalanSourceTreeHelper::appendSibling(this, m_firstChild, theChild);
      }
}



void
XalanSourceTreeDocument::appendChildNode(XalanSourceTreeProcessingInstruction*      theChild)
{
      XalanSourceTreeHelper::appendSibling(this, m_firstChild, theChild);
}



static XalanDOMString   s_staticNameString(XalanMemMgrs::getDummyMemMgr());



const XalanDOMString&   XalanSourceTreeDocument::s_nameString = s_staticNameString;



static const XalanDOMChar     s_document[] =
{
      XalanUnicode::charNumberSign,
      XalanUnicode::charLetter_d,
      XalanUnicode::charLetter_o,
      XalanUnicode::charLetter_c,
      XalanUnicode::charLetter_u,
      XalanUnicode::charLetter_m,
      XalanUnicode::charLetter_e,
      XalanUnicode::charLetter_n,
      XalanUnicode::charLetter_t,
      0
};



void
XalanSourceTreeDocument::initialize(MemoryManagerType& theManager)
{
    XalanDOMString tmpString(s_document, theManager);

      s_staticNameString.swap(tmpString);
}



void
XalanSourceTreeDocument::terminate()
{
      releaseMemory(s_staticNameString, XalanMemMgrs::getDummyMemMgr());
}



XALAN_CPP_NAMESPACE_END

Generated by  Doxygen 1.6.0   Back to index