From c67e84151da71c6042fc57a6bb7a13998f2cab75 Mon Sep 17 00:00:00 2001 From: Tinny Ng <tng@apache.org> Date: Thu, 16 Jan 2003 19:10:41 +0000 Subject: [PATCH] DOM Fix: iterator should be updated when a node is removed from the dom tree git-svn-id: https://svn.apache.org/repos/asf/xerces/c/trunk@174636 13f79535-47bb-0310-9956-ffa450edef68 --- src/xercesc/dom/impl/DOMDocumentImpl.cpp | 44 +++++++++++++++++++- src/xercesc/dom/impl/DOMDocumentImpl.hpp | 4 ++ src/xercesc/dom/impl/DOMNodeIteratorImpl.cpp | 40 +++++++++--------- src/xercesc/dom/impl/DOMNodeIteratorImpl.hpp | 9 ++-- src/xercesc/dom/impl/DOMParentNode.cpp | 15 ++++++- 5 files changed, 85 insertions(+), 27 deletions(-) diff --git a/src/xercesc/dom/impl/DOMDocumentImpl.cpp b/src/xercesc/dom/impl/DOMDocumentImpl.cpp index 6dd541dd0..2b49cd462 100644 --- a/src/xercesc/dom/impl/DOMDocumentImpl.cpp +++ b/src/xercesc/dom/impl/DOMDocumentImpl.cpp @@ -118,6 +118,7 @@ DOMDocumentImpl::DOMDocumentImpl() fNamePool(0), fNodeIDMap(0), fRanges(0), + fNodeIterators(0), fChanges(0), fNodeListPool(0), fActualEncoding(0), @@ -148,6 +149,7 @@ DOMDocumentImpl::DOMDocumentImpl(const XMLCh *fNamespaceURI, fNamePool(0), fNodeIDMap(0), fRanges(0), + fNodeIterators(0), fChanges(0), fNodeListPool(0), fActualEncoding(0), @@ -207,6 +209,9 @@ DOMDocumentImpl::~DOMDocumentImpl() if (fRanges) fRanges->cleanup(); + if (fNodeIterators) + fNodeIterators->cleanup(); + if (fUserDataTable) fUserDataTable->cleanup(); @@ -386,12 +391,49 @@ DOMText *DOMDocumentImpl::createTextNode(const XMLCh *data) DOMNodeIterator* DOMDocumentImpl::createNodeIterator ( DOMNode *root, unsigned long whatToShow, DOMNodeFilter* filter, bool entityReferenceExpansion) { - return new (this) DOMNodeIteratorImpl(root, whatToShow, filter, entityReferenceExpansion); + if (!root) { + throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0); + return 0; + } + + DOMNodeIteratorImpl* nodeIterator = new (this) DOMNodeIteratorImpl(this, root, whatToShow, filter, entityReferenceExpansion); + + if (fNodeIterators == 0L) { + fNodeIterators = new (this) NodeIterators(1, false); + } + 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; + } + } + } + } +} + DOMTreeWalker* DOMDocumentImpl::createTreeWalker (DOMNode *root, unsigned long whatToShow, DOMNodeFilter* filter, bool entityReferenceExpansion) { + if (!root) { + throw DOMException(DOMException::NOT_SUPPORTED_ERR, 0); + return 0; + } + return new (this) DOMTreeWalkerImpl(root, whatToShow, filter, entityReferenceExpansion); } diff --git a/src/xercesc/dom/impl/DOMDocumentImpl.hpp b/src/xercesc/dom/impl/DOMDocumentImpl.hpp index 0f0b95a9a..d052077ed 100644 --- a/src/xercesc/dom/impl/DOMDocumentImpl.hpp +++ b/src/xercesc/dom/impl/DOMDocumentImpl.hpp @@ -112,6 +112,7 @@ class DOMStringPool; class DOMBuffer; typedef RefVectorOf<DOMRangeImpl> Ranges; +typedef RefVectorOf<DOMNodeIteratorImpl> NodeIterators; typedef KeyRefPair<void, DOMUserDataHandler> DOMUserDataRecord; typedef RefHashTableOf<DOMUserDataRecord> DOMNodeUserDataTable; typedef RefStackOf<DOMNode> DOMNodePtr; @@ -190,7 +191,9 @@ public: 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 // @@ -367,6 +370,7 @@ private: DOMStringPool* fNamePool; Ranges* fRanges; + NodeIterators* fNodeIterators; int fChanges; bool errorChecking; // Bypass error checking. diff --git a/src/xercesc/dom/impl/DOMNodeIteratorImpl.cpp b/src/xercesc/dom/impl/DOMNodeIteratorImpl.cpp index cd2e8311b..bcd8fb411 100644 --- a/src/xercesc/dom/impl/DOMNodeIteratorImpl.cpp +++ b/src/xercesc/dom/impl/DOMNodeIteratorImpl.cpp @@ -75,25 +75,7 @@ XERCES_CPP_NAMESPACE_BEGIN // Construction/Destruction ////////////////////////////////////////////////////////////////////// -DOMNodeIteratorImpl::DOMNodeIteratorImpl () -: fDetached(false), - fNodeFilter(0) -{ -} - -DOMNodeIteratorImpl::~DOMNodeIteratorImpl () -{ - fDetached = false; -} - - -void DOMNodeIteratorImpl::detach () -{ - fDetached = true; -} - - -DOMNodeIteratorImpl::DOMNodeIteratorImpl ( +DOMNodeIteratorImpl::DOMNodeIteratorImpl (DOMDocument* doc, DOMNode* root, unsigned long whatToShow, DOMNodeFilter* nodeFilter, @@ -104,7 +86,8 @@ DOMNodeIteratorImpl::DOMNodeIteratorImpl ( fWhatToShow(whatToShow), fNodeFilter(nodeFilter), fForward(true), - fExpandEntityReferences(expandEntityRef) + fExpandEntityReferences(expandEntityRef), + fDocument(doc) { } @@ -117,7 +100,8 @@ DOMNodeIteratorImpl::DOMNodeIteratorImpl ( const DOMNodeIteratorImpl& toCopy) fWhatToShow(toCopy.fWhatToShow), fNodeFilter(toCopy.fNodeFilter), fForward(toCopy.fForward), - fExpandEntityReferences(toCopy.fExpandEntityReferences) + fExpandEntityReferences(toCopy.fExpandEntityReferences), + fDocument(toCopy.fDocument) { } @@ -130,9 +114,23 @@ DOMNodeIteratorImpl& DOMNodeIteratorImpl::operator= (const DOMNodeIteratorImpl& fForward = other.fForward; fDetached = other.fDetached; fExpandEntityReferences = other.fExpandEntityReferences; + fDocument = other.fDocument; return *this; } +DOMNodeIteratorImpl::~DOMNodeIteratorImpl () +{ + fDetached = false; +} + + +void DOMNodeIteratorImpl::detach () +{ + fDetached = true; + ((DOMDocumentImpl *)fDocument)->removeNodeIterator(this); +} + + DOMNode* DOMNodeIteratorImpl::getRoot() { return fRoot; } diff --git a/src/xercesc/dom/impl/DOMNodeIteratorImpl.hpp b/src/xercesc/dom/impl/DOMNodeIteratorImpl.hpp index 255a8410f..578b229a6 100644 --- a/src/xercesc/dom/impl/DOMNodeIteratorImpl.hpp +++ b/src/xercesc/dom/impl/DOMNodeIteratorImpl.hpp @@ -88,6 +88,9 @@ class CDOM_EXPORT DOMNodeIteratorImpl : public DOMNodeIterator { // The root. DOMNode* fRoot; + // The Document used to create this iterator + DOMDocument* fDocument; + // The whatToShow mask. unsigned long fWhatToShow; @@ -120,12 +123,10 @@ class CDOM_EXPORT DOMNodeIteratorImpl : public DOMNodeIterator { // </pre> bool fForward; - protected: - DOMNodeIteratorImpl (); - public: virtual ~DOMNodeIteratorImpl (); DOMNodeIteratorImpl ( + DOMDocument* fDocument, DOMNode* root, unsigned long whatToShow, DOMNodeFilter* nodeFilter, @@ -145,12 +146,12 @@ class CDOM_EXPORT DOMNodeIteratorImpl : public DOMNodeIterator { virtual void detach (); virtual void release(); + void removeNode (DOMNode* node); private: DOMNode* matchNodeOrParent (DOMNode* node); DOMNode* nextNode (DOMNode* node, bool visitChildren); DOMNode* previousNode (DOMNode* node); - void removeNode (DOMNode* node); bool acceptNode (DOMNode* node); }; diff --git a/src/xercesc/dom/impl/DOMParentNode.cpp b/src/xercesc/dom/impl/DOMParentNode.cpp index bd3999137..f87c65c46 100644 --- a/src/xercesc/dom/impl/DOMParentNode.cpp +++ b/src/xercesc/dom/impl/DOMParentNode.cpp @@ -65,6 +65,7 @@ #include "DOMDocumentImpl.hpp" #include "DOMNodeListImpl.hpp" #include "DOMRangeImpl.hpp" +#include "DOMNodeIteratorImpl.hpp" #include "DOMParentNode.hpp" #include "DOMCasts.hpp" @@ -310,8 +311,20 @@ DOMNode *DOMParentNode::removeChild(DOMNode *oldChild) if (oldChild != 0 && oldChild->getParentNode() != castToNode(this)) throw DOMException(DOMException::NOT_FOUND_ERR, 0); - //fix other ranges for change before deleting the node if (this->getOwnerDocument() != 0 ) { + //notify iterators + NodeIterators* nodeIterators = ((DOMDocumentImpl *)this->getOwnerDocument())->getNodeIterators(); + if (nodeIterators != 0) { + XMLSize_t sz = nodeIterators->size(); + if (sz != 0) { + for (XMLSize_t i =0; i<sz; i++) { + if (nodeIterators->elementAt(i) != 0) + nodeIterators->elementAt(i)->removeNode(oldChild); + } + } + } + + //fix other ranges for change before deleting the node Ranges* ranges = ((DOMDocumentImpl *)this->getOwnerDocument())->getRanges(); if (ranges != 0) { XMLSize_t sz = ranges->size(); -- GitLab