| /* |
| * 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$ |
| */ |
| |
| #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 <xercesc/dom/DOM.hpp> for the entire |
| // DOM API, or xercesc/dom/DOM*.hpp for individual DOM classes, where the class |
| // name is substituded for the *. |
| // |
| |
| #include <xercesc/util/RefArrayOf.hpp> |
| #include <xercesc/util/RefStackOf.hpp> |
| #include <xercesc/util/RefHash2KeysTableOf.hpp> |
| #include <xercesc/util/StringPool.hpp> |
| #include <xercesc/util/KeyRefPair.hpp> |
| #include <xercesc/util/XMLChar.hpp> |
| #include <xercesc/dom/DOMDocument.hpp> |
| #include <xercesc/dom/DOMUserDataHandler.hpp> |
| #include <xercesc/dom/DOMMemoryManager.hpp> |
| #include "DOMNodeBase.hpp" |
| #include "DOMNodeImpl.hpp" |
| #include "DOMStringPool.hpp" |
| #include "DOMParentNode.hpp" |
| #include "DOMDeepNodeListPool.hpp" |
| |
| namespace XERCES_CPP_NAMESPACE { |
| |
| |
| 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<DOMRangeImpl> Ranges; |
| typedef RefVectorOf<DOMNodeIteratorImpl> NodeIterators; |
| typedef KeyRefPair<void, DOMUserDataHandler> DOMUserDataRecord; |
| typedef RefStackOf<DOMNode> DOMNodePtr; |
| |
| class CDOM_EXPORT DOMDocumentImpl: public XMemory, public DOMMemoryManager, public DOMDocument, |
| public HasDOMNodeImpl, public HasDOMParentImpl { |
| 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; |
| |
| // Add accessors for implementation bits. |
| DOMNODEIMPL_DECL; |
| DOMPARENTIMPL_DECL; |
| |
| 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); |
| // try to remove the block from the list of allocated memory |
| virtual void release(void* oldBuffer); |
| 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: |
| * <ul> |
| * <li>Checking strings to make sure that all characters are |
| * legal XML characters |
| * <li>Hierarchy checking such as allowed children, checks for |
| * cycles, etc. |
| * </ul> |
| * <p> |
| * Turning off error checking does <em>not</em> turn off the |
| * following checks: |
| * <ul> |
| * <li>Read only checks |
| * <li>Checks related to DOM events |
| * </ul> |
| */ |
| 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(const DOMNode *parent, const 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<DOMUserDataRecord, PtrHasher>* 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; |
| void* fCurrentSingletonBlock; |
| char* fFreePtr; |
| XMLSize_t fFreeBytesRemaining, |
| fHeapAllocSize; |
| |
| // To recycle the DOMNode pointer |
| RefArrayOf<DOMNodePtr>* fRecycleNodePtr; |
| |
| // To recycle DOMBuffer pointer |
| RefStackOf<DOMBuffer>* fRecycleBufferPtr; |
| |
| // Pool of DOMNodeList for getElementsByTagName |
| DOMDeepNodeListPool<DOMDeepNodeListImpl>* 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; |
| XMLSize_t n = XMLString::stringLen(in); |
| |
| DOMStringPoolEntry **pspe; |
| DOMStringPoolEntry *spe; |
| |
| XMLSize_t inHash = XMLString::hash(in, fNameTableSize); |
| pspe = &fNameTable[inHash]; |
| while (*pspe != 0) |
| { |
| if ((*pspe)->fLength == n && 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) + n*sizeof(XMLCh); |
| *pspe = spe = (DOMStringPoolEntry *)allocate(sizeToAllocate); |
| spe->fLength = n; |
| 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 ((*pspe)->fLength == n && 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->fLength = n; |
| 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; |
| } |
| |
| } |
| |
| // --------------------------------------------------------------------------- |
| // |
| // Operator new. Global overloaded version, lets any object be allocated on |
| // the heap owned by a document. |
| // |
| // --------------------------------------------------------------------------- |
| inline void * operator new(size_t amt, xercesc::DOMDocumentImpl *doc, xercesc::DOMMemoryManager::NodeObjectType type) |
| { |
| void *p = doc->allocate(amt, type); |
| return p; |
| } |
| |
| inline void * operator new(size_t amt, xercesc::DOMDocument *doc, xercesc::DOMMemoryManager::NodeObjectType type) |
| { |
| xercesc::DOMMemoryManager* mgr=(xercesc::DOMMemoryManager*)doc->getFeature(xercesc::XMLUni::fgXercescInterfaceDOMMemoryManager,0); |
| void* p=0; |
| if(mgr) |
| p = mgr->allocate(amt, type); |
| return p; |
| } |
| |
| inline void * operator new(size_t amt, xercesc::DOMDocumentImpl *doc) |
| { |
| void* p = doc->allocate(amt); |
| return p; |
| } |
| |
| inline void * operator new(size_t amt, xercesc::DOMDocument *doc) |
| { |
| xercesc::DOMMemoryManager* mgr=(xercesc::DOMMemoryManager*)doc->getFeature(xercesc::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*/, xercesc::DOMDocumentImpl * /*doc*/, xercesc::DOMMemoryManager::NodeObjectType /*type*/) |
| { |
| return; |
| } |
| inline void operator delete(void* /*ptr*/, xercesc::DOMDocument * /*doc*/, xercesc::DOMMemoryManager::NodeObjectType /*type*/) |
| { |
| return; |
| } |
| |
| inline void operator delete(void* /*ptr*/, xercesc::DOMDocumentImpl * /*doc*/) |
| { |
| return; |
| } |
| inline void operator delete(void* /*ptr*/, xercesc::DOMDocument * /*doc*/) |
| { |
| return; |
| } |
| #endif |
| |
| #endif |