/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * $Id: DOMDocumentImpl.hpp 679340 2008-07-24 10:28:29Z borisk $ */ #if !defined(XERCESC_INCLUDE_GUARD_DOMDOCUMENTIMPL_HPP) #define XERCESC_INCLUDE_GUARD_DOMDOCUMENTIMPL_HPP // // This file is part of the internal implementation of the C++ XML DOM. // It should NOT be included or used directly by application programs. // // Applications should include the file for the entire // DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class // name is substituded for the *. // #include #include #include #include #include #include #include #include #include #include "DOMNodeImpl.hpp" #include "DOMStringPool.hpp" #include "DOMParentNode.hpp" #include "DOMDeepNodeListPool.hpp" XERCES_CPP_NAMESPACE_BEGIN class DOMAttrImpl; class DOMCDATASectionImpl; class DOMCommentImpl; class DOMConfiguration; class DOMDeepNodeListImpl; class DOMDocumentFragmentImpl; class DOMDocumentTypeImpl; class DOMElementImpl; class DOMEntityImpl; class DOMEntityReferenceImpl; class DOMNotationImpl; class DOMProcessingInstructionImpl; class DOMTextImpl; class DOMNodeIteratorImpl; class DOMNormalizer; class DOMTreeWalkerImpl; class DOMNodeFilter; class DOMNodeFilterImpl; class DOMImplementation; class DOMNodeIDMap; class DOMRangeImpl; class DOMBuffer; class MemoryManager; class XPathNSResolver; class XPathExpression; typedef RefVectorOf Ranges; typedef RefVectorOf NodeIterators; typedef KeyRefPair DOMUserDataRecord; typedef RefStackOf DOMNodePtr; class CDOM_EXPORT DOMDocumentImpl: public XMemory, public DOMMemoryManager, public DOMDocument { public: // ----------------------------------------------------------------------- // data // ----------------------------------------------------------------------- DOMNodeImpl fNode; // Implements common node functionality. DOMParentNode fParent; // Implements common parent node functionality DOMNodeIDMap* fNodeIDMap; // for use by GetElementsById(). public: DOMDocumentImpl(DOMImplementation* domImpl, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); DOMDocumentImpl(const XMLCh* namespaceURI, //DOM Level 2 const XMLCh* qualifiedName, DOMDocumentType* doctype, DOMImplementation* domImpl, MemoryManager* const manager = XMLPlatformUtils::fgMemoryManager); virtual ~DOMDocumentImpl(); void setDocumentType(DOMDocumentType *doctype); public: // Add all functions that are pure virtual in DOMNODE DOMNODE_FUNCTIONS; public: // Add all functions that are pure virtual in DOMDocument virtual DOMAttr* createAttribute(const XMLCh *name); virtual DOMCDATASection* createCDATASection(const XMLCh *data); virtual DOMComment* createComment(const XMLCh *data); virtual DOMDocumentFragment* createDocumentFragment(); virtual DOMDocumentType* createDocumentType(const XMLCh *name); virtual DOMDocumentType* createDocumentType(const XMLCh *qName, const XMLCh *publicId, const XMLCh *systemId); virtual DOMElement* createElement(const XMLCh * tagName); virtual DOMElement* createElementNoCheck(const XMLCh *tagName); virtual DOMEntity* createEntity(const XMLCh * name); virtual DOMEntityReference* createEntityReference(const XMLCh * name); virtual DOMNotation* createNotation(const XMLCh * name); virtual DOMProcessingInstruction* createProcessingInstruction(const XMLCh * target, const XMLCh * data); virtual DOMText* createTextNode(const XMLCh * data); virtual DOMDocumentType* getDoctype() const; virtual DOMElement* getDocumentElement() const; virtual DOMNodeList* getElementsByTagName(const XMLCh * tagname) const; virtual DOMImplementation* getImplementation() const; bool isXMLName(const XMLCh * s); virtual DOMNodeIterator* createNodeIterator(DOMNode *root, DOMNodeFilter::ShowType whatToShow, DOMNodeFilter* filter, bool entityReferenceExpansion); virtual DOMTreeWalker* createTreeWalker(DOMNode *root, DOMNodeFilter::ShowType whatToShow, DOMNodeFilter* filter, bool entityReferenceExpansion); virtual DOMRange* createRange(); virtual Ranges* getRanges() const; //non-standard api virtual NodeIterators* getNodeIterators() const; //non-standard api virtual void removeRange(DOMRangeImpl* range); //non-standard api virtual void removeNodeIterator(DOMNodeIteratorImpl* nodeIterator); //non-standard api virtual DOMXPathExpression* createExpression(const XMLCh *expression, const DOMXPathNSResolver *resolver); virtual DOMXPathNSResolver* createNSResolver(const DOMNode *nodeResolver); virtual DOMXPathResult* evaluate(const XMLCh *expression, const DOMNode *contextNode, const DOMXPathNSResolver *resolver, DOMXPathResult::ResultType type, DOMXPathResult* result); // Extension to be called by the Parser DOMEntityReference* createEntityReferenceByParser(const XMLCh * name); // Add all functions that are pure virtual in DOMMemoryManager virtual XMLSize_t getMemoryAllocationBlockSize() const; virtual void setMemoryAllocationBlockSize(XMLSize_t size); virtual void* allocate(XMLSize_t amount); virtual void* allocate(XMLSize_t amount, DOMMemoryManager::NodeObjectType type); virtual void release(DOMNode* object, DOMMemoryManager::NodeObjectType type); virtual XMLCh* cloneString(const XMLCh *src); // // Functions to keep track of document mutations, so that node list chached // information can be invalidated. One global changes counter per document. // virtual void changed(); virtual int changes() const; /** * Sets whether the DOM implementation performs error checking * upon operations. Turning off error checking only affects * the following DOM checks: *
    *
  • Checking strings to make sure that all characters are * legal XML characters *
  • Hierarchy checking such as allowed children, checks for * cycles, etc. *
*

* Turning off error checking does not turn off the * following checks: *

    *
  • Read only checks *
  • Checks related to DOM events *
*/ inline void setErrorChecking(bool check) { errorChecking = check; } /** * Returns true if the DOM implementation performs error checking. */ inline bool getErrorChecking() const { return errorChecking; } //Introduced in DOM Level 2 virtual DOMNode* importNode(const DOMNode *source, bool deep); virtual DOMElement* createElementNS(const XMLCh *namespaceURI, const XMLCh *qualifiedName); virtual DOMElement* createElementNS(const XMLCh *namespaceURI, const XMLCh *qualifiedName, const XMLFileLoc lineNo, const XMLFileLoc columnNo); virtual DOMAttr* createAttributeNS(const XMLCh *namespaceURI, const XMLCh *qualifiedName); virtual DOMNodeList* getElementsByTagNameNS(const XMLCh *namespaceURI, const XMLCh *localName) const; virtual DOMElement* getElementById(const XMLCh *elementId) const; //Introduced in DOM Level 3 virtual const XMLCh* getInputEncoding() const; virtual const XMLCh* getXmlEncoding() const; virtual bool getXmlStandalone() const; virtual void setXmlStandalone(bool standalone); virtual const XMLCh* getXmlVersion() const; virtual void setXmlVersion(const XMLCh* version); virtual const XMLCh* getDocumentURI() const; virtual void setDocumentURI(const XMLCh* documentURI); virtual bool getStrictErrorChecking() const; virtual void setStrictErrorChecking(bool strictErrorChecking); virtual DOMNode* adoptNode(DOMNode* source); virtual void normalizeDocument(); virtual DOMConfiguration* getDOMConfig() const; void setInputEncoding(const XMLCh* actualEncoding); void setXmlEncoding(const XMLCh* encoding); // helper functions to prevent storing userdata pointers on every node. void* setUserData(DOMNodeImpl* n, const XMLCh* key, void* data, DOMUserDataHandler* handler); void* getUserData(const DOMNodeImpl* n, const XMLCh* key) const; void callUserDataHandlers(const DOMNodeImpl* n, DOMUserDataHandler::DOMOperationType operation, const DOMNode* src, DOMNode* dst) const; void transferUserData(DOMNodeImpl* n1, DOMNodeImpl* n2); DOMNode* renameNode(DOMNode* n, const XMLCh* namespaceURI, const XMLCh* name); //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". static int indexofQualifiedName(const XMLCh * qName); static bool isKidOK(DOMNode *parent, DOMNode *child); inline DOMNodeIDMap* getNodeIDMap() {return fNodeIDMap;}; // // Memory Management Functions. All memory is allocated by and owned by // a document, and is not recovered until the // document itself is deleted. // const XMLCh* getPooledString(const XMLCh*); const XMLCh* getPooledNString(const XMLCh*, XMLSize_t); void deleteHeap(); void releaseDocNotifyUserData(DOMNode* object); void releaseBuffer(DOMBuffer* buffer); DOMBuffer* popBuffer(XMLSize_t nMinSize); MemoryManager* getMemoryManager() const; // Factory methods for getting/creating node lists. // Because nothing is ever deleted, the implementation caches and recycles // previously used instances of DOMDeepNodeList // DOMNodeList* getDeepNodeList(const DOMNode *rootNode, const XMLCh *tagName); DOMNodeList* getDeepNodeList(const DOMNode *rootNode, //DOM Level 2 const XMLCh *namespaceURI, const XMLCh *localName); protected: //Internal helper functions virtual DOMNode* importNode(const DOMNode *source, bool deep, bool cloningNode); private: // ----------------------------------------------------------------------- // Unimplemented constructors and operators // ----------------------------------------------------------------------- DOMDocumentImpl(const DOMDocumentImpl &); DOMDocumentImpl & operator = (const DOMDocumentImpl &); protected: // ----------------------------------------------------------------------- // data // ----------------------------------------------------------------------- // New data introduced in DOM Level 3 const XMLCh* fInputEncoding; const XMLCh* fXmlEncoding; bool fXmlStandalone; const XMLCh* fXmlVersion; const XMLCh* fDocumentURI; DOMConfiguration* fDOMConfiguration; XMLStringPool fUserDataTableKeys; RefHash2KeysTableOf* fUserDataTable; // Per-Document heap Variables. // The heap consists of one or more biggish blocks which are // sub-allocated for individual allocations of nodes, strings, etc. // The big blocks form a linked list, allowing them to be located for deletion. // // There is no provision for deleting suballocated blocks, other than // deleting the entire heap when the document is deleted. // // There is no header on individual sub-allocated blocks. // The header on big blocks consists only of a single back pointer to // the previously allocated big block (our linked list of big blocks) // // // revisit - this heap should be encapsulated into its own // class, rather than hanging naked on Document. // void* fCurrentBlock; char* fFreePtr; XMLSize_t fFreeBytesRemaining, fHeapAllocSize; // To recycle the DOMNode pointer RefArrayOf* fRecycleNodePtr; // To recycle DOMBuffer pointer RefStackOf* fRecycleBufferPtr; // Pool of DOMNodeList for getElementsByTagName DOMDeepNodeListPool* fNodeListPool; // Other data DOMDocumentType* fDocType; DOMElement* fDocElement; DOMStringPoolEntry** fNameTable; XMLSize_t fNameTableSize; DOMNormalizer* fNormalizer; Ranges* fRanges; NodeIterators* fNodeIterators; MemoryManager* fMemoryManager; // configurable memory manager DOMImplementation* fDOMImplementation; int fChanges; bool errorChecking; // Bypass error checking. }; inline MemoryManager* DOMDocumentImpl::getMemoryManager() const { return fMemoryManager; } inline const XMLCh* DOMDocumentImpl::getPooledString(const XMLCh *in) { if (in == 0) return 0; DOMStringPoolEntry **pspe; DOMStringPoolEntry *spe; XMLSize_t inHash = XMLString::hash(in, fNameTableSize); pspe = &fNameTable[inHash]; while (*pspe != 0) { if (XMLString::equals((*pspe)->fString, in)) return (*pspe)->fString; pspe = &((*pspe)->fNext); } // This string hasn't been seen before. Add it to the pool. // // Compute size to allocate. Note that there's 1 char of string // declared in the struct, so we don't need to add one again to // account for the trailing null. // XMLSize_t sizeToAllocate = sizeof(DOMStringPoolEntry) + XMLString::stringLen(in)*sizeof(XMLCh); *pspe = spe = (DOMStringPoolEntry *)allocate(sizeToAllocate); spe->fNext = 0; XMLString::copyString((XMLCh*)spe->fString, in); return spe->fString; } inline const XMLCh* DOMDocumentImpl:: getPooledNString(const XMLCh *in, XMLSize_t n) { if (in == 0) return 0; DOMStringPoolEntry **pspe; DOMStringPoolEntry *spe; XMLSize_t inHash = XMLString::hashN(in, n, fNameTableSize); pspe = &fNameTable[inHash]; while (*pspe != 0) { if (XMLString::equalsN((*pspe)->fString, in, n)) return (*pspe)->fString; pspe = &((*pspe)->fNext); } // This string hasn't been seen before. Add it to the pool. // // Compute size to allocate. Note that there's 1 char of string // declared in the struct, so we don't need to add one again to // account for the trailing null. // XMLSize_t sizeToAllocate = sizeof(DOMStringPoolEntry) + n*sizeof(XMLCh); *pspe = spe = (DOMStringPoolEntry *)allocate(sizeToAllocate); spe->fNext = 0; XMLString::copyNString((XMLCh*)spe->fString, in, n); return spe->fString; } inline int DOMDocumentImpl::indexofQualifiedName(const XMLCh* name) { int i = 0; int colon = -1; int colon_count = 0; for (; *name != 0; ++i, ++name) { if (*name == chColon) { ++colon_count; colon = i; } } if (i == 0 || colon == 0 || colon == (i - 1) || colon_count > 1) return -1; return colon != -1 ? colon : 0; } XERCES_CPP_NAMESPACE_END // --------------------------------------------------------------------------- // // Operator new. Global overloaded version, lets any object be allocated on // the heap owned by a document. // // --------------------------------------------------------------------------- inline void * operator new(size_t amt, XERCES_CPP_NAMESPACE_QUALIFIER DOMDocumentImpl *doc, XERCES_CPP_NAMESPACE_QUALIFIER DOMMemoryManager::NodeObjectType type) { void *p = doc->allocate(amt, type); return p; } inline void * operator new(size_t amt, XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *doc, XERCES_CPP_NAMESPACE_QUALIFIER DOMMemoryManager::NodeObjectType type) { XERCES_CPP_NAMESPACE_QUALIFIER DOMMemoryManager* mgr=(XERCES_CPP_NAMESPACE_QUALIFIER DOMMemoryManager*)doc->getFeature(XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgXercescInterfaceDOMMemoryManager,0); void* p=0; if(mgr) p = mgr->allocate(amt, type); return p; } inline void * operator new(size_t amt, XERCES_CPP_NAMESPACE_QUALIFIER DOMDocumentImpl *doc) { void* p = doc->allocate(amt); return p; } inline void * operator new(size_t amt, XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument *doc) { XERCES_CPP_NAMESPACE_QUALIFIER DOMMemoryManager* mgr=(XERCES_CPP_NAMESPACE_QUALIFIER DOMMemoryManager*)doc->getFeature(XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgXercescInterfaceDOMMemoryManager,0); void* p=0; if(mgr) p = mgr->allocate(amt); return p; } // --------------------------------------------------------------------------- // For DOM: // Bypass compiler warning: // no matching operator delete found; memory will not be freed if initialization throws an exception // --------------------------------------------------------------------------- #if !defined(XERCES_NO_MATCHING_DELETE_OPERATOR) inline void operator delete(void* /*ptr*/, XERCES_CPP_NAMESPACE_QUALIFIER DOMDocumentImpl * /*doc*/, XERCES_CPP_NAMESPACE_QUALIFIER DOMMemoryManager::NodeObjectType /*type*/) { return; } inline void operator delete(void* /*ptr*/, XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument * /*doc*/, XERCES_CPP_NAMESPACE_QUALIFIER DOMMemoryManager::NodeObjectType /*type*/) { return; } inline void operator delete(void* /*ptr*/, XERCES_CPP_NAMESPACE_QUALIFIER DOMDocumentImpl * /*doc*/) { return; } inline void operator delete(void* /*ptr*/, XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument * /*doc*/) { return; } #endif #endif