PageRenderTime 70ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/ATF2/control-software/epics-3.14.8/extensions/src/ChannelArchiver/ThirdParty/xerces-c-src2_4_0/src/xercesc/dom/impl/DOMDocumentImpl.cpp

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