| /* |
| * 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: DOMNamedNodeMapImpl.cpp 568078 2007-08-21 11:43:25Z amassari $ |
| */ |
| |
| |
| #include <xercesc/dom/DOMAttr.hpp> |
| #include <xercesc/dom/DOMException.hpp> |
| #include <xercesc/framework/XMLBuffer.hpp> |
| #include <xercesc/util/XMLUniDefs.hpp> |
| |
| #include "DOMNodeVector.hpp" |
| #include "DOMNamedNodeMapImpl.hpp" |
| #include "DOMCasts.hpp" |
| #include "DOMDocumentImpl.hpp" |
| #include "DOMNodeImpl.hpp" |
| |
| XERCES_CPP_NAMESPACE_BEGIN |
| |
| DOMNamedNodeMapImpl::DOMNamedNodeMapImpl(DOMNode *ownerNod) |
| { |
| fOwnerNode=ownerNod; |
| memset(fBuckets,0,MAP_SIZE*sizeof(DOMNodeVector*)); |
| } |
| |
| DOMNamedNodeMapImpl::~DOMNamedNodeMapImpl() |
| { |
| } |
| |
| bool DOMNamedNodeMapImpl::readOnly() |
| { |
| return castToNodeImpl(fOwnerNode)->isReadOnly(); |
| } |
| |
| DOMNamedNodeMapImpl *DOMNamedNodeMapImpl::cloneMap(DOMNode *ownerNod) |
| { |
| DOMDocumentImpl *doc = (DOMDocumentImpl *)(castToNodeImpl(ownerNod)->getOwnerDocument()); |
| DOMNamedNodeMapImpl *newmap = new (doc) DOMNamedNodeMapImpl(ownerNod); |
| |
| for(int index=0;index<MAP_SIZE;index++) |
| if (fBuckets[index] != 0) { |
| XMLSize_t size=fBuckets[index]->size(); |
| newmap->fBuckets[index] = new (doc) DOMNodeVector(doc, size); |
| for (XMLSize_t i = 0; i < size; ++i) { |
| DOMNode *s = fBuckets[index]->elementAt(i); |
| DOMNode *n = s->cloneNode(true); |
| castToNodeImpl(n)->isSpecified(castToNodeImpl(s)->isSpecified()); |
| castToNodeImpl(n)->fOwnerNode = ownerNod; |
| castToNodeImpl(n)->isOwned(true); |
| newmap->fBuckets[index]->addElement(n); |
| } |
| } |
| |
| return newmap; |
| } |
| |
| |
| XMLSize_t DOMNamedNodeMapImpl::getLength() const |
| { |
| XMLSize_t count=0; |
| for(int index=0;index<MAP_SIZE;index++) |
| count+=(fBuckets[index]==0?0:fBuckets[index]->size()); |
| return count; |
| } |
| |
| DOMNode * DOMNamedNodeMapImpl::item(XMLSize_t index) const |
| { |
| XMLSize_t count=0; |
| for(XMLSize_t i=0;i<MAP_SIZE;i++) { |
| if(fBuckets[i]==0) |
| continue; |
| XMLSize_t thisBucket=fBuckets[i]->size(); |
| if(index>=count && index<(count+thisBucket)) |
| return fBuckets[i]->elementAt(index-count); |
| count+=thisBucket; |
| } |
| return NULL; |
| } |
| |
| |
| DOMNode * DOMNamedNodeMapImpl::getNamedItem(const XMLCh *name) const |
| { |
| unsigned int hash=XMLString::hash(name,MAP_SIZE); |
| if(fBuckets[hash]==0) |
| return 0; |
| |
| 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())) |
| return n; |
| } |
| |
| return 0; |
| } |
| |
| |
| // |
| // removeNamedItem() - Remove the named item, and return it. |
| // The caller can release the |
| // returned item if it's not used |
| // we can't do it here because the caller would |
| // never see the returned node. |
| // |
| DOMNode * DOMNamedNodeMapImpl::removeNamedItem(const XMLCh *name) |
| { |
| if (this->readOnly()) |
| throw DOMException( |
| DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager); |
| |
| unsigned int hash=XMLString::hash(name,MAP_SIZE); |
| if(fBuckets[hash]==0) |
| throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager); |
| |
| 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]->removeElementAt(i); |
| castToNodeImpl(n)->fOwnerNode = fOwnerNode->getOwnerDocument(); |
| castToNodeImpl(n)->isOwned(false); |
| return n; |
| } |
| } |
| |
| throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager); |
| return 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; |
| } |
| |
| |
| void DOMNamedNodeMapImpl::setReadOnly(bool readOnl, bool deep) |
| { |
| // this->fReadOnly=readOnl; |
| if(deep) { |
| for (int index = 0; index < MAP_SIZE; index++) { |
| if(fBuckets[index]==0) |
| continue; |
| int sz = fBuckets[index]->size(); |
| for (int i=0; i<sz; ++i) |
| castToNodeImpl(fBuckets[index]->elementAt(i))->setReadOnly(readOnl, deep); |
| } |
| } |
| } |
| |
| |
| //Introduced in DOM Level 2 |
| |
| DOMNode *DOMNamedNodeMapImpl::getNamedItemNS(const XMLCh *namespaceURI, const XMLCh *localName) const |
| { |
| // 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()))) |
| return n; |
| } |
| } |
| } |
| 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); |
| } |
| |
| |
| // removeNamedItemNS() - Remove the named item, and return it. |
| // The caller can release the |
| // returned item if it's not used |
| // we can't do it here because the caller would |
| // never see the returned node. |
| DOMNode *DOMNamedNodeMapImpl::removeNamedItemNS(const XMLCh *namespaceURI, |
| const XMLCh *localName) |
| { |
| if (this->readOnly()) |
| throw DOMException( |
| DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager); |
| |
| // 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]->removeElementAt(i); |
| castToNodeImpl(n)->fOwnerNode = fOwnerNode->getOwnerDocument(); |
| castToNodeImpl(n)->isOwned(false); |
| return n; |
| } |
| } |
| } |
| } |
| throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager); |
| return 0; |
| } |
| |
| XERCES_CPP_NAMESPACE_END |
| |