Newer
Older
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001-2003 The Apache Software Foundation. All rights
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Xerces" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache\@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation, and was
* originally based on software copyright (c) 2001, International
* Business Machines, Inc., http://www.ibm.com . For more information
* on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
/*
* $Id$
*/
#include "DOMDocumentImpl.hpp"
#include "DOMCasts.hpp"
#include "DOMConfigurationImpl.hpp"
#include "DOMDocumentTypeImpl.hpp"
#include "DOMAttrImpl.hpp"
#include "DOMAttrNSImpl.hpp"
#include "DOMCDATASectionImpl.hpp"
#include "DOMCommentImpl.hpp"
#include "DOMDeepNodeListImpl.hpp"
#include "DOMDocumentFragmentImpl.hpp"
#include "DOMElementImpl.hpp"
#include "XSDElementNSImpl.hpp"
#include "DOMEntityImpl.hpp"
#include "DOMEntityReferenceImpl.hpp"
#include "DOMNotationImpl.hpp"
#include "DOMProcessingInstructionImpl.hpp"
#include "DOMTextImpl.hpp"
#include "DOMStringPool.hpp"
#include "DOMTreeWalkerImpl.hpp"
#include "DOMNodeIteratorImpl.hpp"
#include "DOMNodeIDMap.hpp"
#include "DOMRangeImpl.hpp"
#include <xercesc/dom/DOMImplementation.hpp>
#include <xercesc/util/XMLChar.hpp>
#include <xercesc/framework/MemoryManager.hpp>
Neil Graham
committed
#include <xercesc/util/OutOfMemoryException.hpp>
//
// Constructors. Warning - be very careful with the ordering of initialization
// of the heap. Ordering depends on the order of declaration
// in the .hpp file, not on the order of initializers here
// in the constructor. The heap declaration can not be
// first - fNode and fParent must be first for the casting
// functions in DOMCasts to work correctly. This means that
// fNode and fParent constructors used here can not
// allocate.
//
DOMDocumentImpl::DOMDocumentImpl(MemoryManager* const manager)
: fNode(this),
fParent(this),
fNodeIDMap(0),
David Abram Cargill
committed
fVersion(0),
David Abram Cargill
committed
fDOMConfiguration(0),
fUserDataTableKeys(17, manager),
David Abram Cargill
committed
fCurrentBlock(0),
fFreePtr(0),
fFreeBytesRemaining(0),
fRecycleNodePtr(0),
fRecycleBufferPtr(0),
David Abram Cargill
committed
fNodeListPool(0),
fDocType(0),
fDocElement(0),
fNamePool(0),
fNormalizer(0),
fRanges(0),
fNodeIterators(0),
fMemoryManager(manager),
David Abram Cargill
committed
fChanges(0),
{
fNamePool = new (this) DOMStringPool(257, this);
David Abram Cargill
committed
}
//DOM Level 2
DOMDocumentImpl::DOMDocumentImpl(const XMLCh *fNamespaceURI,
const XMLCh *qualifiedName,
DOMDocumentType *doctype,
MemoryManager* const manager)
: fNode(this),
fParent(this),
fNodeIDMap(0),
David Abram Cargill
committed
fVersion(0),
David Abram Cargill
committed
fDOMConfiguration(0),
fUserDataTableKeys(17, manager),
David Abram Cargill
committed
fCurrentBlock(0),
fFreePtr(0),
fFreeBytesRemaining(0),
fRecycleNodePtr(0),
fRecycleBufferPtr(0),
David Abram Cargill
committed
fNodeListPool(0),
fDocType(0),
fDocElement(0),
fNamePool(0),
fNormalizer(0),
fRanges(0),
fNodeIterators(0),
fMemoryManager(manager),
David Abram Cargill
committed
fChanges(0),
{
fNamePool = new (this) DOMStringPool(257, this);
try {
setDocumentType(doctype);
if (qualifiedName)
appendChild(createElementNS(fNamespaceURI, qualifiedName)); //root element
else if (fNamespaceURI)
throw DOMException(DOMException::NAMESPACE_ERR, 0, getMemoryManager());
}
Neil Graham
committed
catch(const OutOfMemoryException&)
{
throw;
}
catch (...) {
this->deleteHeap();
throw;
}
}
void DOMDocumentImpl::setDocumentType(DOMDocumentType *doctype)
{
// New doctypes can be created either with the factory methods on DOMImplementation, in
// which case ownerDocument will be 0, or with methods on DocumentImpl, in which case
// ownerDocument will be set, but the DocType won't yet be a child of the document.
if (doctype->getOwnerDocument() != 0 && doctype->getOwnerDocument() != this)
throw DOMException( //one doctype can belong to only one DOMDocumentImpl
DOMException::WRONG_DOCUMENT_ERR, 0, getMemoryManager());
DOMDocumentTypeImpl* doctypeImpl = (DOMDocumentTypeImpl*) doctype;
doctypeImpl->setOwnerDocument(this);
// The doctype can not have any Entities or Notations yet, because they can not
// be created except through factory methods on a document.
// revisit. What if this doctype is already a child of the document?
}
DOMDocumentImpl::~DOMDocumentImpl()
{
// Clean up the fNodeListPool
if (fNodeListPool)
fNodeListPool->cleanup();
if (fRanges)
delete fRanges; //fRanges->cleanup();
if (fNodeIterators)
delete fNodeIterators;//fNodeIterators->cleanup();
delete fUserDataTable;//fUserDataTable->cleanup();
if (fRecycleNodePtr) {
fRecycleNodePtr->deleteAllElements();
delete fRecycleNodePtr;
}
if (fRecycleBufferPtr) {
delete fRecycleBufferPtr;
}
// Delete the heap for this document. This uncerimoniously yanks the storage
// out from under all of the nodes in the document. Destructors are NOT called.
this->deleteHeap();
David Abram Cargill
committed
}
DOMNode *DOMDocumentImpl::cloneNode(bool deep) const {
Alberto Massari
committed
// Note: the cloned document node goes on the same heap we live in.
DOMDocumentImpl *newdoc = new (fMemoryManager) DOMDocumentImpl(fMemoryManager);
Alberto Massari
committed
if(fEncoding && *fEncoding)
newdoc->setEncoding(fEncoding);
if(fVersion && *fVersion)
newdoc->setVersion(fVersion);
newdoc->setStandalone(fStandalone);
// then the children by _importing_ them
if (deep)
for (DOMNode *n = this->getFirstChild(); n != 0; n = n->getNextSibling()) {
newdoc->appendChild(newdoc->importNode(n, true, true));
}
fNode.callUserDataHandlers(DOMUserDataHandler::NODE_CLONED, this, newdoc);
return newdoc;
David Abram Cargill
committed
}
const XMLCh * DOMDocumentImpl::getNodeName() const {
static const XMLCh nam[] = // "#document"
{chPound, chLatin_d, chLatin_o, chLatin_c, chLatin_u, chLatin_m, chLatin_e, chLatin_n, chLatin_t, 0};
return nam;
}
short DOMDocumentImpl::getNodeType() const {
return DOMNode::DOCUMENT_NODE;
David Abram Cargill
committed
}
// even though ownerDocument refers to this in this implementation
// the DOM Level 2 spec says it must be 0, so make it appear so
DOMDocument * DOMDocumentImpl::getOwnerDocument() const {
return 0;
}
DOMAttr *DOMDocumentImpl::createAttribute(const XMLCh *nam)
{
throw DOMException(DOMException::INVALID_CHARACTER_ERR,0, getMemoryManager());
return new (this, DOMDocumentImpl::ATTR_OBJECT) DOMAttrImpl(this,nam);
David Abram Cargill
committed
}
DOMCDATASection *DOMDocumentImpl::createCDATASection(const XMLCh *data) {
return new (this, DOMDocumentImpl::CDATA_SECTION_OBJECT) DOMCDATASectionImpl(this,data);
David Abram Cargill
committed
}
DOMComment *DOMDocumentImpl::createComment(const XMLCh *data)
{
return new (this, DOMDocumentImpl::COMMENT_OBJECT) DOMCommentImpl(this, data);
David Abram Cargill
committed
}
DOMDocumentFragment *DOMDocumentImpl::createDocumentFragment()
{
return new (this, DOMDocumentImpl::DOCUMENT_FRAGMENT_OBJECT) DOMDocumentFragmentImpl(this);
David Abram Cargill
committed
}
DOMDocumentType *DOMDocumentImpl::createDocumentType(const XMLCh *nam)
{
throw DOMException(
DOMException::INVALID_CHARACTER_ERR, 0, getMemoryManager());
return new (this, DOMDocumentImpl::DOCUMENT_TYPE_OBJECT) DOMDocumentTypeImpl(this, nam, false);
David Abram Cargill
committed
}
DOMDocumentType *
DOMDocumentImpl::createDocumentType(const XMLCh *qualifiedName,
const XMLCh *publicId,
const XMLCh *systemId)
{
throw DOMException(
DOMException::INVALID_CHARACTER_ERR, 0, getMemoryManager());
return new (this, DOMDocumentImpl::DOCUMENT_TYPE_OBJECT) DOMDocumentTypeImpl(this, qualifiedName, publicId, systemId, false);
David Abram Cargill
committed
}
DOMElement *DOMDocumentImpl::createElement(const XMLCh *tagName)
{
throw DOMException(DOMException::INVALID_CHARACTER_ERR,0, getMemoryManager());
return new (this, DOMDocumentImpl::ELEMENT_OBJECT) DOMElementImpl(this,tagName);
David Abram Cargill
committed
}
DOMElement *DOMDocumentImpl::createElementNoCheck(const XMLCh *tagName)
{
return new (this, DOMDocumentImpl::ELEMENT_OBJECT) DOMElementImpl(this, tagName);
David Abram Cargill
committed
}
DOMEntity *DOMDocumentImpl::createEntity(const XMLCh *nam)
{
throw DOMException(
DOMException::INVALID_CHARACTER_ERR, 0, getMemoryManager());
return new (this, DOMDocumentImpl::ENTITY_OBJECT) DOMEntityImpl(this, nam);
David Abram Cargill
committed
}
DOMEntityReference *DOMDocumentImpl::createEntityReference(const XMLCh *nam)
{
throw DOMException(
DOMException::INVALID_CHARACTER_ERR, 0, getMemoryManager());
return new (this, DOMDocumentImpl::ENTITY_REFERENCE_OBJECT) DOMEntityReferenceImpl(this, nam);
David Abram Cargill
committed
}
DOMEntityReference *DOMDocumentImpl::createEntityReferenceByParser(const XMLCh *nam)
{
if (!nam || !isXMLName(nam))
throw DOMException(
DOMException::INVALID_CHARACTER_ERR, 0, getMemoryManager());
return new (this, DOMDocumentImpl::ENTITY_REFERENCE_OBJECT) DOMEntityReferenceImpl(this, nam, false);
David Abram Cargill
committed
}
DOMNotation *DOMDocumentImpl::createNotation(const XMLCh *nam)
{
throw DOMException(
DOMException::INVALID_CHARACTER_ERR, 0, getMemoryManager());
return new (this, DOMDocumentImpl::NOTATION_OBJECT) DOMNotationImpl(this, nam);
David Abram Cargill
committed
}
DOMProcessingInstruction *DOMDocumentImpl::createProcessingInstruction(
const XMLCh *target, const XMLCh *data)
{
throw DOMException(DOMException::INVALID_CHARACTER_ERR,0, getMemoryManager());
return new (this, DOMDocumentImpl::PROCESSING_INSTRUCTION_OBJECT) DOMProcessingInstructionImpl(this,target,data);
David Abram Cargill
committed
}
DOMText *DOMDocumentImpl::createTextNode(const XMLCh *data)
{
return new (this, DOMDocumentImpl::TEXT_OBJECT) DOMTextImpl(this,data);
David Abram Cargill
committed
}
DOMNodeIterator* DOMDocumentImpl::createNodeIterator (
DOMNode *root, unsigned long whatToShow, DOMNodeFilter* filter, bool entityReferenceExpansion)
{
if (!root) {
throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, getMemoryManager());
return 0;
}
DOMNodeIteratorImpl* nodeIterator = new (this) DOMNodeIteratorImpl(this, root, whatToShow, filter, entityReferenceExpansion);
if (fNodeIterators == 0L) {
//fNodeIterators = new (this) NodeIterators(1, false);
fNodeIterators = new (fMemoryManager) NodeIterators(1, false, fMemoryManager);
}
fNodeIterators->addElement(nodeIterator);
return nodeIterator;
}
NodeIterators* DOMDocumentImpl::getNodeIterators() const
{
return fNodeIterators;
}
void DOMDocumentImpl::removeNodeIterator(DOMNodeIteratorImpl* nodeIterator)
{
if (fNodeIterators != 0) {
XMLSize_t sz = fNodeIterators->size();
if (sz !=0) {
for (XMLSize_t i =0; i<sz; i++) {
if (fNodeIterators->elementAt(i) == nodeIterator) {
fNodeIterators->removeElementAt(i);
break;
}
}
}
}
}
Gareth Reakes
committed
David Abram Cargill
committed
const DOMXPathExpression* DOMDocumentImpl::createExpression(const XMLCh *, const DOMXPathNSResolver *)
Gareth Reakes
committed
{
throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, getMemoryManager());
Gareth Reakes
committed
return 0;
}
David Abram Cargill
committed
const DOMXPathNSResolver* DOMDocumentImpl::createNSResolver(DOMNode *)
Gareth Reakes
committed
{
throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, getMemoryManager());
Gareth Reakes
committed
return 0;
}
David Abram Cargill
committed
void* DOMDocumentImpl::evaluate(const XMLCh *, DOMNode *, const DOMXPathNSResolver *,
unsigned short, void* )
Gareth Reakes
committed
{
throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, getMemoryManager());
Gareth Reakes
committed
return 0;
}
DOMTreeWalker* DOMDocumentImpl::createTreeWalker (DOMNode *root, unsigned long whatToShow, DOMNodeFilter* filter, bool entityReferenceExpansion)
{
if (!root) {
throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, getMemoryManager());
return 0;
}
return new (this) DOMTreeWalkerImpl(root, whatToShow, filter, entityReferenceExpansion);
}
DOMDocumentType *DOMDocumentImpl::getDoctype() const
{
return fDocType;
David Abram Cargill
committed
}
DOMElement *DOMDocumentImpl::getDocumentElement() const
{
return fDocElement;
David Abram Cargill
committed
}
DOMNodeList *DOMDocumentImpl::getElementsByTagName(const XMLCh *tagname) const
{
// cast off the const of this because we will update the fNodeListPool
return ((DOMDocumentImpl*)this)->getDeepNodeList(this,tagname);
David Abram Cargill
committed
}
DOMImplementation *DOMDocumentImpl::getImplementation() const {
return DOMImplementation::getImplementation();
}
DOMNode *DOMDocumentImpl::insertBefore(DOMNode *newChild, DOMNode *refChild)
{
// Only one such child permitted
if(
(newChild->getNodeType() == DOMNode::ELEMENT_NODE && fDocElement!=0)
||
(newChild->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE && fDocType!=0)
)
throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0, getMemoryManager());
// if the newChild is a documenttype node created from domimplementation, set the ownerDoc first
if ((newChild->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE) && !newChild->getOwnerDocument())
fParent.insertBefore(newChild,refChild);
// If insert succeeded, cache the kid appropriately
if(newChild->getNodeType() == DOMNode::ELEMENT_NODE)
fDocElement=(DOMElement *)newChild;
else if(newChild->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE)
fDocType=(DOMDocumentType *)newChild;
return newChild;
David Abram Cargill
committed
}
DOMNode* DOMDocumentImpl::replaceChild(DOMNode *newChild, DOMNode *oldChild) {
DOMDocumentType* tempDocType = fDocType;
DOMElement* tempDocElement = fDocElement;
if(oldChild->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE)
fDocType=0;
else if(oldChild->getNodeType() == DOMNode::ELEMENT_NODE)
fDocElement=0;
try {
insertBefore(newChild, oldChild);
// changed() already done.
if((oldChild->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE)
|| (oldChild->getNodeType() == DOMNode::ELEMENT_NODE))
return fParent.removeChild(oldChild);
else
return removeChild(oldChild);
}
Neil Graham
committed
catch(const OutOfMemoryException&)
{
throw;
}
catch(...) {
fDocType = tempDocType;
fDocElement = tempDocElement;
throw;
}
bool DOMDocumentImpl::isXMLName(const XMLCh *s)
{
if (XMLString::equals(fVersion, XMLUni::fgVersion1_1))
return XMLChar1_1::isValidName(s, XMLString::stringLen(s));
else
return XMLChar1_0::isValidName(s, XMLString::stringLen(s));
David Abram Cargill
committed
}
DOMNode *DOMDocumentImpl::removeChild(DOMNode *oldChild)
{
fParent.removeChild(oldChild);
// If remove succeeded, un-cache the kid appropriately
if(oldChild->getNodeType() == DOMNode::ELEMENT_NODE)
fDocElement=0;
else if(oldChild->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE)
fDocType=0;
return oldChild;
David Abram Cargill
committed
}
void DOMDocumentImpl::setNodeValue(const XMLCh *x)
{
fNode.setNodeValue(x);
David Abram Cargill
committed
}
//Introduced in DOM Level 2
DOMNode *DOMDocumentImpl::importNode(DOMNode *source, bool deep)
{
}
DOMElement *DOMDocumentImpl::createElementNS(const XMLCh *fNamespaceURI,
{
throw DOMException(DOMException::INVALID_CHARACTER_ERR,0, getMemoryManager());
//XMLCh * pooledTagName = this->fNamePool->getPooledString(qualifiedName);
return new (this, DOMDocumentImpl::ELEMENT_NS_OBJECT) DOMElementNSImpl(this, fNamespaceURI, qualifiedName);
}
DOMElement *DOMDocumentImpl::createElementNS(const XMLCh *fNamespaceURI,
const XMLCh *qualifiedName,
Tinny Ng
committed
const XMLSSize_t lineNo,
const XMLSSize_t columnNo)
{
throw DOMException(DOMException::INVALID_CHARACTER_ERR,0, getMemoryManager());
return new (this) XSDElementNSImpl(this, fNamespaceURI, qualifiedName, lineNo, columnNo);
}
DOMAttr *DOMDocumentImpl::createAttributeNS(const XMLCh *fNamespaceURI,
{
throw DOMException(DOMException::INVALID_CHARACTER_ERR,0, getMemoryManager());
return new (this, DOMDocumentImpl::ATTR_NS_OBJECT) DOMAttrNSImpl(this, fNamespaceURI, qualifiedName);
}
DOMNodeList *DOMDocumentImpl::getElementsByTagNameNS(const XMLCh *fNamespaceURI,
{
// cast off the const of this because we will update the fNodeListPool
return ((DOMDocumentImpl*)this)->getDeepNodeList(this, fNamespaceURI, fLocalName);
}
DOMElement *DOMDocumentImpl::getElementById(const XMLCh *elementId) const
{
if (fNodeIDMap == 0)
return 0;
DOMAttr *theAttr = fNodeIDMap->find(elementId);
if (theAttr == 0)
return theAttr->getOwnerElement();
}
//Return the index > 0 of ':' in the given qualified name qName="prefix:localName".
//Return 0 if there is no ':', or -1 if qName is malformed such as ":abcd" or "abcd:".
int DOMDocumentImpl::indexofQualifiedName(const XMLCh * qName)
{
int qNameLen = XMLString::stringLen(qName);
int index = -1, count = 0;
for (int i = 0; i < qNameLen; ++i) {
if (qName[i] == chColon) {
index = i;
}
}
if (qNameLen == 0 || count > 1 || index == 0 || index == qNameLen-1)
return -1;
return count == 0 ? 0 : index;
}
const XMLCh* DOMDocumentImpl::getBaseURI() const
{
return fDocumentURI;
David Abram Cargill
committed
}
DOMRange* DOMDocumentImpl::createRange()
{
DOMRangeImpl* range = new (this) DOMRangeImpl(this, fMemoryManager);
if (fRanges == 0L) {
//fRanges = new (this) Ranges(1, false);
fRanges = new (fMemoryManager) Ranges(1, false, fMemoryManager); // XMemory
}
fRanges->addElement(range);
return range;
}
Ranges* DOMDocumentImpl::getRanges() const
{
return fRanges;
}
void DOMDocumentImpl::removeRange(DOMRangeImpl* range)
{
if (fRanges != 0) {
Tinny Ng
committed
XMLSize_t sz = fRanges->size();
if (sz !=0) {
Tinny Ng
committed
for (XMLSize_t i =0; i<sz; i++) {
if (fRanges->elementAt(i) == range) {
fRanges->removeElementAt(i);
break;
}
}
}
}
}
/** Uses the kidOK lookup table to check whether the proposed
tree structure is legal.
????? It feels like there must be a more efficient solution,
but for the life of me I can't think what it would be.
*/
bool DOMDocumentImpl::isKidOK(DOMNode *parent, DOMNode *child)
{
static int kidOK[14];
if (kidOK[DOMNode::ATTRIBUTE_NODE] == 0)
{
kidOK[DOMNode::DOCUMENT_NODE] =
1 << DOMNode::ELEMENT_NODE |
1 << DOMNode::PROCESSING_INSTRUCTION_NODE |
1 << DOMNode::COMMENT_NODE |
kidOK[DOMNode::DOCUMENT_FRAGMENT_NODE] =
kidOK[DOMNode::ENTITY_NODE] =
kidOK[DOMNode::ENTITY_REFERENCE_NODE] =
kidOK[DOMNode::ELEMENT_NODE] =
1 << DOMNode::ELEMENT_NODE |
1 << DOMNode::PROCESSING_INSTRUCTION_NODE |
1 << DOMNode::COMMENT_NODE |
1 << DOMNode::TEXT_NODE |
1 << DOMNode::CDATA_SECTION_NODE |
kidOK[DOMNode::ATTRIBUTE_NODE] =
1 << DOMNode::TEXT_NODE |
1 << DOMNode::ENTITY_REFERENCE_NODE;
kidOK[DOMNode::PROCESSING_INSTRUCTION_NODE] =
kidOK[DOMNode::COMMENT_NODE] =
kidOK[DOMNode::TEXT_NODE] =
kidOK[DOMNode::CDATA_SECTION_NODE] =
kidOK[DOMNode::NOTATION_NODE] =
0;
David Abram Cargill
committed
}
int p=parent->getNodeType();
int ch = child->getNodeType();
return (kidOK[p] & 1<<ch) != 0;
}
void DOMDocumentImpl::changed()
{
fChanges++;
}
int DOMDocumentImpl::changes() const{
return fChanges;
David Abram Cargill
committed
}
//
// Delegation for functions inherited from DOMNode
//
David Abram Cargill
committed
DOMNode* DOMDocumentImpl::appendChild(DOMNode *newChild) {return insertBefore(newChild, 0); }
DOMNamedNodeMap* DOMDocumentImpl::getAttributes() const {return fNode.getAttributes (); }
DOMNodeList* DOMDocumentImpl::getChildNodes() const {return fParent.getChildNodes (); }
DOMNode* DOMDocumentImpl::getFirstChild() const {return fParent.getFirstChild (); }
DOMNode* DOMDocumentImpl::getLastChild() const {return fParent.getLastChild (); }
const XMLCh* DOMDocumentImpl::getLocalName() const {return fNode.getLocalName (); }
const XMLCh* DOMDocumentImpl::getNamespaceURI() const {return fNode.getNamespaceURI (); }
DOMNode* DOMDocumentImpl::getNextSibling() const {return fNode.getNextSibling (); }
const XMLCh* DOMDocumentImpl::getNodeValue() const {return fNode.getNodeValue (); }
const XMLCh* DOMDocumentImpl::getPrefix() const {return fNode.getPrefix (); }
DOMNode* DOMDocumentImpl::getParentNode() const {return fNode.getParentNode (); }
DOMNode* DOMDocumentImpl::getPreviousSibling() const {return fNode.getPreviousSibling (); }
bool DOMDocumentImpl::hasChildNodes() const {return fParent.hasChildNodes (); }
void DOMDocumentImpl::normalize() {fParent.normalize (); }
bool DOMDocumentImpl::isSupported(const XMLCh *feature, const XMLCh *version) const
David Abram Cargill
committed
{return fNode.isSupported (feature, version); }
void DOMDocumentImpl::setPrefix(const XMLCh *prefix) {fNode.setPrefix(prefix); }
bool DOMDocumentImpl::hasAttributes() const {return fNode.hasAttributes(); }
bool DOMDocumentImpl::isSameNode(const DOMNode* other) const {return fNode.isSameNode(other);}
bool DOMDocumentImpl::isEqualNode(const DOMNode* arg) const {return fParent.isEqualNode(arg);}
void* DOMDocumentImpl::setUserData(const XMLCh* key, void* data, DOMUserDataHandler* handler)
David Abram Cargill
committed
{return fNode.setUserData(key, data, handler); }
void* DOMDocumentImpl::getUserData(const XMLCh* key) const {return fNode.getUserData(key); }
short DOMDocumentImpl::compareTreePosition(const DOMNode* other) const {return fNode.compareTreePosition(other); }
const XMLCh* DOMDocumentImpl::getTextContent() const {return fNode.getTextContent(); }
void DOMDocumentImpl::setTextContent(const XMLCh* textContent){fNode.setTextContent(textContent); }
const XMLCh* DOMDocumentImpl::lookupNamespacePrefix(const XMLCh* namespaceURI, bool useDefault) const {return fNode.lookupNamespacePrefix(namespaceURI, useDefault); }
bool DOMDocumentImpl::isDefaultNamespace(const XMLCh* namespaceURI) const {return fNode.isDefaultNamespace(namespaceURI); }
const XMLCh* DOMDocumentImpl::lookupNamespaceURI(const XMLCh* prefix) const {return fNode.lookupNamespaceURI(prefix); }
DOMNode* DOMDocumentImpl::getInterface(const XMLCh* feature) {return fNode.getInterface(feature); }
//-----------------------------------------------------------------------
//
// Per Document Heap and Heap Helper functions
//
// revisit - this stuff should be a class of its own, rather than
// just lying around naked in DocumentImpl.
//
//-----------------------------------------------------------------------
XMLCh * DOMDocumentImpl::cloneString(const XMLCh *src)
{
if (!src) return 0;
size_t len = XMLString::stringLen(src);
len = (len + 1) * sizeof(XMLCh);
len = (len % 4) + len;
XMLCh *newStr = (XMLCh *)this->allocate(len);
XMLString::copyString(newStr, src);
return newStr;
}
const XMLCh * DOMDocumentImpl::getPooledString(const XMLCh *src)
{
if (!src) return 0;
else return this->fNamePool->getPooledString(src);
}
static const int kHeapAllocSize = 0x10000; // The chunk size to allocate from the
// system allocator.
static const int kMaxSubAllocationSize = 4096; // Any request for more bytes
// than this will be handled by
// allocating directly with system.
void * DOMDocumentImpl::allocate(size_t amount)
James David Berry
committed
{
// Align the request size so that suballocated blocks
// beyond this one will be maintained at the same alignment.
amount = XMLPlatformUtils::alignPointerForNewBlockAllocation(amount);
// If the request is for a largish block, hand it off to the system
// allocator. The block still must be linked into the list of
// allocated blocks so that it will be deleted when the time comes.
if (amount > kMaxSubAllocationSize)
{
James David Berry
committed
// The size of the header we add to our raw blocks
size_t sizeOfHeader = XMLPlatformUtils::alignPointerForNewBlockAllocation(sizeof(void *));
// Try to allocate the block
Neil Graham
committed
void* newBlock;
newBlock = fMemoryManager->allocate((sizeOfHeader + amount) * sizeof(char)); //new char[amount + sizeOfHeader];
James David Berry
committed
// Link it into the list beyond current block, as current block
// is still being subdivided. If there is no current block
// then track that we have no bytes to further divide.
if (fCurrentBlock)
{
*(void **)newBlock = *(void **)fCurrentBlock;
*(void **)fCurrentBlock = newBlock;
}
else
{
fCurrentBlock = newBlock;
fFreePtr = 0;
fFreeBytesRemaining = 0;
}
James David Berry
committed
void *retPtr = (char *)newBlock + sizeOfHeader;
return retPtr;
}
James David Berry
committed
// It's a normal (sub-allocatable) request.
// Are we out of room in our current block?
if (amount > fFreeBytesRemaining)
{
// Request doesn't fit in the current block.
James David Berry
committed
// The size of the header we add to our raw blocks
size_t sizeOfHeader = XMLPlatformUtils::alignPointerForNewBlockAllocation(sizeof(void *));
// Get a new block from the system allocator.
Neil Graham
committed
void* newBlock;
newBlock = fMemoryManager->allocate(kHeapAllocSize * sizeof(char)); //new char[kHeapAllocSize];
*(void **)newBlock = fCurrentBlock;
fCurrentBlock = newBlock;
James David Berry
committed
fFreePtr = (char *)newBlock + sizeOfHeader;
fFreeBytesRemaining = kHeapAllocSize - sizeOfHeader;
}
James David Berry
committed
// Subdivide the request off current block
void *retPtr = fFreePtr;
fFreePtr += amount;
fFreeBytesRemaining -= amount;
James David Berry
committed
return retPtr;
}
void DOMDocumentImpl::deleteHeap()
{
while (fCurrentBlock != 0)
{
void *nextBlock = *(void **)fCurrentBlock;
fMemoryManager->deallocate(fCurrentBlock); //delete [] (char*) fCurrentBlock;
fCurrentBlock = nextBlock;
}
}
James David Berry
committed
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
DOMNodeList *DOMDocumentImpl::getDeepNodeList(const DOMNode *rootNode, const XMLCh *tagName)
{
if(!fNodeListPool) {
fNodeListPool = new (this) DOMDeepNodeListPool<DOMDeepNodeListImpl>(109, false);
}
DOMDeepNodeListImpl* retList = fNodeListPool->getByKey(rootNode, tagName, 0);
if (!retList) {
int id = fNodeListPool->put((void*) rootNode, (XMLCh*) tagName, 0, new (this) DOMDeepNodeListImpl(rootNode, tagName));
retList = fNodeListPool->getById(id);
}
return retList;
}
DOMNodeList *DOMDocumentImpl::getDeepNodeList(const DOMNode *rootNode, //DOM Level 2
const XMLCh *namespaceURI,
const XMLCh *localName)
{
if(!fNodeListPool) {
fNodeListPool = new (this) DOMDeepNodeListPool<DOMDeepNodeListImpl>(109, false);
}
DOMDeepNodeListImpl* retList = fNodeListPool->getByKey(rootNode, localName, namespaceURI);
if (!retList) {
// the pool will adopt the DOMDeepNodeListImpl
int id = fNodeListPool->put((void*) rootNode, (XMLCh*) localName, (XMLCh*) namespaceURI, new (this) DOMDeepNodeListImpl(rootNode, namespaceURI, localName));
retList = fNodeListPool->getById(id);
}
return retList;
}
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
//Introduced in DOM Level 3
const XMLCh* DOMDocumentImpl::getActualEncoding() const {
return fActualEncoding;
}
void DOMDocumentImpl::setActualEncoding(const XMLCh* actualEncoding){
fActualEncoding = cloneString(actualEncoding);
}
const XMLCh* DOMDocumentImpl::getEncoding() const {
return fEncoding;
}
void DOMDocumentImpl::setEncoding(const XMLCh* encoding){
fEncoding = cloneString(encoding);
}
bool DOMDocumentImpl::getStandalone() const{
return fStandalone;
}
void DOMDocumentImpl::setStandalone(bool standalone){
fStandalone = standalone;
}
const XMLCh* DOMDocumentImpl::getVersion() const {
return fVersion;
}
void DOMDocumentImpl::setVersion(const XMLCh* version){
if ((version && *version) &&
!XMLString::equals(version, XMLUni::fgVersion1_0) &&
!XMLString::equals(version, XMLUni::fgVersion1_1))
throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0, getMemoryManager());
const XMLCh* DOMDocumentImpl::getDocumentURI() const
{
return fDocumentURI;
}
void DOMDocumentImpl::setDocumentURI(const XMLCh* documentURI){