Coverage Report

Created: 2025-06-13 07:02

/src/xerces-c/src/xercesc/dom/impl/DOMNamedNodeMapImpl.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 * contributor license agreements.  See the NOTICE file distributed with
4
 * this work for additional information regarding copyright ownership.
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 * (the "License"); you may not use this file except in compliance with
7
 * the License.  You may obtain a copy of the License at
8
 *
9
 *      http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
18
/*
19
 * $Id: DOMNamedNodeMapImpl.cpp 678381 2008-07-21 10:15:01Z borisk $
20
 */
21
22
23
#include <xercesc/dom/DOMAttr.hpp>
24
#include <xercesc/dom/DOMException.hpp>
25
#include <xercesc/framework/XMLBuffer.hpp>
26
#include <xercesc/util/XMLUniDefs.hpp>
27
28
#include "DOMNodeVector.hpp"
29
#include "DOMNamedNodeMapImpl.hpp"
30
#include "DOMCasts.hpp"
31
#include "DOMDocumentImpl.hpp"
32
#include "DOMNodeImpl.hpp"
33
34
XERCES_CPP_NAMESPACE_BEGIN
35
36
DOMNamedNodeMapImpl::DOMNamedNodeMapImpl(DOMNode *ownerNod)
37
0
{
38
0
    fOwnerNode=ownerNod;
39
0
    memset(fBuckets,0,MAP_SIZE*sizeof(DOMNodeVector*));
40
0
}
41
42
DOMNamedNodeMapImpl::~DOMNamedNodeMapImpl()
43
0
{
44
0
}
45
46
bool DOMNamedNodeMapImpl::readOnly()
47
0
{
48
0
    return castToNodeImpl(fOwnerNode)->isReadOnly();
49
0
}
50
51
DOMNamedNodeMapImpl *DOMNamedNodeMapImpl::cloneMap(DOMNode *ownerNod)
52
0
{
53
0
    DOMDocumentImpl *doc = (DOMDocumentImpl *)(castToNodeImpl(ownerNod)->getOwnerDocument());
54
0
    DOMNamedNodeMapImpl *newmap = new (doc) DOMNamedNodeMapImpl(ownerNod);
55
56
0
    for(XMLSize_t index=0;index<MAP_SIZE;index++)
57
0
        if (fBuckets[index] != 0) {
58
0
            XMLSize_t size=fBuckets[index]->size();
59
0
            newmap->fBuckets[index] = new (doc) DOMNodeVector(doc, size);
60
0
            for (XMLSize_t i = 0; i < size; ++i) {
61
0
                DOMNode *s = fBuckets[index]->elementAt(i);
62
0
                DOMNode *n = s->cloneNode(true);
63
0
          castToNodeImpl(n)->isSpecified(castToNodeImpl(s)->isSpecified());
64
0
                castToNodeImpl(n)->fOwnerNode = ownerNod;
65
0
                castToNodeImpl(n)->isOwned(true);
66
0
                newmap->fBuckets[index]->addElement(n);
67
0
            }
68
0
        }
69
70
0
    return newmap;
71
0
}
72
73
74
XMLSize_t DOMNamedNodeMapImpl::getLength() const
75
0
{
76
0
    XMLSize_t count=0;
77
0
    for(XMLSize_t index=0;index<MAP_SIZE;index++)
78
0
        count+=(fBuckets[index]==0?0:fBuckets[index]->size());
79
0
    return count;
80
0
}
81
82
DOMNode * DOMNamedNodeMapImpl::item(XMLSize_t index) const
83
0
{
84
0
    XMLSize_t count=0;
85
0
    for(XMLSize_t i=0;i<MAP_SIZE;i++) {
86
0
        if(fBuckets[i]==0)
87
0
            continue;
88
0
        XMLSize_t thisBucket=fBuckets[i]->size();
89
0
        if(index>=count && index<(count+thisBucket))
90
0
            return fBuckets[i]->elementAt(index-count);
91
0
        count+=thisBucket;
92
0
    }
93
0
    return NULL;
94
0
}
95
96
97
DOMNode * DOMNamedNodeMapImpl::getNamedItem(const XMLCh *name) const
98
0
{
99
0
    XMLSize_t hash=XMLString::hash(name,MAP_SIZE);
100
0
    if(fBuckets[hash]==0)
101
0
        return 0;
102
103
0
    XMLSize_t i = 0;
104
0
    XMLSize_t size = fBuckets[hash]->size();
105
0
    for (i = 0; i < size; ++i) {
106
0
        DOMNode *n=fBuckets[hash]->elementAt(i);
107
0
        if(XMLString::equals(name,n->getNodeName()))
108
0
            return n;
109
0
    }
110
111
0
    return 0;
112
0
}
113
114
115
//
116
// removeNamedItem() - Remove the named item, and return it.
117
//                      The caller can release the
118
//                      returned item if it's not used
119
//                      we can't do it here because the caller would
120
//                      never see the returned node.
121
//
122
DOMNode * DOMNamedNodeMapImpl::removeNamedItem(const XMLCh *name)
123
0
{
124
0
    if (this->readOnly())
125
0
        throw DOMException(
126
0
            DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager);
127
128
0
    XMLSize_t hash=XMLString::hash(name,MAP_SIZE);
129
0
    if(fBuckets[hash]==0)
130
0
        throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager);
131
132
0
    DOMDocument *doc = fOwnerNode->getOwnerDocument();
133
134
0
    XMLSize_t i = 0;
135
0
    XMLSize_t size = fBuckets[hash]->size();
136
0
    for (i = 0; i < size; ++i) {
137
0
        DOMNode *n=fBuckets[hash]->elementAt(i);
138
0
        if(XMLString::equals(name,n->getNodeName())) {
139
0
            fBuckets[hash]->removeElementAt(i);
140
0
            castToNodeImpl(n)->fOwnerNode = doc;
141
0
            castToNodeImpl(n)->isOwned(false);
142
0
            return n;
143
0
        }
144
0
    }
145
146
0
    throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager);
147
0
    return 0;
148
0
}
149
150
151
152
//
153
// setNamedItem()  Put the item into the NamedNodeList by name.
154
//                  If an item with the same name already was
155
//                  in the list, replace it.  Return the old
156
//                  item, if there was one.
157
//                  Caller is responsible for arranging for
158
//                  deletion of the old item if its ref count is
159
//                  zero.
160
//
161
DOMNode * DOMNamedNodeMapImpl::setNamedItem(DOMNode * arg)
162
0
{
163
0
    DOMDocument *doc = fOwnerNode->getOwnerDocument();
164
0
    DOMNodeImpl *argImpl = castToNodeImpl(arg);
165
0
    if(argImpl->getOwnerDocument() != doc)
166
0
        throw DOMException(DOMException::WRONG_DOCUMENT_ERR,0, GetDOMNamedNodeMapMemoryManager);
167
0
    if (this->readOnly())
168
0
        throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager);
169
0
    if ((arg->getNodeType() == DOMNode::ATTRIBUTE_NODE) && argImpl->isOwned() && (argImpl->fOwnerNode != fOwnerNode))
170
0
        throw DOMException(DOMException::INUSE_ATTRIBUTE_ERR,0, GetDOMNamedNodeMapMemoryManager);
171
172
0
    argImpl->fOwnerNode = fOwnerNode;
173
0
    argImpl->isOwned(true);
174
175
0
    const XMLCh* name=arg->getNodeName();
176
0
    XMLSize_t hash=XMLString::hash(name,MAP_SIZE);
177
0
    if(fBuckets[hash]==0)
178
0
        fBuckets[hash] = new (doc) DOMNodeVector(doc, 3);
179
180
0
    XMLSize_t i = 0;
181
0
    XMLSize_t size = fBuckets[hash]->size();
182
0
    for (i = 0; i < size; ++i) {
183
0
        DOMNode *n=fBuckets[hash]->elementAt(i);
184
0
        if(XMLString::equals(name,n->getNodeName())) {
185
0
            fBuckets[hash]->setElementAt(arg,i);
186
0
            castToNodeImpl(n)->fOwnerNode = doc;
187
0
            castToNodeImpl(n)->isOwned(false);
188
0
            return n;
189
0
        }
190
0
    }
191
0
    fBuckets[hash]->addElement(arg);
192
0
    return 0;
193
0
}
194
195
196
void DOMNamedNodeMapImpl::setReadOnly(bool readOnl, bool deep)
197
0
{
198
    // this->fReadOnly=readOnl;
199
0
    if(deep) {
200
0
        for (XMLSize_t index = 0; index < MAP_SIZE; index++) {
201
0
            if(fBuckets[index]==0)
202
0
                continue;
203
0
            XMLSize_t sz = fBuckets[index]->size();
204
0
            for (XMLSize_t i=0; i<sz; ++i)
205
0
                castToNodeImpl(fBuckets[index]->elementAt(i))->setReadOnly(readOnl, deep);
206
0
        }
207
0
    }
208
0
}
209
210
211
//Introduced in DOM Level 2
212
213
DOMNode *DOMNamedNodeMapImpl::getNamedItemNS(const XMLCh *namespaceURI, const XMLCh *localName) const
214
0
{
215
    // the map is indexed using the full name of nodes; to search given a namespace and a local name
216
    // we have to do a linear search
217
0
    for (XMLSize_t index = 0; index < MAP_SIZE; index++) {
218
0
        if(fBuckets[index]==0)
219
0
            continue;
220
221
0
        XMLSize_t i = 0;
222
0
        XMLSize_t size = fBuckets[index]->size();
223
0
        for (i = 0; i < size; ++i) {
224
0
            DOMNode *n=fBuckets[index]->elementAt(i);
225
0
            const XMLCh * nNamespaceURI = n->getNamespaceURI();
226
0
            const XMLCh * nLocalName = n->getLocalName();
227
0
            if (!XMLString::equals(nNamespaceURI, namespaceURI))    //URI not match
228
0
                continue;
229
0
            else {
230
0
                if (XMLString::equals(localName, nLocalName)
231
0
                    ||
232
0
                    (nLocalName == 0 && XMLString::equals(localName, n->getNodeName())))
233
0
                    return n;
234
0
            }
235
0
        }
236
0
    }
237
0
    return 0;
238
0
}
239
240
241
//
242
// setNamedItemNS()  Put the item into the NamedNodeList by name.
243
//                  If an item with the same name already was
244
//                  in the list, replace it.  Return the old
245
//                  item, if there was one.
246
//                  Caller is responsible for arranging for
247
//                  deletion of the old item if its ref count is
248
//                  zero.
249
//
250
DOMNode * DOMNamedNodeMapImpl::setNamedItemNS(DOMNode *arg)
251
0
{
252
0
    DOMDocument *doc = fOwnerNode->getOwnerDocument();
253
0
    DOMNodeImpl *argImpl = castToNodeImpl(arg);
254
0
    if (argImpl->getOwnerDocument() != doc)
255
0
        throw DOMException(DOMException::WRONG_DOCUMENT_ERR,0, GetDOMNamedNodeMapMemoryManager);
256
0
    if (this->readOnly())
257
0
        throw DOMException(DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager);
258
0
    if (argImpl->isOwned())
259
0
        throw DOMException(DOMException::INUSE_ATTRIBUTE_ERR,0, GetDOMNamedNodeMapMemoryManager);
260
261
0
    argImpl->fOwnerNode = fOwnerNode;
262
0
    argImpl->isOwned(true);
263
264
0
    const XMLCh* namespaceURI=arg->getNamespaceURI();
265
0
    const XMLCh* localName=arg->getLocalName();
266
    // the map is indexed using the full name of nodes; to search given a namespace and a local name
267
    // we have to do a linear search
268
0
    for (XMLSize_t index = 0; index < MAP_SIZE; index++) {
269
0
        if(fBuckets[index]==0)
270
0
            continue;
271
272
0
        XMLSize_t i = 0;
273
0
        XMLSize_t size = fBuckets[index]->size();
274
0
        for (i = 0; i < size; ++i) {
275
0
            DOMNode *n=fBuckets[index]->elementAt(i);
276
0
            const XMLCh * nNamespaceURI = n->getNamespaceURI();
277
0
            const XMLCh * nLocalName = n->getLocalName();
278
0
            if (!XMLString::equals(nNamespaceURI, namespaceURI))    //URI not match
279
0
                continue;
280
0
            else {
281
0
                if (XMLString::equals(localName, nLocalName)
282
0
                    ||
283
0
                    (nLocalName == 0 && XMLString::equals(localName, n->getNodeName()))) {
284
0
                    fBuckets[index]->setElementAt(arg,i);
285
0
                    castToNodeImpl(n)->fOwnerNode = doc;
286
0
                    castToNodeImpl(n)->isOwned(false);
287
0
                    return n;
288
0
                }
289
0
            }
290
0
        }
291
0
    }
292
    // if not found, add it using the full name as key
293
0
    return setNamedItem(arg);
294
0
}
295
296
297
// removeNamedItemNS() - Remove the named item, and return it.
298
//                      The caller can release the
299
//                      returned item if it's not used
300
//                      we can't do it here because the caller would
301
//                      never see the returned node.
302
DOMNode *DOMNamedNodeMapImpl::removeNamedItemNS(const XMLCh *namespaceURI,
303
                                                 const XMLCh *localName)
304
0
{
305
0
    if (this->readOnly())
306
0
        throw DOMException(
307
0
        DOMException::NO_MODIFICATION_ALLOWED_ERR, 0, GetDOMNamedNodeMapMemoryManager);
308
309
    // the map is indexed using the full name of nodes; to search given a namespace and a local name
310
    // we have to do a linear search
311
0
    for (XMLSize_t index = 0; index < MAP_SIZE; index++) {
312
0
        if(fBuckets[index]==0)
313
0
            continue;
314
315
0
        DOMDocument *doc = fOwnerNode->getOwnerDocument();
316
0
        XMLSize_t i = 0;
317
0
        XMLSize_t size = fBuckets[index]->size();
318
0
        for (i = 0; i < size; ++i) {
319
0
            DOMNode *n=fBuckets[index]->elementAt(i);
320
0
            const XMLCh * nNamespaceURI = n->getNamespaceURI();
321
0
            const XMLCh * nLocalName = n->getLocalName();
322
0
            if (!XMLString::equals(nNamespaceURI, namespaceURI))    //URI not match
323
0
                continue;
324
0
            else {
325
0
                if (XMLString::equals(localName, nLocalName)
326
0
                    ||
327
0
                    (nLocalName == 0 && XMLString::equals(localName, n->getNodeName()))) {
328
0
                    fBuckets[index]->removeElementAt(i);
329
0
                    castToNodeImpl(n)->fOwnerNode = doc;
330
0
                    castToNodeImpl(n)->isOwned(false);
331
0
                    return n;
332
0
                }
333
0
            }
334
0
        }
335
0
    }
336
0
    throw DOMException(DOMException::NOT_FOUND_ERR, 0, GetDOMNamedNodeMapMemoryManager);
337
0
    return 0;
338
0
}
339
340
XERCES_CPP_NAMESPACE_END