DOMNode * DOMChildNode::getParentNode(const DOMNode *thisNode) const { // if we have an owner, ownerNode is our parent, otherwise it's // our ownerDocument and we don't have a parent DOMNodeImpl *thisNodeImpl = castToNodeImpl(thisNode); return thisNodeImpl->isOwned() ? thisNodeImpl->fOwnerNode : 0; }
// // setNamedItem() Put the item into the NamedNodeList by name. // If an item with the same name already was // in the list, replace it. Return the old // item, if there was one. // Caller is responsible for arranging for // deletion of the old item if its ref count is // zero. // DOMNode * DOMNamedNodeMapImpl::setNamedItem(DOMNode * arg) { DOMDocument *doc = fOwnerNode->getOwnerDocument(); DOMNodeImpl *argImpl = castToNodeImpl(arg); if(argImpl->getOwnerDocument() != doc) throw DOMException(DOMException::WRONG_DOCUMENT_ERR,0, GetDOMNamedNodeMapMemoryManager); if (this->readOnly()) throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager); if ((arg->getNodeType() == DOMNode::ATTRIBUTE_NODE) && argImpl->isOwned() && (argImpl->fOwnerNode != fOwnerNode)) throw DOMException(DOMException::INUSE_ATTRIBUTE_ERR,0, GetDOMNamedNodeMapMemoryManager); argImpl->fOwnerNode = fOwnerNode; argImpl->isOwned(true); const XMLCh* name=arg->getNodeName(); unsigned int hash=XMLString::hash(name,MAP_SIZE); if(fBuckets[hash]==0) fBuckets[hash] = new (doc) DOMNodeVector(doc, 3); int i = 0; int size = fBuckets[hash]->size(); for (i = 0; i < size; ++i) { DOMNode *n=fBuckets[hash]->elementAt(i); if(XMLString::equals(name,n->getNodeName())) { fBuckets[hash]->setElementAt(arg,i); castToNodeImpl(n)->fOwnerNode = fOwnerNode->getOwnerDocument(); castToNodeImpl(n)->isOwned(false); return n; } } fBuckets[hash]->addElement(arg); return 0; }
// // setNamedItemNS() Put the item into the NamedNodeList by name. // If an item with the same name already was // in the list, replace it. Return the old // item, if there was one. // Caller is responsible for arranging for // deletion of the old item if its ref count is // zero. // DOMNode * DOMNamedNodeMapImpl::setNamedItemNS(DOMNode *arg) { DOMDocument *doc = fOwnerNode->getOwnerDocument(); DOMNodeImpl *argImpl = castToNodeImpl(arg); if (argImpl->getOwnerDocument() != doc) throw DOMException(DOMException::WRONG_DOCUMENT_ERR,0, GetDOMNamedNodeMapMemoryManager); if (this->readOnly()) throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager); if (argImpl->isOwned()) throw DOMException(DOMException::INUSE_ATTRIBUTE_ERR,0, GetDOMNamedNodeMapMemoryManager); argImpl->fOwnerNode = fOwnerNode; argImpl->isOwned(true); const XMLCh* namespaceURI=arg->getNamespaceURI(); const XMLCh* localName=arg->getLocalName(); // the map is indexed using the full name of nodes; to search given a namespace and a local name // we have to do a linear search for (int index = 0; index < MAP_SIZE; index++) { if(fBuckets[index]==0) continue; int i = 0; int size = fBuckets[index]->size(); for (i = 0; i < size; ++i) { DOMNode *n=fBuckets[index]->elementAt(i); const XMLCh * nNamespaceURI = n->getNamespaceURI(); const XMLCh * nLocalName = n->getLocalName(); if (!XMLString::equals(nNamespaceURI, namespaceURI)) //URI not match continue; else { if (XMLString::equals(localName, nLocalName) || (nLocalName == 0 && XMLString::equals(localName, n->getNodeName()))) { fBuckets[index]->setElementAt(arg,i); castToNodeImpl(n)->fOwnerNode = fOwnerNode->getOwnerDocument(); castToNodeImpl(n)->isOwned(false); return n; } } } } // if not found, add it using the full name as key return setNamedItem(arg); }
// This only makes a shallow copy, cloneChildren must also be called for a // deep clone DOMNodeImpl::DOMNodeImpl(const DOMNodeImpl &other) { this->flags = other.flags; this->isReadOnly(false); // Need to break the association w/ original parent this->fOwnerNode = other.getOwnerDocument(); this->isOwned(false); }
DOMNode *DOMAttrMapImpl::setNamedItem(DOMNode *arg) { if (arg->getNodeType() != DOMNode::ATTRIBUTE_NODE) throw DOMException(DOMException::HIERARCHY_REQUEST_ERR, 0, GetDOMNamedNodeMapMemoryManager); DOMDocument *doc = fOwnerNode->getOwnerDocument(); DOMNodeImpl *argImpl = castToNodeImpl(arg); if(argImpl->getOwnerDocument() != doc) throw DOMException(DOMException::WRONG_DOCUMENT_ERR, 0, GetDOMNamedNodeMapMemoryManager); if (this->readOnly()) throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager); if ((arg->getNodeType() == DOMNode::ATTRIBUTE_NODE) && argImpl->isOwned() && (argImpl->fOwnerNode != fOwnerNode)) throw DOMException(DOMException::INUSE_ATTRIBUTE_ERR,0, GetDOMNamedNodeMapMemoryManager); argImpl->fOwnerNode = fOwnerNode; argImpl->isOwned(true); int i=findNamePoint(arg->getNodeName()); DOMNode * previous=0; if(i>=0) { previous = fNodes->elementAt(i); fNodes->setElementAt(arg,i); } else { i=-1-i; // Insert point (may be end of list) if(0==fNodes) { fNodes=new (doc) DOMNodeVector(doc); } fNodes->insertElementAt(arg,i); } if (previous != 0) { castToNodeImpl(previous)->fOwnerNode = fOwnerNode->getOwnerDocument(); castToNodeImpl(previous)->isOwned(false); } return previous; }
DOMNode *DOMParentNode::insertBefore(DOMNode *newChild, DOMNode *refChild) { //not really in the specs, but better than nothing if(newChild==NULL) throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0, GetDOMParentNodeMemoryManager); DOMNodeImpl *thisNodeImpl = castToNodeImpl(this); if (thisNodeImpl->isReadOnly()) throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMParentNodeMemoryManager); if (newChild->getOwnerDocument() != fOwnerDocument) throw DOMException(DOMException::WRONG_DOCUMENT_ERR, 0, GetDOMParentNodeMemoryManager); // Prevent cycles in the tree //only need to do this if the node has children if(newChild->hasChildNodes()) { bool treeSafe=true; for(DOMNode *a=castToNode(this)->getParentNode(); treeSafe && a!=0; a=a->getParentNode()) treeSafe=(newChild!=a); if(!treeSafe) throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0, GetDOMParentNodeMemoryManager); } // refChild must in fact be a child of this node (or 0) if (refChild!=0 && refChild->getParentNode() != castToNode(this)) throw DOMException(DOMException::NOT_FOUND_ERR,0, GetDOMParentNodeMemoryManager); // if the new node has to be placed before itself, we don't have to do anything // (even worse, we would crash if we continue, as we assume they are two distinct nodes) if (refChild!=0 && newChild->isSameNode(refChild)) return newChild; if (newChild->getNodeType() == DOMNode::DOCUMENT_FRAGMENT_NODE) { // SLOW BUT SAFE: We could insert the whole subtree without // juggling so many next/previous pointers. (Wipe out the // parent's child-list, patch the parent pointers, set the // ends of the list.) But we know some subclasses have special- // case behavior they add to insertBefore(), so we don't risk it. // This approch also takes fewer bytecodes. // NOTE: If one of the children is not a legal child of this // node, throw HIERARCHY_REQUEST_ERR before _any_ of the children // have been transferred. (Alternative behaviors would be to // reparent up to the first failure point or reparent all those // which are acceptable to the target node, neither of which is // as robust. PR-DOM-0818 isn't entirely clear on which it // recommends????? // No need to check kids for right-document; if they weren't, // they wouldn't be kids of that DocFrag. for(DOMNode *kid=newChild->getFirstChild(); // Prescan kid!=0; kid=kid->getNextSibling()) { if (!DOMDocumentImpl::isKidOK(castToNode(this), kid)) throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0, GetDOMParentNodeMemoryManager); } while(newChild->hasChildNodes()) // Move insertBefore(newChild->getFirstChild(),refChild); } else if (!DOMDocumentImpl::isKidOK(castToNode(this), newChild)) throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0, GetDOMParentNodeMemoryManager); else { DOMNode *oldparent=newChild->getParentNode(); if(oldparent!=0) oldparent->removeChild(newChild); // Attach up castToNodeImpl(newChild)->fOwnerNode = castToNode(this); castToNodeImpl(newChild)->isOwned(true); // Attach before and after // Note: fFirstChild.previousSibling == lastChild!! if (fFirstChild == 0) { // this our first and only child fFirstChild = newChild; castToNodeImpl(newChild)->isFirstChild(true); // castToChildImpl(newChild)->previousSibling = newChild; DOMChildNode *newChild_ci = castToChildImpl(newChild); newChild_ci->previousSibling = newChild; } else { if (refChild == 0) { // this is an append DOMNode *lastChild = castToChildImpl(fFirstChild)->previousSibling; castToChildImpl(lastChild)->nextSibling = newChild; castToChildImpl(newChild)->previousSibling = lastChild; castToChildImpl(fFirstChild)->previousSibling = newChild; } else { // this is an insert if (refChild == fFirstChild) { // at the head of the list castToNodeImpl(fFirstChild)->isFirstChild(false); castToChildImpl(newChild)->nextSibling = fFirstChild; castToChildImpl(newChild)->previousSibling = castToChildImpl(fFirstChild)->previousSibling; castToChildImpl(fFirstChild)->previousSibling = newChild; fFirstChild = newChild; castToNodeImpl(newChild)->isFirstChild(true); } else { // somewhere in the middle DOMNode *prev = castToChildImpl(refChild)->previousSibling; castToChildImpl(newChild)->nextSibling = refChild; castToChildImpl(prev)->nextSibling = newChild; castToChildImpl(refChild)->previousSibling = newChild; castToChildImpl(newChild)->previousSibling = prev; } } } } changed(); if (this->getOwnerDocument() != 0) { Ranges* ranges = ((DOMDocumentImpl *)this->getOwnerDocument())->getRanges(); if ( ranges != 0) { XMLSize_t sz = ranges->size(); if (sz != 0) { for (XMLSize_t i =0; i<sz; i++) { ranges->elementAt(i)->updateRangeForInsertedNode(newChild); } } } } return newChild; }
DOMNode *XPathDocumentImpl::insertBefore(DOMNode *newChild, DOMNode *refChild) { // if the newChild is a documenttype node created from domimplementation, set the ownerDoc first if ((newChild->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE) && !newChild->getOwnerDocument()) ((DOMDocumentTypeImpl*)newChild)->setOwnerDocument(this); if(newChild==NULL) throw DOMException(DOMException::HIERARCHY_REQUEST_ERR,0, getMemoryManager()); DOMNodeImpl *thisNodeImpl = castToNodeImpl(this); if (thisNodeImpl->isReadOnly()) throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, getMemoryManager()); DOMNode* thisNode = castToNode(&fParent); if (newChild->getOwnerDocument() != thisNode) throw DOMException(DOMException::WRONG_DOCUMENT_ERR, 0, getMemoryManager()); // refChild must in fact be a child of this node (or 0) if (refChild!=0 && refChild->getParentNode() != thisNode) throw DOMException(DOMException::NOT_FOUND_ERR,0, getMemoryManager()); // if the new node has to be placed before itself, we don't have to do anything // (even worse, we would crash if we continue, as we assume they are two distinct nodes) if (refChild!=0 && newChild->isSameNode(refChild)) return newChild; if (newChild->getNodeType() == DOMNode::DOCUMENT_FRAGMENT_NODE) { // SLOW BUT SAFE: We could insert the whole subtree without // juggling so many next/previous pointers. (Wipe out the // parent's child-list, patch the parent pointers, set the // ends of the list.) But we know some subclasses have special- // case behavior they add to insertBefore(), so we don't risk it. // This approch also takes fewer bytecodes. while(newChild->hasChildNodes()) // Move insertBefore(newChild->getFirstChild(),refChild); } else { DOMNode *oldparent=newChild->getParentNode(); if(oldparent!=0) oldparent->removeChild(newChild); // Attach up castToNodeImpl(newChild)->fOwnerNode = thisNode; castToNodeImpl(newChild)->isOwned(true); // Attach before and after // Note: fFirstChild.previousSibling == lastChild!! if (fParent.fFirstChild == 0) { // this our first and only child fParent.fFirstChild = newChild; castToNodeImpl(newChild)->isFirstChild(true); // castToChildImpl(newChild)->previousSibling = newChild; DOMChildNode *newChild_ci = castToChildImpl(newChild); newChild_ci->previousSibling = newChild; } else { if (refChild == 0) { // this is an append DOMNode *lastChild = castToChildImpl(fParent.fFirstChild)->previousSibling; castToChildImpl(lastChild)->nextSibling = newChild; castToChildImpl(newChild)->previousSibling = lastChild; castToChildImpl(fParent.fFirstChild)->previousSibling = newChild; } else { // this is an insert if (refChild == fParent.fFirstChild) { // at the head of the list castToNodeImpl(fParent.fFirstChild)->isFirstChild(false); castToChildImpl(newChild)->nextSibling = fParent.fFirstChild; castToChildImpl(newChild)->previousSibling = castToChildImpl(fParent.fFirstChild)->previousSibling; castToChildImpl(fParent.fFirstChild)->previousSibling = newChild; fParent.fFirstChild = newChild; castToNodeImpl(newChild)->isFirstChild(true); } else { // somewhere in the middle DOMNode *prev = castToChildImpl(refChild)->previousSibling; castToChildImpl(newChild)->nextSibling = refChild; castToChildImpl(prev)->nextSibling = newChild; castToChildImpl(refChild)->previousSibling = newChild; castToChildImpl(newChild)->previousSibling = prev; } } } } changed(); Ranges* ranges = getRanges(); if ( ranges != 0) { XMLSize_t sz = ranges->size(); if (sz != 0) { for (XMLSize_t i =0; i<sz; i++) { ranges->elementAt(i)->updateRangeForInsertedNode(newChild); } } } // If insert succeeded, cache the kid appropriately if(newChild->getNodeType() == DOMNode::ELEMENT_NODE) fMyDocElement=(DOMElement *)newChild; else if(newChild->getNodeType() == DOMNode::DOCUMENT_TYPE_NODE) fMyDocType=(DOMDocumentType *)newChild; return newChild; }