DOMDocumentImpl.cpp
上传用户:zhuqijet
上传日期:2013-06-25
资源大小:10074k
文件大小:47k
源码类别:

词法分析

开发平台:

Visual C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
  5.  * reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  *
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  *
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in
  16.  *    the documentation and/or other materials provided with the
  17.  *    distribution.
  18.  *
  19.  * 3. The end-user documentation included with the redistribution,
  20.  *    if any, must include the following acknowledgment:
  21.  *       "This product includes software developed by the
  22.  *        Apache Software Foundation (http://www.apache.org/)."
  23.  *    Alternately, this acknowledgment may appear in the software itself,
  24.  *    if and wherever such third-party acknowledgments normally appear.
  25.  *
  26.  * 4. The names "Xerces" and "Apache Software Foundation" must
  27.  *    not be used to endorse or promote products derived from this
  28.  *    software without prior written permission. For written
  29.  *    permission, please contact apache@apache.org.
  30.  *
  31.  * 5. Products derived from this software may not be called "Apache",
  32.  *    nor may "Apache" appear in their name, without prior written
  33.  *    permission of the Apache Software Foundation.
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38.  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42.  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44.  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45.  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46.  * SUCH DAMAGE.
  47.  * ====================================================================
  48.  *
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Software Foundation, and was
  51.  * originally based on software copyright (c) 2001, International
  52.  * Business Machines, Inc., http://www.ibm.com .  For more information
  53.  * on the Apache Software Foundation, please see
  54.  * <http://www.apache.org/>.
  55.  */
  56. /*
  57.  * $Id: DOMDocumentImpl.cpp,v 1.43 2003/05/23 17:07:41 knoaman Exp $
  58.  */
  59. #include "DOMDocumentImpl.hpp"
  60. #include "DOMCasts.hpp"
  61. #include "DOMConfigurationImpl.hpp"
  62. #include "DOMDocumentTypeImpl.hpp"
  63. #include "DOMAttrImpl.hpp"
  64. #include "DOMAttrNSImpl.hpp"
  65. #include "DOMCDATASectionImpl.hpp"
  66. #include "DOMCommentImpl.hpp"
  67. #include "DOMDeepNodeListImpl.hpp"
  68. #include "DOMDocumentFragmentImpl.hpp"
  69. #include "DOMElementImpl.hpp"
  70. #include "XSDElementNSImpl.hpp"
  71. #include "DOMEntityImpl.hpp"
  72. #include "DOMEntityReferenceImpl.hpp"
  73. #include "DOMNamedNodeMapImpl.hpp"
  74. #include "DOMNormalizer.hpp"
  75. #include "DOMNotationImpl.hpp"
  76. #include "DOMProcessingInstructionImpl.hpp"
  77. #include "DOMTextImpl.hpp"
  78. #include "DOMStringPool.hpp"
  79. #include "DOMTreeWalkerImpl.hpp"
  80. #include "DOMNodeIteratorImpl.hpp"
  81. #include "DOMNodeIDMap.hpp"
  82. #include "DOMRangeImpl.hpp"
  83. #include <xercesc/dom/DOMImplementation.hpp>
  84. #include <xercesc/util/XMLChar.hpp>
  85. #include <xercesc/framework/MemoryManager.hpp>
  86. XERCES_CPP_NAMESPACE_BEGIN
  87. //
  88. //   Constructors.   Warning - be very careful with the ordering of initialization
  89. //                             of the heap.  Ordering depends on the order of declaration
  90. //                             in the .hpp file, not on the order of initializers here
  91. //                             in the constructor.  The heap declaration can not be
  92. //                             first - fNode and fParent must be first for the casting
  93. //                             functions in DOMCasts to work correctly.  This means that
  94. //                             fNode and fParent constructors used here can not
  95. //                             allocate.
  96. //
  97. DOMDocumentImpl::DOMDocumentImpl(MemoryManager* const manager)
  98.     : fNode(this),
  99.       fParent(this),
  100.       fCurrentBlock(0),
  101.       fDOMConfiguration(0),
  102.       fFreePtr(0),
  103.       fFreeBytesRemaining(0),
  104.       fDocType(0),
  105.       fDocElement(0),
  106.       fNamePool(0),
  107.       fNormalizer(0),
  108.       fNodeIDMap(0),
  109.       fRanges(0),
  110.       fNodeIterators(0),
  111.       fChanges(0),
  112.       fNodeListPool(0),
  113.       fActualEncoding(0),
  114.       fEncoding(0),
  115.       fVersion(0),
  116.       fStandalone(false),
  117.       fDocumentURI(0),
  118.       fUserDataTable(0),
  119.       fRecycleNodePtr(0),
  120.       fRecycleBufferPtr(0),
  121.       fMemoryManager(manager),
  122.       errorChecking(true)
  123. {
  124.     fNamePool    = new (this) DOMStringPool(257, this);
  125. };
  126. //DOM Level 2
  127. DOMDocumentImpl::DOMDocumentImpl(const XMLCh *fNamespaceURI,
  128.                                const XMLCh *qualifiedName,
  129.                                DOMDocumentType *doctype,
  130.                                MemoryManager* const manager)
  131.     : fNode(this),
  132.       fParent(this),
  133.       fCurrentBlock(0),
  134.       fDOMConfiguration(0),
  135.       fFreePtr(0),
  136.       fFreeBytesRemaining(0),
  137.       fDocType(0),
  138.       fDocElement(0),
  139.       fNamePool(0),
  140.       fNormalizer(0),
  141.       fNodeIDMap(0),
  142.       fRanges(0),
  143.       fNodeIterators(0),
  144.       fChanges(0),
  145.       fNodeListPool(0),
  146.       fActualEncoding(0),
  147.       fEncoding(0),
  148.       fVersion(0),
  149.       fStandalone(false),
  150.       fDocumentURI(0),
  151.       fUserDataTable(0),
  152.       fRecycleNodePtr(0),
  153.       fRecycleBufferPtr(0),
  154.       fMemoryManager(manager),
  155.       errorChecking(true)
  156. {
  157.     fNamePool    = new (this) DOMStringPool(257, this);
  158.     try {
  159.         setDocumentType(doctype);
  160.         if (qualifiedName)
  161.             appendChild(createElementNS(fNamespaceURI, qualifiedName));  //root element
  162.         else if (fNamespaceURI)
  163.             throw DOMException(DOMException::NAMESPACE_ERR, 0);
  164.     }
  165.     catch (...) {
  166.         this->deleteHeap();
  167.         throw;
  168.     }
  169. }
  170. void DOMDocumentImpl::setDocumentType(DOMDocumentType *doctype)
  171. {
  172.     if (!doctype)
  173.         return;
  174.     // New doctypes can be created either with the factory methods on DOMImplementation, in
  175.     //   which case ownerDocument will be 0, or with methods on DocumentImpl, in which case
  176.     //   ownerDocument will be set, but the DocType won't yet be a child of the document.
  177.     if (doctype->getOwnerDocument() != 0 && doctype->getOwnerDocument() != this)
  178.         throw DOMException(    //one doctype can belong to only one DOMDocumentImpl
  179.         DOMException::WRONG_DOCUMENT_ERR, 0);
  180.     DOMDocumentTypeImpl* doctypeImpl = (DOMDocumentTypeImpl*) doctype;
  181.     doctypeImpl->setOwnerDocument(this);
  182.     // The doctype can not have any Entities or Notations yet, because they can not
  183.     //   be created except through factory methods on a document.
  184.     // revisit.  What if this doctype is already a child of the document?
  185.     appendChild(doctype);
  186. }
  187. DOMDocumentImpl::~DOMDocumentImpl()
  188. {
  189.     //  Clean up the fNodeListPool
  190.     if (fNodeListPool)
  191.         fNodeListPool->cleanup();
  192.     if (fRanges)
  193.         delete fRanges; //fRanges->cleanup();
  194.     if (fNodeIterators)
  195.         delete fNodeIterators;//fNodeIterators->cleanup();
  196.     if (fUserDataTable)
  197.         delete fUserDataTable;//fUserDataTable->cleanup();
  198.     if (fRecycleNodePtr) {
  199.         fRecycleNodePtr->deleteAllElements();
  200.         delete fRecycleNodePtr;
  201.     }
  202.     if (fRecycleBufferPtr) {
  203.         delete fRecycleBufferPtr;
  204.     }
  205.     delete fNormalizer;
  206.     //  Delete the heap for this document.  This uncerimoniously yanks the storage
  207.     //      out from under all of the nodes in the document.  Destructors are NOT called.
  208.     this->deleteHeap();
  209. };
  210. DOMNode *DOMDocumentImpl::cloneNode(bool deep) const {
  211.     // Note:  the cloned document node goes on the system heap.  All other
  212.     //   nodes added to the new document will go on that document's heap,
  213.     //   but we need to construct the document first, before its heap exists.
  214.     DOMDocumentImpl *newdoc = new (fMemoryManager) DOMDocumentImpl(fMemoryManager);
  215.     // then the children by _importing_ them
  216.     if (deep)
  217.         for (DOMNode *n = this->getFirstChild(); n != 0; n = n->getNextSibling()) {
  218.             newdoc->appendChild(newdoc->importNode(n, true, true));
  219.     }
  220.     fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newdoc);
  221.     return newdoc;
  222. };
  223. const XMLCh * DOMDocumentImpl::getNodeName() const {
  224.     static const XMLCh nam[] =  // "#document"
  225.         {chPound, chLatin_d, chLatin_o, chLatin_c, chLatin_u, chLatin_m, chLatin_e, chLatin_n, chLatin_t, 0};
  226.     return nam;
  227. }
  228. short DOMDocumentImpl::getNodeType() const {
  229.     return DOMNode::DOCUMENT_NODE;
  230. };
  231. // even though ownerDocument refers to this in this implementation
  232. // the DOM Level 2 spec says it must be 0, so make it appear so
  233. DOMDocument * DOMDocumentImpl::getOwnerDocument() const {
  234.     return 0;
  235. }
  236. DOMAttr *DOMDocumentImpl::createAttribute(const XMLCh *nam)
  237. {
  238.     if(!nam || !isXMLName(nam))
  239.         throw DOMException(DOMException::INVALID_CHARACTER_ERR,0);
  240.     return new (this, DOMDocumentImpl::ATTR_OBJECT) DOMAttrImpl(this,nam);
  241. };
  242. DOMCDATASection *DOMDocumentImpl::createCDATASection(const XMLCh *data) {
  243.     return new (this, DOMDocumentImpl::CDATA_SECTION_OBJECT) DOMCDATASectionImpl(this,data);
  244. };
  245. DOMComment *DOMDocumentImpl::createComment(const XMLCh *data)
  246. {
  247.     return new (this, DOMDocumentImpl::COMMENT_OBJECT) DOMCommentImpl(this, data);
  248. };
  249. DOMDocumentFragment *DOMDocumentImpl::createDocumentFragment()
  250. {
  251.     return new (this, DOMDocumentImpl::DOCUMENT_FRAGMENT_OBJECT) DOMDocumentFragmentImpl(this);
  252. };
  253. DOMDocumentType *DOMDocumentImpl::createDocumentType(const XMLCh *nam)
  254. {
  255.     if (!nam || !isXMLName(nam))
  256.         throw DOMException(
  257.         DOMException::INVALID_CHARACTER_ERR, 0);
  258.     return new (this, DOMDocumentImpl::DOCUMENT_TYPE_OBJECT) DOMDocumentTypeImpl(this, nam, false);
  259. };
  260. DOMDocumentType *
  261.     DOMDocumentImpl::createDocumentType(const XMLCh *qualifiedName,
  262.                                      const XMLCh *publicId,
  263.                                      const XMLCh *systemId)
  264. {
  265.     if (!qualifiedName || !isXMLName(qualifiedName))
  266.         throw DOMException(
  267.         DOMException::INVALID_CHARACTER_ERR, 0);
  268.     return new (this, DOMDocumentImpl::DOCUMENT_TYPE_OBJECT) DOMDocumentTypeImpl(this, qualifiedName, publicId, systemId, false);
  269. };
  270. DOMElement *DOMDocumentImpl::createElement(const XMLCh *tagName)
  271. {
  272.     if(!tagName || !isXMLName(tagName))
  273.         throw DOMException(DOMException::INVALID_CHARACTER_ERR,0);
  274.     return new (this, DOMDocumentImpl::ELEMENT_OBJECT) DOMElementImpl(this,tagName);
  275. };
  276. DOMElement *DOMDocumentImpl::createElementNoCheck(const XMLCh *tagName)
  277. {
  278.     return new (this, DOMDocumentImpl::ELEMENT_OBJECT) DOMElementImpl(this, tagName);
  279. };
  280. DOMEntity *DOMDocumentImpl::createEntity(const XMLCh *nam)
  281. {
  282.     if (!nam || !isXMLName(nam))
  283.         throw DOMException(
  284.         DOMException::INVALID_CHARACTER_ERR, 0);
  285.     return new (this, DOMDocumentImpl::ENTITY_OBJECT) DOMEntityImpl(this, nam);
  286. };
  287. DOMEntityReference *DOMDocumentImpl::createEntityReference(const XMLCh *nam)
  288. {
  289.     if (!nam || !isXMLName(nam))
  290.         throw DOMException(
  291.         DOMException::INVALID_CHARACTER_ERR, 0);
  292.     return new (this, DOMDocumentImpl::ENTITY_REFERENCE_OBJECT) DOMEntityReferenceImpl(this, nam);
  293. };
  294. DOMEntityReference *DOMDocumentImpl::createEntityReferenceByParser(const XMLCh *nam)
  295. {
  296.     if (!nam || !isXMLName(nam))
  297.         throw DOMException(
  298.         DOMException::INVALID_CHARACTER_ERR, 0);
  299.     return new (this, DOMDocumentImpl::ENTITY_REFERENCE_OBJECT) DOMEntityReferenceImpl(this, nam, false);
  300. };
  301. DOMNotation *DOMDocumentImpl::createNotation(const XMLCh *nam)
  302. {
  303.     if (!nam || !isXMLName(nam))
  304.         throw DOMException(
  305.         DOMException::INVALID_CHARACTER_ERR, 0);
  306.     return new (this, DOMDocumentImpl::NOTATION_OBJECT) DOMNotationImpl(this, nam);
  307. };
  308. DOMProcessingInstruction *DOMDocumentImpl::createProcessingInstruction(
  309.                                           const XMLCh *target, const XMLCh *data)
  310. {
  311.     if(!target || !isXMLName(target))
  312.         throw DOMException(DOMException::INVALID_CHARACTER_ERR,0);
  313.     return new (this, DOMDocumentImpl::PROCESSING_INSTRUCTION_OBJECT) DOMProcessingInstructionImpl(this,target,data);
  314. };
  315. DOMText *DOMDocumentImpl::createTextNode(const XMLCh *data)
  316. {
  317.     return new (this, DOMDocumentImpl::TEXT_OBJECT) DOMTextImpl(this,data);
  318. };
  319. DOMNodeIterator* DOMDocumentImpl::createNodeIterator (
  320.           DOMNode *root, unsigned long whatToShow, DOMNodeFilter* filter, bool entityReferenceExpansion)
  321. {
  322.     if (!root) {
  323.         throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0);
  324.         return 0;
  325.     }
  326.     DOMNodeIteratorImpl* nodeIterator = new (this) DOMNodeIteratorImpl(this, root, whatToShow, filter, entityReferenceExpansion);
  327.     if (fNodeIterators == 0L) {
  328.         //fNodeIterators = new (this) NodeIterators(1, false);
  329.         fNodeIterators = new (fMemoryManager) NodeIterators(1, false, fMemoryManager);
  330.     }
  331.     fNodeIterators->addElement(nodeIterator);
  332.     return nodeIterator;
  333. }
  334. NodeIterators* DOMDocumentImpl::getNodeIterators() const
  335. {
  336.     return fNodeIterators;
  337. }
  338. void DOMDocumentImpl::removeNodeIterator(DOMNodeIteratorImpl* nodeIterator)
  339. {
  340.     if (fNodeIterators != 0) {
  341.         XMLSize_t sz = fNodeIterators->size();
  342.         if (sz !=0) {
  343.             for (XMLSize_t i =0; i<sz; i++) {
  344.                 if (fNodeIterators->elementAt(i) == nodeIterator) {
  345.                     fNodeIterators->removeElementAt(i);
  346.                     break;
  347.                 }
  348.             }
  349.         }
  350.     }
  351. }
  352. DOMTreeWalker* DOMDocumentImpl::createTreeWalker (DOMNode *root, unsigned long whatToShow, DOMNodeFilter* filter, bool entityReferenceExpansion)
  353. {
  354.     if (!root) {
  355.         throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0);
  356.         return 0;
  357.     }
  358.     return new (this) DOMTreeWalkerImpl(root, whatToShow, filter, entityReferenceExpansion);
  359. }
  360. DOMDocumentType *DOMDocumentImpl::getDoctype() const
  361. {
  362.     return fDocType;
  363. };
  364. DOMElement *DOMDocumentImpl::getDocumentElement() const
  365. {
  366.     return fDocElement;
  367. };
  368. DOMNodeList *DOMDocumentImpl::getElementsByTagName(const XMLCh *tagname) const
  369. {
  370.     // cast off the const of this because we will update the fNodeListPool
  371.     return ((DOMDocumentImpl*)this)->getDeepNodeList(this,tagname);
  372. };
  373. DOMImplementation   *DOMDocumentImpl::getImplementation() const {
  374.     return DOMImplementation::getImplementation();
  375. }
  376. DOMNode *DOMDocumentImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
  377. {
  378.     // Only one such child permitted
  379.     if(
  380.         (newChild->getNodeType() == DOMNode::ELEMENT_NODE  && fDocElement!=0)
  381.         ||
  382.         (newChild->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE  && fDocType!=0)
  383.         )
  384.         throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0);
  385.     // if the newChild is a documenttype node created from domimplementation, set the ownerDoc first
  386.     if ((newChild->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE) && !newChild->getOwnerDocument())
  387.         ((DOMDocumentTypeImpl*)newChild)->setOwnerDocument(this);
  388.     fParent.insertBefore(newChild,refChild);
  389.     // If insert succeeded, cache the kid appropriately
  390.     if(newChild->getNodeType() == DOMNode::ELEMENT_NODE)
  391.         fDocElement=(DOMElement *)newChild;
  392.     else if(newChild->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE)
  393.         fDocType=(DOMDocumentType *)newChild;
  394.     return newChild;
  395. };
  396. DOMNode* DOMDocumentImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild) {
  397.     DOMDocumentType* tempDocType = fDocType;
  398.     DOMElement* tempDocElement = fDocElement;
  399.     if(oldChild->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE)
  400.         fDocType=0;
  401.     else if(oldChild->getNodeType() == DOMNode::ELEMENT_NODE)
  402.         fDocElement=0;
  403.     try {
  404.         insertBefore(newChild, oldChild);
  405.         // changed() already done.
  406.         if((oldChild->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE)
  407.         || (oldChild->getNodeType() == DOMNode::ELEMENT_NODE))
  408.             return fParent.removeChild(oldChild);
  409.         else
  410.             return removeChild(oldChild);
  411.     }
  412.     catch(...) {
  413.         fDocType = tempDocType;
  414.         fDocElement = tempDocElement;
  415.         throw;
  416.     }
  417. }
  418. bool DOMDocumentImpl::isXMLName(const XMLCh *s)
  419. {
  420.     if (XMLString::equals(fVersion, XMLUni::fgVersion1_1))
  421.         return XMLChar1_1::isValidName(s, XMLString::stringLen(s));
  422.     else
  423.         return XMLChar1_0::isValidName(s, XMLString::stringLen(s));
  424. };
  425. DOMNode *DOMDocumentImpl::removeChild(DOMNode *oldChild)
  426. {
  427.     fParent.removeChild(oldChild);
  428.     // If remove succeeded, un-cache the kid appropriately
  429.     if(oldChild->getNodeType() == DOMNode::ELEMENT_NODE)
  430.         fDocElement=0;
  431.     else if(oldChild->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE)
  432.         fDocType=0;
  433.     return oldChild;
  434. };
  435. void DOMDocumentImpl::setNodeValue(const XMLCh *x)
  436. {
  437.     fNode.setNodeValue(x);
  438. };
  439. //Introduced in DOM Level 2
  440. DOMNode *DOMDocumentImpl::importNode(DOMNode *source, bool deep)
  441. {
  442.     return importNode(source, deep, false);
  443. }
  444. DOMElement *DOMDocumentImpl::createElementNS(const XMLCh *fNamespaceURI,
  445.     const XMLCh *qualifiedName)
  446. {
  447.     if(!qualifiedName || !isXMLName(qualifiedName))
  448.         throw DOMException(DOMException::INVALID_CHARACTER_ERR,0);
  449.     //XMLCh * pooledTagName = this->fNamePool->getPooledString(qualifiedName);
  450.     return new (this, DOMDocumentImpl::ELEMENT_NS_OBJECT) DOMElementNSImpl(this, fNamespaceURI, qualifiedName);
  451. }
  452. DOMElement *DOMDocumentImpl::createElementNS(const XMLCh *fNamespaceURI,
  453.                                               const XMLCh *qualifiedName,
  454.                                               const XMLSSize_t lineNo,
  455.                                               const XMLSSize_t columnNo)
  456. {
  457.     if(!qualifiedName || !isXMLName(qualifiedName))
  458.         throw DOMException(DOMException::INVALID_CHARACTER_ERR,0);
  459.     return new (this) XSDElementNSImpl(this, fNamespaceURI, qualifiedName, lineNo, columnNo);
  460. }
  461. DOMAttr *DOMDocumentImpl::createAttributeNS(const XMLCh *fNamespaceURI,
  462.     const XMLCh *qualifiedName)
  463. {
  464.     if(!qualifiedName || !isXMLName(qualifiedName))
  465.         throw DOMException(DOMException::INVALID_CHARACTER_ERR,0);
  466.     return new (this, DOMDocumentImpl::ATTR_NS_OBJECT) DOMAttrNSImpl(this, fNamespaceURI, qualifiedName);
  467. }
  468. DOMNodeList *DOMDocumentImpl::getElementsByTagNameNS(const XMLCh *fNamespaceURI,
  469.     const XMLCh *fLocalName)  const
  470. {
  471.     // cast off the const of this because we will update the fNodeListPool
  472.     return ((DOMDocumentImpl*)this)->getDeepNodeList(this, fNamespaceURI, fLocalName);
  473. }
  474. DOMElement *DOMDocumentImpl::getElementById(const XMLCh *elementId) const
  475. {
  476.     if (fNodeIDMap == 0)
  477.         return 0;
  478.     DOMAttr *theAttr = fNodeIDMap->find(elementId);
  479.     if (theAttr == 0)
  480.         return 0;
  481.     return theAttr->getOwnerElement();
  482. }
  483. //Return the index > 0 of ':' in the given qualified name qName="prefix:localName".
  484. //Return 0 if there is no ':', or -1 if qName is malformed such as ":abcd" or "abcd:".
  485. int DOMDocumentImpl::indexofQualifiedName(const XMLCh * qName)
  486. {
  487.     int qNameLen = XMLString::stringLen(qName);
  488.     int index = -1, count = 0;
  489.     for (int i = 0; i < qNameLen; ++i) {
  490.         if (qName[i] == chColon) {
  491.             index = i;
  492.             ++count;    //number of ':' found
  493.         }
  494.     }
  495.     if (qNameLen == 0 || count > 1 || index == 0 || index == qNameLen-1)
  496.         return -1;
  497.     return count == 0 ? 0 : index;
  498. }
  499. const XMLCh*     DOMDocumentImpl::getBaseURI() const
  500. {
  501.   return fDocumentURI;
  502. };
  503. DOMRange* DOMDocumentImpl::createRange()
  504. {
  505.     DOMRangeImpl* range = new (this) DOMRangeImpl(this);
  506.     if (fRanges == 0L) {
  507.         //fRanges = new (this) Ranges(1, false);
  508.         fRanges = new (fMemoryManager) Ranges(1, false, fMemoryManager); // XMemory
  509.     }
  510.     fRanges->addElement(range);
  511.     return range;
  512. }
  513. Ranges* DOMDocumentImpl::getRanges() const
  514. {
  515.     return fRanges;
  516. }
  517. void DOMDocumentImpl::removeRange(DOMRangeImpl* range)
  518. {
  519.     if (fRanges != 0) {
  520.         XMLSize_t sz = fRanges->size();
  521.         if (sz !=0) {
  522.             for (XMLSize_t i =0; i<sz; i++) {
  523.                 if (fRanges->elementAt(i) == range) {
  524.                     fRanges->removeElementAt(i);
  525.                     break;
  526.                 }
  527.             }
  528.         }
  529.     }
  530. }
  531. /** Uses the kidOK lookup table to check whether the proposed
  532.     tree structure is legal.
  533.     ????? It feels like there must be a more efficient solution,
  534.     but for the life of me I can't think what it would be.
  535. */
  536. bool DOMDocumentImpl::isKidOK(DOMNode *parent, DOMNode *child)
  537. {
  538.       static int kidOK[14];
  539.       if (kidOK[DOMNode::ATTRIBUTE_NODE] == 0)
  540.       {
  541.           kidOK[DOMNode::DOCUMENT_NODE] =
  542.               1 << DOMNode::ELEMENT_NODE |
  543.               1 << DOMNode::PROCESSING_INSTRUCTION_NODE |
  544.               1 << DOMNode::COMMENT_NODE |
  545.               1 << DOMNode::DOCUMENT_TYPE_NODE;
  546.           kidOK[DOMNode::DOCUMENT_FRAGMENT_NODE] =
  547.               kidOK[DOMNode::ENTITY_NODE] =
  548.               kidOK[DOMNode::ENTITY_REFERENCE_NODE] =
  549.               kidOK[DOMNode::ELEMENT_NODE] =
  550.               1 << DOMNode::ELEMENT_NODE |
  551.               1 << DOMNode::PROCESSING_INSTRUCTION_NODE |
  552.               1 << DOMNode::COMMENT_NODE |
  553.               1 << DOMNode::TEXT_NODE |
  554.               1 << DOMNode::CDATA_SECTION_NODE |
  555.               1 << DOMNode::ENTITY_REFERENCE_NODE;
  556.           kidOK[DOMNode::ATTRIBUTE_NODE] =
  557.               1 << DOMNode::TEXT_NODE |
  558.               1 << DOMNode::ENTITY_REFERENCE_NODE;
  559.           kidOK[DOMNode::PROCESSING_INSTRUCTION_NODE] =
  560.               kidOK[DOMNode::COMMENT_NODE] =
  561.               kidOK[DOMNode::TEXT_NODE] =
  562.               kidOK[DOMNode::CDATA_SECTION_NODE] =
  563.               kidOK[DOMNode::NOTATION_NODE] =
  564.               0;
  565.       };
  566.       int p=parent->getNodeType();
  567.       int ch = child->getNodeType();
  568.       return (kidOK[p] & 1<<ch) != 0;
  569. }
  570. void            DOMDocumentImpl::changed()
  571. {
  572.     fChanges++;
  573. }
  574. int             DOMDocumentImpl::changes() const{
  575.     return fChanges;
  576. };
  577. //
  578. //    Delegation for functions inherited from DOMNode
  579. //
  580.            DOMNode*         DOMDocumentImpl::appendChild(DOMNode *newChild)          {return insertBefore(newChild, 0); };
  581.            DOMNamedNodeMap* DOMDocumentImpl::getAttributes() const                   {return fNode.getAttributes (); };
  582.            DOMNodeList*     DOMDocumentImpl::getChildNodes() const                   {return fParent.getChildNodes (); };
  583.            DOMNode*         DOMDocumentImpl::getFirstChild() const                   {return fParent.getFirstChild (); };
  584.            DOMNode*         DOMDocumentImpl::getLastChild() const                    {return fParent.getLastChild (); };
  585.      const XMLCh*           DOMDocumentImpl::getLocalName() const                    {return fNode.getLocalName (); };
  586.      const XMLCh*           DOMDocumentImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); };
  587.            DOMNode*         DOMDocumentImpl::getNextSibling() const                  {return fNode.getNextSibling (); };
  588.      const XMLCh*           DOMDocumentImpl::getNodeValue() const                    {return fNode.getNodeValue (); };
  589.      const XMLCh*           DOMDocumentImpl::getPrefix() const                       {return fNode.getPrefix (); };
  590.            DOMNode*         DOMDocumentImpl::getParentNode() const                   {return fNode.getParentNode (); };
  591.            DOMNode*         DOMDocumentImpl::getPreviousSibling() const              {return fNode.getPreviousSibling (); };
  592.            bool             DOMDocumentImpl::hasChildNodes() const                   {return fParent.hasChildNodes (); };
  593.            void             DOMDocumentImpl::normalize()                             {fParent.normalize (); };
  594.            bool             DOMDocumentImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
  595.                                                                                      {return fNode.isSupported (feature, version); };
  596.            void             DOMDocumentImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); };
  597.            bool             DOMDocumentImpl::hasAttributes() const                   {return fNode.hasAttributes(); };
  598.            bool             DOMDocumentImpl::isSameNode(const DOMNode* other) const  {return fNode.isSameNode(other);};
  599.            bool             DOMDocumentImpl::isEqualNode(const DOMNode* arg) const   {return fParent.isEqualNode(arg);};
  600.            void*            DOMDocumentImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler)
  601.                                                                                      {return fNode.setUserData(key, data, handler); };
  602.            void*            DOMDocumentImpl::getUserData(const XMLCh* key) const     {return fNode.getUserData(key); };
  603.            short            DOMDocumentImpl::compareTreePosition(const DOMNode* other) const {return fNode.compareTreePosition(other); };
  604.            const XMLCh*     DOMDocumentImpl::getTextContent() const                  {return fNode.getTextContent(); };
  605.            void             DOMDocumentImpl::setTextContent(const XMLCh* textContent){fNode.setTextContent(textContent); };
  606.            const XMLCh*     DOMDocumentImpl::lookupNamespacePrefix(const XMLCh* namespaceURI, bool useDefault) const  {return fNode.lookupNamespacePrefix(namespaceURI, useDefault); };
  607.            bool             DOMDocumentImpl::isDefaultNamespace(const XMLCh* namespaceURI) const {return fNode.isDefaultNamespace(namespaceURI); };
  608.            const XMLCh*     DOMDocumentImpl::lookupNamespaceURI(const XMLCh* prefix) const  {return fNode.lookupNamespaceURI(prefix); };
  609.            DOMNode*         DOMDocumentImpl::getInterface(const XMLCh* feature)      {return fNode.getInterface(feature); };
  610. //-----------------------------------------------------------------------
  611. //
  612. //  Per Document Heap and Heap Helper functions
  613. //
  614. //        revisit - this stuff should be a class of its own, rather than
  615. //                       just lying around naked in DocumentImpl.
  616. //
  617. //-----------------------------------------------------------------------
  618. XMLCh * DOMDocumentImpl::cloneString(const XMLCh *src)
  619. {
  620.     if (!src) return 0;
  621.     size_t   len = XMLString::stringLen(src);
  622.     len = (len + 1) * sizeof(XMLCh);
  623.     len = (len % 4) + len;
  624.     XMLCh *newStr = (XMLCh *)this->allocate(len);
  625.     XMLString::copyString(newStr, src);
  626.     return newStr;
  627. }
  628. const XMLCh *  DOMDocumentImpl::getPooledString(const XMLCh *src)
  629. {
  630.     if (!src) return 0;
  631.     else return this->fNamePool->getPooledString(src);
  632. }
  633. static const int kHeapAllocSize = 0x10000;    // The chunk size to allocate from the
  634.                                               //   system allocator.
  635. static const int kMaxSubAllocationSize = 4096;   // Any request for more bytes
  636.                                                  //  than this will be handled by
  637.                                                  //  allocating directly with system.
  638. void *         DOMDocumentImpl::allocate(size_t amount)
  639. {
  640. // Align the request size so that suballocated blocks
  641. // beyond this one will be maintained at the same alignment.
  642. amount = XMLPlatformUtils::alignPointerForNewBlockAllocation(amount);
  643.     // If the request is for a largish block, hand it off to the system
  644.     //   allocator.  The block still must be linked into the list of
  645.     //   allocated blocks so that it will be deleted when the time comes.
  646.     if (amount > kMaxSubAllocationSize)
  647.     {
  648. // The size of the header we add to our raw blocks
  649. size_t sizeOfHeader = XMLPlatformUtils::alignPointerForNewBlockAllocation(sizeof(void *));
  650. // Try to allocate the block
  651.         void* newBlock = 0;
  652.         try {
  653.             newBlock = fMemoryManager->allocate((sizeOfHeader + amount) * sizeof(char)); //new char[amount + sizeOfHeader];
  654.         }
  655.         catch (...) {
  656.             ThrowXML(RuntimeException, XMLExcepts::Out_Of_Memory);
  657.         }
  658.         if (!newBlock)
  659.            ThrowXML(RuntimeException, XMLExcepts::Out_Of_Memory);
  660. // Link it into the list beyond current block, as current block
  661. // is still being subdivided. If there is no current block
  662. // then track that we have no bytes to further divide.
  663.         if (fCurrentBlock)
  664.         {
  665.             *(void **)newBlock = *(void **)fCurrentBlock;
  666.             *(void **)fCurrentBlock = newBlock;
  667.         }
  668.         else
  669.         {
  670.             fCurrentBlock = newBlock;
  671.             fFreePtr = 0;
  672.             fFreeBytesRemaining = 0;
  673.         }
  674.         void *retPtr = (char *)newBlock + sizeOfHeader;
  675.         return retPtr;
  676.     }
  677.     // It's a normal (sub-allocatable) request.
  678. // Are we out of room in our current block?
  679. if (amount > fFreeBytesRemaining)
  680.     {
  681.         // Request doesn't fit in the current block.
  682. // The size of the header we add to our raw blocks
  683. size_t sizeOfHeader = XMLPlatformUtils::alignPointerForNewBlockAllocation(sizeof(void *));
  684.         // Get a new block from the system allocator.
  685.         void* newBlock = 0;
  686.         try {
  687.             newBlock = fMemoryManager->allocate(kHeapAllocSize * sizeof(char)); //new char[kHeapAllocSize];
  688.         }
  689.         catch (...) {
  690.             ThrowXML(RuntimeException, XMLExcepts::Out_Of_Memory);
  691.         }
  692.         if (!newBlock)
  693.            ThrowXML(RuntimeException, XMLExcepts::Out_Of_Memory);
  694.         *(void **)newBlock = fCurrentBlock;
  695.         fCurrentBlock = newBlock;
  696.         fFreePtr = (char *)newBlock + sizeOfHeader;
  697.         fFreeBytesRemaining = kHeapAllocSize - sizeOfHeader;
  698.     }
  699. // Subdivide the request off current block
  700.     void *retPtr = fFreePtr;
  701.     fFreePtr += amount;
  702.     fFreeBytesRemaining -= amount;
  703.     return retPtr;
  704. }
  705. void    DOMDocumentImpl::deleteHeap()
  706. {
  707.     while (fCurrentBlock != 0)
  708.     {
  709.         void *nextBlock = *(void **)fCurrentBlock;
  710.         fMemoryManager->deallocate(fCurrentBlock); //delete [] (char*) fCurrentBlock;
  711.         fCurrentBlock = nextBlock;
  712.     }
  713. }
  714. DOMNodeList *DOMDocumentImpl::getDeepNodeList(const DOMNode *rootNode, const XMLCh *tagName)
  715. {
  716.     if(!fNodeListPool) {
  717.         fNodeListPool = new (this) DOMDeepNodeListPool<DOMDeepNodeListImpl>(109, false);
  718.     }
  719.     DOMDeepNodeListImpl* retList = fNodeListPool->getByKey(rootNode, tagName, 0);
  720.     if (!retList) {
  721.         int id = fNodeListPool->put((void*) rootNode, (XMLCh*) tagName, 0, new (this) DOMDeepNodeListImpl(rootNode, tagName));
  722.         retList = fNodeListPool->getById(id);
  723.     }
  724.     return retList;
  725. }
  726. DOMNodeList *DOMDocumentImpl::getDeepNodeList(const DOMNode *rootNode,     //DOM Level 2
  727.                                                    const XMLCh *namespaceURI,
  728.                                                    const XMLCh *localName)
  729. {
  730.     if(!fNodeListPool) {
  731.         fNodeListPool = new (this) DOMDeepNodeListPool<DOMDeepNodeListImpl>(109, false);
  732.     }
  733.     DOMDeepNodeListImpl* retList = fNodeListPool->getByKey(rootNode, localName, namespaceURI);
  734.     if (!retList) {
  735.         // the pool will adopt the DOMDeepNodeListImpl
  736.         int id = fNodeListPool->put((void*) rootNode, (XMLCh*) localName, (XMLCh*) namespaceURI, new (this) DOMDeepNodeListImpl(rootNode, namespaceURI, localName));
  737.         retList = fNodeListPool->getById(id);
  738.     }
  739.     return retList;
  740. }
  741. //Introduced in DOM Level 3
  742. const XMLCh* DOMDocumentImpl::getActualEncoding() const {
  743.     return fActualEncoding;
  744. }
  745. void DOMDocumentImpl::setActualEncoding(const XMLCh* actualEncoding){
  746.     fActualEncoding = cloneString(actualEncoding);
  747. }
  748. const XMLCh* DOMDocumentImpl::getEncoding() const {
  749.     return fEncoding;
  750. }
  751. void DOMDocumentImpl::setEncoding(const XMLCh* encoding){
  752.     fEncoding = cloneString(encoding);
  753. }
  754. bool DOMDocumentImpl::getStandalone() const{
  755.     return fStandalone;
  756. }
  757. void DOMDocumentImpl::setStandalone(bool standalone){
  758.     fStandalone = standalone;
  759. }
  760. const XMLCh* DOMDocumentImpl::getVersion() const {
  761.     return fVersion;
  762. }
  763. void DOMDocumentImpl::setVersion(const XMLCh* version){
  764.     if ((version && *version) &&
  765.         !XMLString::equals(version, XMLUni::fgVersion1_0) &&
  766.         !XMLString::equals(version, XMLUni::fgVersion1_1))
  767.         throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0);
  768.     fVersion = cloneString(version);
  769. }
  770. const XMLCh* DOMDocumentImpl::getDocumentURI() const
  771. {
  772.     return fDocumentURI;
  773. }
  774. void DOMDocumentImpl::setDocumentURI(const XMLCh* documentURI){
  775.     if (documentURI && *documentURI) {
  776.         XMLCh* temp = (XMLCh*) this->allocate((XMLString::stringLen(documentURI) + 9)*sizeof(XMLCh));
  777.         XMLString::fixURI(documentURI, temp);
  778.         fDocumentURI = temp;
  779.     }
  780.     else
  781.         fDocumentURI = 0;
  782. }
  783. bool DOMDocumentImpl::getStrictErrorChecking() const {
  784.     return getErrorChecking();
  785. }
  786. void DOMDocumentImpl::setStrictErrorChecking(bool strictErrorChecking) {
  787.     setErrorChecking(strictErrorChecking);
  788. }
  789. DOMNode* DOMDocumentImpl::adoptNode(DOMNode* source) {
  790.     throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0);
  791.     return 0;
  792. }
  793. void DOMDocumentImpl::normalizeDocument() {
  794.     if(!fNormalizer) 
  795.         fNormalizer = new (fMemoryManager) DOMNormalizer(fMemoryManager);
  796.     fNormalizer->normalizeDocument(this);
  797. }
  798. DOMConfiguration* DOMDocumentImpl::getDOMConfiguration() const {
  799.     if(!fDOMConfiguration)
  800.         ((DOMDocumentImpl*)this)->fDOMConfiguration = new ((DOMDocumentImpl*)this) DOMConfigurationImpl();
  801.     return fDOMConfiguration;
  802. }
  803. void DOMDocumentImpl::setDOMConfiguration(DOMConfiguration *config) {
  804.     fDOMConfiguration = config;
  805. }
  806. DOMNode *DOMDocumentImpl::importNode(DOMNode *source, bool deep, bool cloningDoc)
  807. {
  808.     DOMNode *newnode=0;
  809.     bool oldErrorCheckingFlag = errorChecking;
  810.     switch (source->getNodeType())
  811.     {
  812.     case DOMNode::ELEMENT_NODE :
  813.         {
  814.             DOMElement *newelement;
  815.             if (source->getLocalName() == 0)
  816.                 newelement = createElement(source->getNodeName());
  817.             else
  818.                 newelement = createElementNS(source->getNamespaceURI(),
  819.             source->getNodeName());
  820.             DOMNamedNodeMap *srcattr=source->getAttributes();
  821.             if(srcattr!=0)
  822.                 for(XMLSize_t i=0;i<srcattr->getLength();++i)
  823.                 {
  824.                     DOMAttr *attr = (DOMAttr *) srcattr->item(i);
  825.                     if (attr -> getSpecified()) { // not a default attribute
  826.                         DOMAttr *nattr = (DOMAttr *) importNode(attr, true, false);
  827.                         if (attr -> getLocalName() == 0)
  828.                             newelement->setAttributeNode(nattr);
  829.                         else
  830.                             newelement->setAttributeNodeNS(nattr);
  831.                         // if the imported attribute is of ID type, register the new node in fNodeIDMap
  832.                         if (castToNodeImpl(attr)->isIdAttr()) {
  833.                             castToNodeImpl(nattr)->isIdAttr(true);
  834.                             if (!fNodeIDMap)
  835.                                  fNodeIDMap = new (this) DOMNodeIDMap(500, this);
  836.                             fNodeIDMap->add((DOMAttr*)nattr);
  837.                         }
  838.                     }
  839.                 }
  840.             newnode=newelement;
  841.         }
  842.         break;
  843.     case DOMNode::ATTRIBUTE_NODE :
  844.         if (source->getLocalName() == 0)
  845.             newnode = createAttribute(source->getNodeName());
  846.         else
  847.             newnode = createAttributeNS(source->getNamespaceURI(),
  848.             source->getNodeName());
  849.         deep = true;
  850.         // Kids carry value
  851.         break;
  852.     case DOMNode::TEXT_NODE :
  853.         newnode = createTextNode(source->getNodeValue());
  854.         break;
  855.     case DOMNode::CDATA_SECTION_NODE :
  856.         newnode = createCDATASection(source->getNodeValue());
  857.         break;
  858.     case DOMNode::ENTITY_REFERENCE_NODE :
  859.         {
  860.             DOMEntityReferenceImpl* newentityRef = (DOMEntityReferenceImpl*)createEntityReference(source->getNodeName());
  861.             newnode=newentityRef;
  862.             errorChecking = false;
  863.             newentityRef->setReadOnly(false, true); //allow deep import temporarily
  864.         }
  865.         break;
  866.     case DOMNode::ENTITY_NODE :
  867.         {
  868.             DOMEntity *srcentity=(DOMEntity *)source;
  869.             DOMEntityImpl *newentity = (DOMEntityImpl *)createEntity(source->getNodeName());
  870.             newentity->setPublicId(srcentity->getPublicId());
  871.             newentity->setSystemId(srcentity->getSystemId());
  872.             newentity->setNotationName(srcentity->getNotationName());
  873.             // Kids carry additional value
  874.             newnode=newentity;
  875.             castToNodeImpl(newentity)->setReadOnly(false, true);// allow deep import temporarily
  876.         }
  877.         break;
  878.     case DOMNode::PROCESSING_INSTRUCTION_NODE :
  879.         newnode = createProcessingInstruction(source->getNodeName(),
  880.             source->getNodeValue());
  881.         break;
  882.     case DOMNode::COMMENT_NODE :
  883.         newnode = createComment(source->getNodeValue());
  884.         break;
  885.     case DOMNode::DOCUMENT_TYPE_NODE :
  886.         {
  887.             // unless this is used as part of cloning a Document
  888.             // forbid it for the sake of being compliant to the DOM spec
  889.             if (!cloningDoc)
  890.                 throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0);
  891.             DOMDocumentType *srcdoctype = (DOMDocumentType *)source;
  892.             DOMDocumentType *newdoctype = (DOMDocumentType *)
  893.                 createDocumentType(srcdoctype->getNodeName(),
  894.                 srcdoctype->getPublicId(),
  895.                 srcdoctype->getSystemId());
  896.             // Values are on NamedNodeMaps
  897.             DOMNamedNodeMap *smap = srcdoctype->getEntities();
  898.             DOMNamedNodeMap *tmap = newdoctype->getEntities();
  899.             if(smap != 0) {
  900.                 for(XMLSize_t i = 0; i < smap->getLength(); i++) {
  901.                     tmap->setNamedItem(importNode(smap->item(i), true, false));
  902.                 }
  903.             }
  904.             smap = srcdoctype->getNotations();
  905.             tmap = newdoctype->getNotations();
  906.             if (smap != 0) {
  907.                 for(XMLSize_t i = 0; i < smap->getLength(); i++) {
  908.                     tmap->setNamedItem(importNode(smap->item(i), true, false));
  909.                 }
  910.             }
  911.             // NOTE: At this time, the DOM definition of DocumentType
  912.             // doesn't cover Elements and their Attributes. domimpl's
  913.             // extentions in that area will not be preserved, even if
  914.             // copying from domimpl to domimpl. We could special-case
  915.             // that here. Arguably we should. Consider. ?????
  916.             newnode = newdoctype;
  917.         }
  918.         break;
  919.     case DOMNode::DOCUMENT_FRAGMENT_NODE :
  920.         newnode = createDocumentFragment();
  921.         // No name, kids carry value
  922.         break;
  923.     case DOMNode::NOTATION_NODE :
  924.         {
  925.             DOMNotation *srcnotation=(DOMNotation *)source;
  926.             DOMNotationImpl *newnotation = (DOMNotationImpl *)createNotation(source->getNodeName());
  927.             newnotation->setPublicId(srcnotation->getPublicId());
  928.             newnotation->setSystemId(srcnotation->getSystemId());
  929.             // Kids carry additional value
  930.             newnode=newnotation;
  931.             // No name, no value
  932.             break;
  933.         }
  934.     case DOMNode::DOCUMENT_NODE : // Document can't be child of Document
  935.     default:                       // Unknown node type
  936.         throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0);
  937.     }
  938.     // If deep, replicate and attach the kids.
  939.     if (deep)
  940.         for (DOMNode *srckid = source->getFirstChild();
  941.              srckid != 0;
  942.              srckid = srckid->getNextSibling())
  943.         {
  944.             newnode->appendChild(importNode(srckid, true, false));
  945.         }
  946.     if (newnode->getNodeType() == DOMNode::ENTITY_REFERENCE_NODE
  947.         || newnode->getNodeType() == DOMNode::ENTITY_NODE) {
  948.         castToNodeImpl(newnode)->setReadOnly(true, true);
  949.         errorChecking = oldErrorCheckingFlag;
  950.     }
  951.     if (!cloningDoc)
  952.         fNode.callUserDataHandlers(DOMUserDataHandler::NODE_IMPORTED, source, newnode);
  953.     return newnode;
  954. }
  955. // user data utility
  956. void* DOMDocumentImpl::setUserData(DOMNodeImpl* n, const XMLCh* key, void* data, DOMUserDataHandler* handler)
  957. {
  958.     void* oldData = 0;
  959.     DOMNodeUserDataTable* node_userDataTable = 0;
  960.     if (!fUserDataTable) {
  961.         // create the table on heap so that it can be cleaned in destructor
  962.         //fUserDataTable = new (this) RefHashTableOf<DOMNodeUserDataTable>(29, true, new HashPtr());
  963.         fUserDataTable = new (fMemoryManager) RefHashTableOf<DOMNodeUserDataTable>
  964.         (
  965.             29
  966.             , true
  967.             , new (fMemoryManager) HashPtr()
  968.             , fMemoryManager
  969.         );
  970.     }
  971.     else {
  972.         node_userDataTable = fUserDataTable->get((void*)n);
  973.         DOMUserDataRecord* oldDataRecord = 0;
  974.         if (node_userDataTable) {
  975.             oldDataRecord = node_userDataTable->get((void*)key);
  976.             if (oldDataRecord) {
  977.                 oldData = oldDataRecord->getKey();
  978.                 node_userDataTable->removeKey((void*)key);
  979.             }
  980.         }
  981.     }
  982.     if (data) {
  983.         // create the DOMNodeUserDataTable if not exists
  984.         // create on the heap and adopted by the hashtable which will delete it upon removal.
  985.         if (!node_userDataTable) {
  986.             node_userDataTable  = new (fMemoryManager) RefHashTableOf<DOMUserDataRecord>(29, true, fMemoryManager);
  987.             fUserDataTable->put(n, node_userDataTable);
  988.         }
  989.         // clone the key first, and create the DOMUserDataRecord
  990.         // create on the heap and adopted by the hashtable which will delete it upon removal.
  991.         node_userDataTable->put((void*)getPooledString(key), new (fMemoryManager) DOMUserDataRecord(data, handler));
  992.     }
  993.     else {
  994.         if (node_userDataTable->isEmpty())
  995.             n->hasUserData(false);
  996.     }
  997.     return oldData;
  998. }
  999. void* DOMDocumentImpl::getUserData(const DOMNodeImpl* n, const XMLCh* key) const
  1000. {
  1001.     if (fUserDataTable) {
  1002.         DOMNodeUserDataTable*  node_userDataTable = fUserDataTable->get((void*)n);
  1003.         if (node_userDataTable) {
  1004.             DOMUserDataRecord* dataRecord = node_userDataTable->get((void*)key);
  1005.             if (dataRecord)
  1006.                 return dataRecord->getKey();
  1007.         }
  1008.     }
  1009.     return 0;
  1010. }
  1011. void DOMDocumentImpl::callUserDataHandlers(const DOMNodeImpl* n, DOMUserDataHandler::DOMOperationType operation, const DOMNode* src, const DOMNode* dst) const
  1012. {
  1013.     if (fUserDataTable) {
  1014.         DOMNodeUserDataTable*  node_userDataTable = fUserDataTable->get((void*)n);
  1015.         if (node_userDataTable) {
  1016.             RefHashTableOfEnumerator<DOMUserDataRecord> userDataEnum(node_userDataTable);
  1017.             // walk through the entire node_userDataTable table
  1018.             while (userDataEnum.hasMoreElements()) {
  1019.                 // get the key
  1020.                 XMLCh* key = (XMLCh*) userDataEnum.nextElementKey();
  1021.                 // get the DOMUserDataRecord
  1022.                 DOMUserDataRecord* userDataRecord = node_userDataTable->get((void*)key);
  1023.                 // get the handler
  1024.                 DOMUserDataHandler* handler = userDataRecord->getValue();
  1025.                 if (handler) {
  1026.                     // get the data
  1027.                     void* data = userDataRecord->getKey();
  1028.                     handler->handle(operation, key, data, src, dst);
  1029.                 }
  1030.                 // if the operation is deleted, we in fact should remove the data from the table
  1031.                 if (operation == DOMUserDataHandler::NODE_DELETED)
  1032.                     node_userDataTable->removeKey((void*)key);
  1033.             }
  1034.         }
  1035.     }
  1036. }
  1037. void DOMDocumentImpl::transferUserData(DOMNodeImpl* n1, DOMNodeImpl* n2)
  1038. {
  1039.     if (fUserDataTable) {
  1040.         fUserDataTable->transferElement((void*)n1, (void*)n2);
  1041.         n1->hasUserData(false);
  1042.         n2->hasUserData(true);
  1043.     }
  1044. }
  1045. DOMNode* DOMDocumentImpl::renameNode(DOMNode* n, const XMLCh* namespaceURI, const XMLCh* name)
  1046. {
  1047.     if (n->getOwnerDocument() != this)
  1048.         if (n->getNodeType() == DOCUMENT_NODE)
  1049.             throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0);
  1050.         else
  1051.             throw DOMException(DOMException::WRONG_DOCUMENT_ERR, 0);
  1052.     switch (n->getNodeType()) {
  1053.         case ELEMENT_NODE:
  1054.             return ((DOMElementImpl*)n)->rename(namespaceURI, name);
  1055.         case ATTRIBUTE_NODE:
  1056.             return ((DOMAttrImpl*)n)->rename(namespaceURI, name);
  1057.         default:
  1058.             throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0);
  1059.     }
  1060.     return 0;
  1061. }
  1062. void DOMDocumentImpl::release()
  1063. {
  1064.     DOMDocument* doc = (DOMDocument*) this;
  1065.     fNode.callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0);
  1066.     // notify userdatahandler first
  1067.     releaseDocNotifyUserData(this);
  1068.     // release the docType in case it was created from heap
  1069.     if (fDocType) {
  1070.         castToNodeImpl(fDocType)->isToBeReleased(true);
  1071.         fDocType->release();
  1072.     }
  1073.     // delete the document memory pool
  1074.     delete doc;
  1075. };
  1076. void DOMDocumentImpl::releaseDocNotifyUserData(DOMNode* object)
  1077. {
  1078.     DOMNode *child = object->getFirstChild();
  1079.     if (child != 0)
  1080.     {
  1081.         while( child != 0)
  1082.         {
  1083.             releaseDocNotifyUserData(child);
  1084.             child = child->getNextSibling();
  1085.         }
  1086.     }
  1087.     else
  1088.         castToNodeImpl(object)->callUserDataHandlers(DOMUserDataHandler::NODE_DELETED, 0, 0);
  1089. }
  1090. void DOMDocumentImpl::release(DOMNode* object, NodeObjectType type)
  1091. {
  1092.     if (!fRecycleNodePtr)
  1093.         fRecycleNodePtr = new (fMemoryManager) RefArrayOf<DOMNodePtr> (15, fMemoryManager);
  1094.     if (!fRecycleNodePtr->operator[](type))
  1095.         fRecycleNodePtr->operator[](type) = new (fMemoryManager) RefStackOf<DOMNode> (15, false, fMemoryManager);
  1096.     fRecycleNodePtr->operator[](type)->push(object);
  1097. }
  1098. void DOMDocumentImpl::releaseBuffer(DOMBuffer* buffer)
  1099. {
  1100.     if (!fRecycleBufferPtr)
  1101.         fRecycleBufferPtr = new (fMemoryManager) RefStackOf<DOMBuffer> (15, false, fMemoryManager);
  1102.     fRecycleBufferPtr->push(buffer);
  1103. }
  1104. DOMBuffer* DOMDocumentImpl::popBuffer()
  1105. {
  1106.     if (!fRecycleBufferPtr || fRecycleBufferPtr->empty())
  1107.         return 0;
  1108.     return fRecycleBufferPtr->pop();
  1109. }
  1110. void * DOMDocumentImpl::allocate(size_t amount, NodeObjectType type)
  1111. {
  1112.     if (!fRecycleNodePtr)
  1113.         return allocate(amount);
  1114.     DOMNodePtr* ptr = fRecycleNodePtr->operator[](type);
  1115.     if (!ptr || ptr->empty())
  1116.         return allocate(amount);
  1117.     return (void*) ptr->pop();
  1118. }
  1119. XERCES_CPP_NAMESPACE_END