IDDocumentImpl.cpp
上传用户:huihehuasu
上传日期:2007-01-10
资源大小:6948k
文件大小:31k
源码类别:

xml/soap/webservice

开发平台:

C/C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 2001 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: IDDocumentImpl.cpp,v 1.13 2001/12/07 01:37:24 tng Exp $
  58.  */
  59. #include <util/XMLUniDefs.hpp>
  60. #include "IDOM_Document.hpp"
  61. #include "IDDocumentImpl.hpp"
  62. #include "IDOM_DocumentType.hpp"
  63. #include "IDOM_DOMException.hpp"
  64. #include "IDOM_DOMImplementation.hpp"
  65. #include "IDOM_NamedNodeMap.hpp"
  66. #include "IDOM_Node.hpp"
  67. #include "IDCasts.hpp"
  68. #include "IDDocumentTypeImpl.hpp"
  69. #include "IDAttrImpl.hpp"
  70. #include "IDAttrNSImpl.hpp"
  71. #include "IDCDATASectionImpl.hpp"
  72. #include "IDCommentImpl.hpp"
  73. #include "IDDeepNodeListImpl.hpp"
  74. #include "IDDocumentFragmentImpl.hpp"
  75. #include "IDElementImpl.hpp"
  76. #include "IDElementNSImpl.hpp"
  77. #include "IDEntityImpl.hpp"
  78. #include "IDEntityReferenceImpl.hpp"
  79. #include "IDNamedNodeMapImpl.hpp"
  80. #include "IDNotationImpl.hpp"
  81. #include "IDProcessingInstructionImpl.hpp"
  82. #include "IDTextImpl.hpp"
  83. #include "IDStringPool.hpp"
  84. #include "IDTreeWalkerImpl.hpp"
  85. #include "IDNodeIteratorImpl.hpp"
  86. #include "IDNodeIDMap.hpp"
  87. #include "IDRangeImpl.hpp"
  88. #include <internal/XMLReader.hpp>
  89. #include <util/HashPtr.hpp>
  90. //idom_revisit.  These can go away once all of the include files above are really there.
  91. class IDOM_TreeWalker;
  92. class IDOM_NodeFilter;
  93. //
  94. //   Constructors.   Warning - be very careful with the ordering of initialization
  95. //                             of the heap.  Ordering depends on the order of declaration
  96. //                             in the .hpp file, not on the order of initializers here
  97. //                             in the constructor.  The heap declaration can not be
  98. //                             first - fNode and fParent must be first for the casting
  99. //                             functions in IDCasts to work correctly.  This means that
  100. //                             fNode and fParent constructors used here can not
  101. //                             allocate.
  102. //
  103. IDDocumentImpl::IDDocumentImpl()
  104.     : fNode(this),
  105.       fParent(this),
  106.       fCurrentBlock(0),
  107.       fFreePtr(0),
  108.       fFreeBytesRemaining(0),
  109.       fDocType(0),
  110.       fDocElement(0),
  111.       fNamePool(0),
  112.       fIterators(0L),
  113.       fTreeWalkers(0L),
  114.       fNodeIDMap(0),
  115.       fUserData(0),
  116.       fRanges(0),
  117.       fChanges(0),
  118.       fNodeListPool(0)
  119. {
  120.     fNamePool    = new (this) IDStringPool(257, this);
  121. };
  122. //DOM Level 2
  123. IDDocumentImpl::IDDocumentImpl(const XMLCh *fNamespaceURI,
  124.                                const XMLCh *qualifiedName,
  125.                                IDOM_DocumentType *doctype)
  126.     : fNode(this),
  127.       fParent(this),
  128.       fCurrentBlock(0),
  129.       fFreePtr(0),
  130.       fFreeBytesRemaining(0),
  131.       fDocType(0),
  132.       fDocElement(0),
  133.       fNamePool(0),
  134.       fIterators(0L),
  135.       fTreeWalkers(0L),
  136.       fNodeIDMap(0),
  137.       fUserData(0),
  138.       fRanges(0),
  139.       fChanges(0),
  140.       fNodeListPool(0)
  141. {
  142.    fNamePool    = new (this) IDStringPool(257, this);
  143. setDocumentType(doctype);
  144.    appendChild(createElementNS(fNamespaceURI, qualifiedName));  //root element
  145. }
  146. void IDDocumentImpl::setDocumentType(IDOM_DocumentType *doctype)
  147. {
  148. if (!doctype)
  149. return;
  150.     // New doctypes can be created either with the factory methods on DOMImplementation, in
  151.     //   which case ownerDocument will be 0, or with methods on DocumentImpl, in which case
  152.     //   ownerDocument will be set, but the DocType won't yet be a child of the document.
  153.     if (doctype->getOwnerDocument() != 0 && doctype->getOwnerDocument() != this)
  154.         throw IDOM_DOMException( //one doctype can belong to only one IDDocumentImpl
  155.         IDOM_DOMException::WRONG_DOCUMENT_ERR, 0);
  156.     IDDocumentTypeImpl* doctypeImpl = (IDDocumentTypeImpl*) doctype;
  157.     doctypeImpl->setOwnerDocument(this);
  158.     // The doctype can not have any Entities or Notations yet, because they can not
  159.     //   be created except through factory methods on a document.
  160.     // idom_revisit.  What if this doctype is already a child of the document?
  161. appendChild(doctype);
  162. }
  163. IDDocumentImpl::~IDDocumentImpl()
  164. {
  165.     //  Delete the heap for this document.  This uncerimoniously yanks the storage
  166.     //      out from under all of the nodes in the document.  Destructors are NOT called.
  167.     this->deleteHeap();
  168. };
  169. IDOM_Node *IDDocumentImpl::cloneNode(bool deep) const {
  170.     // clone the node itself
  171.     // idom_revisit  -- this doesn't look right.  What about entities, doctype?
  172.     // Note:  the cloned document node goes on the system heap.  All other
  173.     //   nodes added to the new document will go on that document's heap,
  174.     //   but we need to construct the document first, before its heap exists.
  175.     IDDocumentImpl *newdoc = new IDDocumentImpl();
  176.     // then the children by _importing_ them
  177.     if (deep)
  178.         for (IDOM_Node *n = this->getFirstChild(); n != 0; n = n->getNextSibling()) {
  179.             newdoc->appendChild(newdoc->importNode(n, true));
  180. }
  181.     return newdoc;
  182. };
  183. const XMLCh * IDDocumentImpl::getNodeName() const {
  184.     static const XMLCh nam[] =  // "#document"
  185.         {chPound, chLatin_d, chLatin_o, chLatin_c, chLatin_u, chLatin_m, chLatin_e, chLatin_n, chLatin_t, 0};
  186.     return nam;
  187. }
  188. short IDDocumentImpl::getNodeType() const {
  189.     return IDOM_Node::DOCUMENT_NODE;
  190. };
  191. // even though ownerDocument refers to this in this implementation
  192. // the DOM Level 2 spec says it must be 0, so make it appear so
  193. IDOM_Document * IDDocumentImpl::getOwnerDocument() const {
  194.     return 0;
  195. }
  196. IDOM_Attr *IDDocumentImpl::createAttribute(const XMLCh *nam)
  197. {
  198.     if(!isXMLName(nam))
  199.         throw IDOM_DOMException(IDOM_DOMException::INVALID_CHARACTER_ERR,0);
  200.     return new (this) IDAttrImpl(this,nam);
  201. };
  202. IDOM_CDATASection *IDDocumentImpl::createCDATASection(const XMLCh *data) {
  203.     return new (this) IDCDATASectionImpl(this,data);
  204. };
  205. IDOM_Comment *IDDocumentImpl::createComment(const XMLCh *data)
  206. {
  207.     return new (this) IDCommentImpl(this, data);
  208. };
  209. IDOM_DocumentFragment *IDDocumentImpl::createDocumentFragment()
  210. {
  211.     return new (this) IDDocumentFragmentImpl(this);
  212. };
  213. IDOM_DocumentType *IDDocumentImpl::createDocumentType(const XMLCh *nam)
  214. {
  215.     if (!isXMLName(nam))
  216.         throw IDOM_DOMException(
  217.         IDOM_DOMException::INVALID_CHARACTER_ERR, 0);
  218.     return new (this) IDDocumentTypeImpl(this, nam);
  219. };
  220. IDOM_DocumentType *
  221.     IDDocumentImpl::createDocumentType(const XMLCh *qualifiedName,
  222.                                      const XMLCh *publicId,
  223.                                      const XMLCh *systemId)
  224. {
  225.     if (!isXMLName(qualifiedName))
  226.         throw IDOM_DOMException(
  227.         IDOM_DOMException::INVALID_CHARACTER_ERR, 0);
  228.     return new (this) IDDocumentTypeImpl(this, qualifiedName, publicId, systemId);
  229. };
  230. IDOM_Element *IDDocumentImpl::createElement(const XMLCh *tagName)
  231. {
  232.     if(!isXMLName(tagName))
  233.         throw IDOM_DOMException(IDOM_DOMException::INVALID_CHARACTER_ERR,0);
  234.     return new (this) IDElementImpl(this,tagName);
  235. };
  236. IDOM_Element *IDDocumentImpl::createElementNoCheck(const XMLCh *tagName)
  237. {
  238.     return new (this) IDElementImpl(this, tagName);
  239. };
  240. IDOM_Entity *IDDocumentImpl::createEntity(const XMLCh *nam)
  241. {
  242.     if (!isXMLName(nam))
  243.         throw IDOM_DOMException(
  244.         IDOM_DOMException::INVALID_CHARACTER_ERR, 0);
  245.     return new (this) IDEntityImpl(this, nam);
  246. };
  247. IDOM_EntityReference *IDDocumentImpl::createEntityReference(const XMLCh *nam)
  248. {
  249.     if (!isXMLName(nam))
  250.         throw IDOM_DOMException(
  251.         IDOM_DOMException::INVALID_CHARACTER_ERR, 0);
  252.     return new (this) IDEntityReferenceImpl(this, nam);
  253. };
  254. IDOM_Notation *IDDocumentImpl::createNotation(const XMLCh *nam)
  255. {
  256.     if (!isXMLName(nam))
  257.         throw IDOM_DOMException(
  258.         IDOM_DOMException::INVALID_CHARACTER_ERR, 0);
  259.     return new (this) IDNotationImpl(this, nam);
  260. };
  261. IDOM_ProcessingInstruction *IDDocumentImpl::createProcessingInstruction(
  262.                                           const XMLCh *target, const XMLCh *data)
  263. {
  264.     if(!isXMLName(target))
  265.         throw IDOM_DOMException(IDOM_DOMException::INVALID_CHARACTER_ERR,0);
  266.     return new (this) IDProcessingInstructionImpl(this,target,data);
  267. };
  268. IDOM_Text *IDDocumentImpl::createTextNode(const XMLCh *data)
  269. {
  270.     return new (this) IDTextImpl(this,data);
  271. };
  272. IDOM_NodeIterator* IDDocumentImpl::createNodeIterator (
  273.           IDOM_Node *root, unsigned long whatToShow, IDOM_NodeFilter* filter, bool entityReferenceExpansion)
  274. {
  275. // Create the node iterator implementation object.
  276. // Add it to the vector of fIterators that must be synchronized when a node is deleted.
  277. // The vector of fIterators is kept in the "owner document" if there is one. If there isn't one, I assume that root is the
  278. // owner document.
  279.     IDNodeIteratorImpl* iter = new (this) IDNodeIteratorImpl(root, whatToShow, filter, entityReferenceExpansion);
  280.     IDOM_Document* doc = root->getOwnerDocument();
  281.     IDDocumentImpl* impl;
  282.     if (doc != 0) {
  283.         impl = (IDDocumentImpl *) doc;
  284.     }
  285.     else
  286.         impl = (IDDocumentImpl *) root;
  287.     if (impl->fIterators == 0L) {
  288.         impl->fIterators = new (this) NodeIterators(1, false);
  289.         impl->fIterators->addElement(iter);
  290.     }
  291.     return iter;
  292. }
  293. IDOM_TreeWalker* IDDocumentImpl::createTreeWalker (IDOM_Node *root, unsigned long whatToShow, IDOM_NodeFilter* filter, bool entityReferenceExpansion)
  294. {
  295.     // See notes for createNodeIterator...
  296.     IDTreeWalkerImpl* twi = new (this) IDTreeWalkerImpl(root, whatToShow, filter, entityReferenceExpansion);
  297.     IDOM_Document* doc = root->getOwnerDocument();
  298.     IDDocumentImpl* impl;
  299.     if ( doc != 0) {
  300.         impl = (IDDocumentImpl *) doc;
  301.     }
  302.     else
  303.         impl = (IDDocumentImpl *) root;
  304.     if (impl->fTreeWalkers == 0L) {
  305.         impl->fTreeWalkers = new (this) TreeWalkers(1, false);
  306.         impl->fTreeWalkers->addElement(twi);
  307.     }
  308.     return twi;
  309. }
  310. IDOM_DocumentType *IDDocumentImpl::getDoctype() const
  311. {
  312.     return fDocType;
  313. };
  314. IDOM_Element *IDDocumentImpl::getDocumentElement() const
  315. {
  316.     return fDocElement;
  317. };
  318. IDOM_NodeList *IDDocumentImpl::getElementsByTagName(const XMLCh *tagname) const
  319. {
  320.     // cast off the const of this because we will update the fNodeListPool
  321.     return ((IDDocumentImpl*)this)->getDeepNodeList(this,tagname);
  322. };
  323. IDOM_DOMImplementation   *IDDocumentImpl::getImplementation() const {
  324.     return IDOM_DOMImplementation::getImplementation();
  325. }
  326. IDOM_Node *IDDocumentImpl::insertBefore(IDOM_Node *newChild, IDOM_Node *refChild)
  327. {
  328.     // Only one such child permitted
  329.     if(
  330.         (newChild->getNodeType() == IDOM_Node::ELEMENT_NODE  && fDocElement!=0)
  331.         ||
  332.         (newChild->getNodeType() == IDOM_Node::DOCUMENT_TYPE_NODE  && fDocType!=0)
  333.         )
  334.         throw IDOM_DOMException(IDOM_DOMException::HIERARCHY_REQUEST_ERR,0);
  335.     fParent.insertBefore(newChild,refChild);
  336.     // If insert succeeded, cache the kid appropriately
  337.     if(newChild->getNodeType() == IDOM_Node::ELEMENT_NODE)
  338.         fDocElement=(IDOM_Element *)newChild;
  339.     else if(newChild->getNodeType() == IDOM_Node::DOCUMENT_TYPE_NODE)
  340.         fDocType=(IDOM_DocumentType *)newChild;
  341.     return newChild;
  342. };
  343. bool IDDocumentImpl::isXMLName(const XMLCh *s)
  344. {
  345.     // idom_revist.  This function probably already exists in the scanner.
  346.     if (!XMLReader::isFirstNameChar(s[0]))
  347.         return false;
  348.     const XMLCh *p;
  349.     for (p=s+1; *p!=0; p++)
  350.     {
  351.         if (!XMLReader::isNameChar(*p))
  352.             return false;
  353.     }
  354.     return true;
  355. };
  356. IDOM_Node *IDDocumentImpl::removeChild(IDOM_Node *oldChild)
  357. {
  358.     fParent.removeChild(oldChild);
  359.     // If remove succeeded, un-cache the kid appropriately
  360.     if(oldChild->getNodeType() == IDOM_Node::ELEMENT_NODE)
  361.         fDocElement=0;
  362.     else if(oldChild->getNodeType() == IDOM_Node::DOCUMENT_TYPE_NODE)
  363.         fDocType=0;
  364.     return oldChild;
  365. };
  366. void IDDocumentImpl::setNodeValue(const XMLCh *x)
  367. {
  368.     fNode.setNodeValue(x);
  369. };
  370. //Introduced in DOM Level 2
  371. IDOM_Node *IDDocumentImpl::importNode(IDOM_Node *source, bool deep)
  372. {
  373.     IDOM_Node *newnode=0;
  374.     switch (source->getNodeType())
  375.     {
  376.     case IDOM_Node::ELEMENT_NODE :
  377.         {
  378.             IDOM_Element *newelement;
  379.             if (source->getLocalName() == 0)
  380.                 newelement = createElement(source->getNodeName());
  381.             else
  382.                 newelement = createElementNS(source->getNamespaceURI(),
  383.                 source->getNodeName());
  384.             IDOM_NamedNodeMap *srcattr=source->getAttributes();
  385.             if(srcattr!=0)
  386.                 for(unsigned int i=0;i<srcattr->getLength();++i)
  387.                 {
  388.                     IDOM_Attr *attr = (IDOM_Attr *) srcattr->item(i);
  389.                     if (attr -> getSpecified()) { // not a default attribute
  390.                         IDOM_Attr *nattr = (IDOM_Attr *) importNode(attr, true);
  391.                         if (attr -> getLocalName() == 0)
  392.                             newelement->setAttributeNode(nattr);
  393.                         else
  394.                             newelement->setAttributeNodeNS(nattr);
  395.                     }
  396.                 }
  397.                 newnode=newelement;
  398.         }
  399.         break;
  400.     case IDOM_Node::ATTRIBUTE_NODE :
  401.         if (source->getLocalName() == 0)
  402.             newnode = createAttribute(source->getNodeName());
  403.         else
  404.             newnode = createAttributeNS(source->getNamespaceURI(),
  405.             source->getNodeName());
  406.         deep = true;
  407.         // Kids carry value
  408.         break;
  409.     case IDOM_Node::TEXT_NODE :
  410.         newnode = createTextNode(source->getNodeValue());
  411.         break;
  412.     case IDOM_Node::CDATA_SECTION_NODE :
  413.         newnode = createCDATASection(source->getNodeValue());
  414.         break;
  415.     case IDOM_Node::ENTITY_REFERENCE_NODE :
  416.         newnode = createEntityReference(source->getNodeName());
  417.         castToNodeImpl(newnode) -> isReadOnly(false); //allow deep import temporarily
  418.         break;
  419.     case IDOM_Node::ENTITY_NODE :
  420.         {
  421.             IDOM_Entity *srcentity=(IDOM_Entity *)source;
  422.             IDEntityImpl *newentity = (IDEntityImpl *)createEntity(source->getNodeName());
  423.             newentity->setPublicId(srcentity->getPublicId());
  424.             newentity->setSystemId(srcentity->getSystemId());
  425.             newentity->setNotationName(srcentity->getNotationName());
  426.             // Kids carry additional value
  427.             newnode=newentity;
  428.             castToNodeImpl(newentity)->isReadOnly(false);// allow deep import temporarily
  429.         }
  430.         break;
  431.     case IDOM_Node::PROCESSING_INSTRUCTION_NODE :
  432.         newnode = createProcessingInstruction(source->getNodeName(),
  433.             source->getNodeValue());
  434.         break;
  435.     case IDOM_Node::COMMENT_NODE :
  436.         newnode = createComment(source->getNodeValue());
  437.         break;
  438.     case IDOM_Node::DOCUMENT_TYPE_NODE :
  439.         {
  440.             IDOM_DocumentType *srcdoctype = (IDOM_DocumentType *)source;
  441.             IDOM_DocumentType *newdoctype = (IDOM_DocumentType *)
  442.                 createDocumentType(srcdoctype->getNodeName(),
  443.                 srcdoctype->getPublicId(),
  444.                 srcdoctype->getSystemId());
  445.             // Values are on NamedNodeMaps
  446.             IDOM_NamedNodeMap *smap = srcdoctype->getEntities();
  447.             IDOM_NamedNodeMap *tmap = newdoctype->getEntities();
  448.             if(smap != 0) {
  449.                 for(unsigned int i = 0; i < smap->getLength(); i++) {
  450.                     tmap->setNamedItem(importNode(smap->item(i), true));
  451.                 }
  452.             }
  453.             smap = srcdoctype->getNotations();
  454.             tmap = newdoctype->getNotations();
  455.             if (smap != 0) {
  456.                 for(unsigned int i = 0; i < smap->getLength(); i++) {
  457.                     tmap->setNamedItem(importNode(smap->item(i), true));
  458.                 }
  459.             }
  460.             // NOTE: At this time, the DOM definition of DocumentType
  461.             // doesn't cover Elements and their Attributes. domimpl's
  462.             // extentions in that area will not be preserved, even if
  463.             // copying from domimpl to domimpl. We could special-case
  464.             // that here. Arguably we should. Consider. ?????
  465.             newnode = newdoctype;
  466.         }
  467.         break;
  468.     case IDOM_Node::DOCUMENT_FRAGMENT_NODE :
  469.         newnode = createDocumentFragment();
  470.         // No name, kids carry value
  471.         break;
  472.     case IDOM_Node::NOTATION_NODE :
  473.         {
  474.             IDOM_Notation *srcnotation=(IDOM_Notation *)source;
  475.             IDNotationImpl *newnotation = (IDNotationImpl *)createNotation(source->getNodeName());
  476.             newnotation->setPublicId(srcnotation->getPublicId());
  477.             newnotation->setSystemId(srcnotation->getSystemId());
  478.             // Kids carry additional value
  479.             newnode=newnotation;
  480.             // No name, no value
  481.             break;
  482.         }
  483.     case IDOM_Node::DOCUMENT_NODE : // Document can't be child of Document
  484.     default:                       // Unknown node type
  485.         throw IDOM_DOMException(IDOM_DOMException::NOT_SUPPORTED_ERR, 0);
  486.     }
  487.     // If deep, replicate and attach the kids.
  488.     if (deep)
  489.         for (IDOM_Node *srckid = source->getFirstChild();
  490.         srckid != 0;
  491.         srckid = srckid->getNextSibling()) {
  492.             newnode->appendChild(importNode(srckid, true));
  493.         }
  494.         if (newnode->getNodeType() == IDOM_Node::ENTITY_REFERENCE_NODE
  495.             || newnode->getNodeType() == IDOM_Node::ENTITY_REFERENCE_NODE)
  496.             castToNodeImpl(newnode)->isReadOnly(true);
  497.         return newnode;
  498. }
  499. IDOM_Element *IDDocumentImpl::createElementNS(const XMLCh *fNamespaceURI,
  500. const XMLCh *qualifiedName)
  501. {
  502.     if(!isXMLName(qualifiedName))
  503.         throw IDOM_DOMException(IDOM_DOMException::INVALID_CHARACTER_ERR,0);
  504.     //XMLCh * pooledTagName = this->fNamePool->getPooledString(qualifiedName);
  505.     return new (this) IDElementNSImpl(this, fNamespaceURI, qualifiedName);
  506. }
  507. IDOM_Attr *IDDocumentImpl::createAttributeNS(const XMLCh *fNamespaceURI,
  508. const XMLCh *qualifiedName)
  509. {
  510.     if(!isXMLName(qualifiedName))
  511.         throw IDOM_DOMException(IDOM_DOMException::INVALID_CHARACTER_ERR,0);
  512.     return new (this) IDAttrNSImpl(this, fNamespaceURI, qualifiedName);
  513. }
  514. IDOM_NodeList *IDDocumentImpl::getElementsByTagNameNS(const XMLCh *fNamespaceURI,
  515. const XMLCh *fLocalName)  const
  516. {
  517.     // cast off the const of this because we will update the fNodeListPool
  518.     return ((IDDocumentImpl*)this)->getDeepNodeList(this, fNamespaceURI, fLocalName);
  519. }
  520. IDOM_Element *IDDocumentImpl::getElementById(const XMLCh *elementId) const
  521. {
  522.     if (fNodeIDMap == 0)
  523.         return 0;
  524.     IDOM_Attr *theAttr = fNodeIDMap->find(elementId);
  525.     if (theAttr == 0)
  526.     return 0;
  527.     return theAttr->getOwnerElement();
  528. }
  529. //Return the index > 0 of ':' in the given qualified name qName="prefix:localName".
  530. //Return 0 if there is no ':', or -1 if qName is malformed such as ":abcd".
  531. int IDDocumentImpl::indexofQualifiedName(const XMLCh * qName)
  532. {
  533.     //Check if s = prefix:localName, name or malformed
  534.     int firstOccurence = XMLString::indexOf(qName, chColon);
  535.     int lastOccurence  = XMLString::lastIndexOf(qName, chColon);
  536.     if (firstOccurence != lastOccurence || firstOccurence == 0) {
  537.         // Error.  More than two ':'s, or ':' is first char.
  538.         return -1;
  539.     }
  540.     if (firstOccurence == -1) {
  541.         //  No colons in the name
  542.         firstOccurence = 0;
  543.     }
  544.     return firstOccurence;
  545. }
  546. IDOM_Range* IDDocumentImpl::createRange()
  547. {
  548.     IDRangeImpl* range = new (this) IDRangeImpl(this);
  549.     if (fRanges == 0L) {
  550.         fRanges = new (this) Ranges(1, false);
  551.     }
  552.     fRanges->addElement(range);
  553.     return range;
  554. }
  555. Ranges* IDDocumentImpl::getRanges() const
  556. {
  557.     return fRanges;
  558. }
  559. void IDDocumentImpl::removeRange(IDRangeImpl* range)
  560. {
  561.     if (fRanges != 0) {
  562.         unsigned int sz = fRanges->size();
  563.         if (sz !=0) {
  564.             for (unsigned int i =0; i<sz; i++) {
  565.                 if (fRanges->elementAt(i) == range) {
  566.                     fRanges->removeElementAt(i);
  567.                     break;
  568.                 }
  569.             }
  570.         }
  571.     }
  572. }
  573. /** Uses the kidOK lookup table to check whether the proposed
  574.     tree structure is legal.
  575.     ????? It feels like there must be a more efficient solution,
  576.     but for the life of me I can't think what it would be.
  577. */
  578. bool IDDocumentImpl::isKidOK(IDOM_Node *parent, IDOM_Node *child)
  579. {
  580.       static int kidOK[14];
  581.       if (kidOK[IDOM_Node::ATTRIBUTE_NODE] == 0)
  582.       {
  583.           kidOK[IDOM_Node::DOCUMENT_NODE] =
  584.               1 << IDOM_Node::ELEMENT_NODE |
  585.               1 << IDOM_Node::PROCESSING_INSTRUCTION_NODE |
  586.               1 << IDOM_Node::COMMENT_NODE |
  587.               1 << IDOM_Node::DOCUMENT_TYPE_NODE |
  588.               1 << IDOM_Node::XML_DECL_NODE;
  589.           kidOK[IDOM_Node::DOCUMENT_FRAGMENT_NODE] =
  590.               kidOK[IDOM_Node::ENTITY_NODE] =
  591.               kidOK[IDOM_Node::ENTITY_REFERENCE_NODE] =
  592.               kidOK[IDOM_Node::ELEMENT_NODE] =
  593.               1 << IDOM_Node::ELEMENT_NODE |
  594.               1 << IDOM_Node::PROCESSING_INSTRUCTION_NODE |
  595.               1 << IDOM_Node::COMMENT_NODE |
  596.               1 << IDOM_Node::TEXT_NODE |
  597.               1 << IDOM_Node::CDATA_SECTION_NODE |
  598.               1 << IDOM_Node::ENTITY_REFERENCE_NODE |
  599.               1 << IDOM_Node::XML_DECL_NODE;
  600.           kidOK[IDOM_Node::ATTRIBUTE_NODE] =
  601.               1 << IDOM_Node::TEXT_NODE |
  602.               1 << IDOM_Node::ENTITY_REFERENCE_NODE;
  603.           kidOK[IDOM_Node::PROCESSING_INSTRUCTION_NODE] =
  604.               kidOK[IDOM_Node::COMMENT_NODE] =
  605.               kidOK[IDOM_Node::TEXT_NODE] =
  606.               kidOK[IDOM_Node::CDATA_SECTION_NODE] =
  607.               kidOK[IDOM_Node::NOTATION_NODE] =
  608.               0;
  609.       };
  610.       int p=parent->getNodeType();
  611.       int ch = child->getNodeType();
  612.       return (kidOK[p] & 1<<ch) != 0;
  613. }
  614. void IDDocumentImpl::setUserData(IDOM_Node* n, void* data)
  615. {
  616. if (!fUserData && data)
  617. fUserData = new (this) RefHashTableOf<void>(29, false, new (this) HashPtr());
  618. if (!data && fUserData)
  619. fUserData->removeKey((void*)n);
  620. else
  621. fUserData->put((void*)n,data);
  622. }
  623. void* IDDocumentImpl::getUserData(const IDOM_Node* n) const
  624. {
  625. if (fUserData)
  626. return fUserData->get((void*)n);
  627. else
  628. return 0;
  629. }
  630. void* IDDocumentImpl::getUserData() const
  631. {
  632. return (fNode.hasUserData()) ? getUserData(this) : 0;
  633. }
  634. void IDDocumentImpl::setUserData(void* val)
  635. {
  636. setUserData(this, val);
  637. if (val)
  638. fNode.hasUserData(true);
  639. else
  640. fNode.hasUserData(false);
  641. };
  642. void            IDDocumentImpl::changed()
  643. {
  644.     fChanges++;
  645. }
  646. int             IDDocumentImpl::changes() const{
  647.     return fChanges;
  648. };
  649. //
  650. //    Delegation for functions inherited from IDOM_Node
  651. //
  652.            IDOM_Node          *IDDocumentImpl::appendChild(IDOM_Node *newChild)        {return insertBefore(newChild, 0); };
  653.            IDOM_NamedNodeMap  *IDDocumentImpl::getAttributes() const          {return fNode.getAttributes (); };
  654.            IDOM_NodeList      *IDDocumentImpl::getChildNodes() const          {return fParent.getChildNodes (); };
  655.            IDOM_Node          *IDDocumentImpl::getFirstChild() const          {return fParent.getFirstChild (); };
  656.            IDOM_Node          *IDDocumentImpl::getLastChild() const              {return fParent.getLastChild (); };
  657.      const XMLCh              *IDDocumentImpl::getLocalName() const                    {return fNode.getLocalName (); };
  658.      const XMLCh              *IDDocumentImpl::getNamespaceURI() const                 {return fNode.getNamespaceURI (); };
  659.            IDOM_Node          *IDDocumentImpl::getNextSibling() const                  {return fNode.getNextSibling (); };
  660.      const XMLCh              *IDDocumentImpl::getNodeValue() const                    {return fNode.getNodeValue (); };
  661.      const XMLCh              *IDDocumentImpl::getPrefix() const                       {return fNode.getPrefix (); };
  662.            IDOM_Node          *IDDocumentImpl::getParentNode() const                   {return fNode.getParentNode (); };
  663.            IDOM_Node          *IDDocumentImpl::getPreviousSibling() const              {return fNode.getPreviousSibling (); };
  664.            bool                IDDocumentImpl::hasChildNodes() const                   {return fParent.hasChildNodes (); };
  665.            void                IDDocumentImpl::normalize()                             {fNode.normalize (); };
  666.            IDOM_Node          *IDDocumentImpl::replaceChild(IDOM_Node *newChild, IDOM_Node *oldChild)
  667.                                                                             {return fParent.replaceChild (newChild, oldChild); };
  668.            bool                IDDocumentImpl::supports(const XMLCh *feature, const XMLCh *version) const
  669.                                                                             {return fNode.supports (feature, version); };
  670.            void                IDDocumentImpl::setPrefix(const XMLCh  *prefix)         {fNode.setPrefix(prefix); };
  671. //-----------------------------------------------------------------------
  672. //
  673. //  Per Document Heap and Heap Helper functions
  674. //
  675. //        idom_revisit - this stuff should be a class of its own, rather than
  676. //                       just lying around naked in DocumentImpl.
  677. //
  678. //-----------------------------------------------------------------------
  679. XMLCh * IDDocumentImpl::cloneString(const XMLCh *src)
  680. {
  681.     size_t   len = XMLString::stringLen(src);
  682.     len = (len + 1) * sizeof(XMLCh);
  683.     len = (len % 4) + len;
  684.     XMLCh *newStr = (XMLCh *)this->allocate(len);
  685.     XMLString::copyString(newStr, src);
  686.     return newStr;
  687. }
  688. const XMLCh *  IDDocumentImpl::getPooledString(const XMLCh *src)
  689. {
  690.     return this->fNamePool->getPooledString(src);
  691. }
  692. static const int kHeapAllocSize = 0x10000;    // The chunk size to allocate from the
  693.                                               //   system allocator.
  694. static const int kMaxSubAllocationSize = 4096;   // Any request for more bytes
  695.                                                  //  than this will be handled by
  696.                                                  //  allocating directly with system.
  697. void *         IDDocumentImpl::allocate(size_t amount)
  698. {
  699.      size_t sizeOfPointer = sizeof(void *);
  700.      if (amount%sizeOfPointer!=0)
  701.        amount = amount + (sizeOfPointer - (amount % sizeOfPointer));
  702.     // If the request is for a largish block, hand it off to the system
  703.     //   allocator.  The block still must be linked into the list of
  704.     //   allocated blocks so that it will be deleted when the time comes.
  705.     if (amount > kMaxSubAllocationSize)
  706.     {
  707.         void* newBlock = 0;
  708.         try {
  709.             newBlock = new char[amount + sizeof(void *)];
  710.         }
  711.         catch (...) {
  712.             ThrowXML(RuntimeException, XMLExcepts::Out_Of_Memory);
  713.         }
  714.         if (!newBlock)
  715.            ThrowXML(RuntimeException, XMLExcepts::Out_Of_Memory);
  716.         if (fCurrentBlock)
  717.         {
  718.             *(void **)newBlock = *(void **)fCurrentBlock;
  719.             *(void **)fCurrentBlock = newBlock;
  720.         }
  721.         else
  722.         {
  723.             fCurrentBlock = newBlock;
  724.             fFreePtr = 0;
  725.             fFreeBytesRemaining = 0;
  726.         }
  727.         void *retPtr = (char *)newBlock + sizeOfPointer;
  728.         return retPtr;
  729.     }
  730.     // It's a normal (sub-allocatable) request.
  731.     if (amount > fFreeBytesRemaining)
  732.     {
  733.         // Request doesn't fit in the current block.
  734.         //   Get a new one from the system allocator.
  735.         void* newBlock = 0;
  736.         try {
  737.             newBlock = new char[kHeapAllocSize];
  738.         }
  739.         catch (...) {
  740.             ThrowXML(RuntimeException, XMLExcepts::Out_Of_Memory);
  741.         }
  742.         if (!newBlock)
  743.            ThrowXML(RuntimeException, XMLExcepts::Out_Of_Memory);
  744.         *(void **)newBlock = fCurrentBlock;
  745.         fCurrentBlock = newBlock;
  746.         fFreePtr = (char *)newBlock + sizeof(void *);
  747.         fFreeBytesRemaining = kHeapAllocSize - sizeof(void *);
  748.     }
  749.     void *retPtr = fFreePtr;
  750.     fFreePtr += amount;
  751.     fFreeBytesRemaining -= amount;
  752.     return retPtr;
  753. }
  754. void    IDDocumentImpl::deleteHeap()
  755. {
  756.     void *block = fCurrentBlock;
  757.     while (fCurrentBlock != 0)
  758.     {
  759.         void *nextBlock = *(void **)fCurrentBlock;
  760.         delete [] fCurrentBlock;
  761.         fCurrentBlock = nextBlock;
  762.     }
  763. }
  764. IDOM_NodeList *IDDocumentImpl::getDeepNodeList(const IDOM_Node *rootNode, const XMLCh *tagName)
  765. {
  766.     if(!fNodeListPool) {
  767.         fNodeListPool = new (this) IDDeepNodeListPool<IDDeepNodeListImpl>(109, false);
  768.     }
  769.     IDDeepNodeListImpl* retList = fNodeListPool->getByKey(rootNode, tagName, 0);
  770.     if (!retList) {
  771.         int id = fNodeListPool->put((void*) rootNode, (XMLCh*) tagName, 0, new (this) IDDeepNodeListImpl(rootNode, tagName));
  772.         retList = fNodeListPool->getById(id);
  773.     }
  774.     return retList;
  775. }
  776. IDOM_NodeList *IDDocumentImpl::getDeepNodeList(const IDOM_Node *rootNode,     //DOM Level 2
  777.                                                    const XMLCh *namespaceURI,
  778.                                                    const XMLCh *localName)
  779. {
  780.     if(!fNodeListPool) {
  781.         fNodeListPool = new (this) IDDeepNodeListPool<IDDeepNodeListImpl>(109, false);
  782.     }
  783.     IDDeepNodeListImpl* retList = fNodeListPool->getByKey(rootNode, localName, namespaceURI);
  784.     if (!retList) {
  785.         // the pool will adopt the IDDeepNodeListImpl
  786.         int id = fNodeListPool->put((void*) rootNode, (XMLCh*) localName, (XMLCh*) namespaceURI, new (this) IDDeepNodeListImpl(rootNode, namespaceURI, localName));
  787.         retList = fNodeListPool->getById(id);
  788.     }
  789.     return retList;
  790. }