Coverage Report

Created: 2025-11-16 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/xerces-c/src/xercesc/dom/impl/DOMNodeIDMap.cpp
Line
Count
Source
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: DOMNodeIDMap.cpp 678144 2008-07-19 12:08:55Z borisk $
20
 */
21
22
#include "DOMAttrImpl.hpp"
23
#include "DOMDocumentImpl.hpp"
24
#include "DOMNodeIDMap.hpp"
25
26
#include <xercesc/util/XMLString.hpp>
27
#include <xercesc/util/RuntimeException.hpp>
28
#include <stdio.h>
29
30
XERCES_CPP_NAMESPACE_BEGIN
31
32
33
static const XMLSize_t gPrimes[] = {997, 9973, 99991, 999983, 0 };  // To do - add a few more.
34
35
static const float gMaxFill = 0.8f;   // The maximum fraction of the total
36
                                    // table entries to consume before exanding.
37
38
DOMNodeIDMap::DOMNodeIDMap(XMLSize_t initialSize, DOMDocument *doc)
39
0
: fNumEntries(0)
40
0
, fDoc(doc)
41
0
{
42
0
    for (fSizeIndex = 0; gPrimes[fSizeIndex] < initialSize; fSizeIndex++)
43
0
    {
44
0
        if (gPrimes[fSizeIndex] == 0)
45
0
        {
46
            // We need a bigger size than the largest available one.
47
            //   Big trouble.
48
0
            fSizeIndex--;
49
0
            ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::NodeIDMap_GrowErr, ((DOMDocumentImpl *)fDoc)->getMemoryManager());
50
0
        }
51
0
    }
52
53
0
    fSize = gPrimes[fSizeIndex];
54
0
    fMaxEntries = (XMLSize_t)(float(fSize) * gMaxFill);
55
56
    //fTable = new (fDoc) DOMAttr*[fSize];
57
0
    fTable = (DOMAttr**) ((DOMDocumentImpl *)fDoc)->allocate(sizeof(DOMAttr*) * fSize);
58
0
    XMLSize_t i;
59
0
    for (i=0; i<fSize; i++)
60
0
        fTable[i] = 0;
61
0
}
62
63
64
DOMNodeIDMap::~DOMNodeIDMap()
65
0
{
66
    // don't delete - the document owns the storage.
67
0
    fTable = 0;
68
0
}
69
70
71
72
void DOMNodeIDMap::add(DOMAttr *attr)
73
0
{
74
  //
75
  //  If the table is getting too full, grow it.  We arbitrarily limit
76
  //   the table to 80 full, which should limit the average number of
77
  //   rehashes to a reasonable value.
78
  //
79
0
  if (fNumEntries >= fMaxEntries)
80
0
    growTable();
81
82
0
        fNumEntries++;
83
84
  //
85
  // Hash the value string from the ID attribute being added to the table
86
  //      0 < Initial hash value < table size.
87
  //      An initial hash of zero would cause the rehash to fail.
88
  //
89
0
  const XMLCh *id=attr->getValue();
90
0
        XMLSize_t initalHash = XMLString::hash(id, fSize-1);
91
0
  initalHash++;
92
0
  XMLSize_t currentHash = initalHash;
93
94
  //
95
  // Loop looking for an empty slot for this ID.
96
  //   Don't even bother checking to see if the ID is already there -
97
  //   the table is only filled by the parser from valid documents, which
98
  //   can not have duplicates.  Behavior of invalid docs is not defined.
99
  //
100
0
    while (fTable[currentHash]!=0 && fTable[currentHash]!=(DOMAttr *)-1)
101
0
  {
102
0
    currentHash += initalHash;  // rehash
103
0
        if (currentHash >= fSize)
104
0
            currentHash = currentHash % fSize;
105
0
    }
106
107
    //
108
    // We've found our slot.  Stick the pointer to the attr into it.
109
    //
110
0
    fTable[currentHash] = attr;
111
112
0
}
113
114
115
void DOMNodeIDMap::remove(DOMAttr *attr)
116
0
{
117
    //
118
  // Hash the value string from the ID attribute being added to the table
119
  //      0 < Initial hash value < table size.
120
  //      An initial hash of zero would cause the rehash to fail.
121
  //
122
0
  const XMLCh *id=attr->getValue();
123
0
        XMLSize_t initalHash = XMLString::hash(id, fSize-1);
124
0
  initalHash++;
125
0
  XMLSize_t currentHash = initalHash;
126
127
  //
128
  // Loop looking for a slot pointing to an attr with this id.
129
    //
130
0
  DOMAttr *tableSlot;
131
0
    while ((tableSlot= fTable[currentHash])!=0)
132
0
  {
133
0
        if (tableSlot == attr)
134
0
        {
135
            //  Found the attribute.  Set the slot to -1 to indicate
136
            //   that it was once used, meaning that lookups, while never
137
            //   matching here, can not stop either, but must rehash again
138
            //   and continue searching.
139
0
            fTable[currentHash] = (DOMAttr *)-1;
140
0
            return;
141
0
        }
142
143
0
        currentHash += initalHash;  // rehash.
144
0
        if (currentHash >= fSize)
145
0
            currentHash = currentHash % fSize;
146
0
    }
147
    // There is no matching entry in the table
148
0
}
149
150
151
DOMAttr *DOMNodeIDMap::find(const XMLCh *id)
152
0
{
153
    //
154
    //  Get the hashcode for the supplied string.
155
    //
156
0
    XMLSize_t initalHash = XMLString::hash(id, fSize-1);
157
0
  initalHash++;
158
0
  XMLSize_t currentHash = initalHash;
159
160
  //
161
  // Loop looking for a slot pointing to an attr with this id.
162
    //
163
0
  DOMAttr *tableSlot;
164
0
    while ((tableSlot= fTable[currentHash])!=0)
165
0
  {
166
0
        if ((tableSlot != (DOMAttr *)-1) && XMLString::equals(tableSlot->getValue(), id))
167
0
            return tableSlot;
168
169
0
        currentHash += initalHash;  // rehash
170
0
        if (currentHash >= fSize)
171
0
            currentHash = currentHash % fSize;
172
0
    }
173
    // There is no matching entry in the table
174
0
    return 0;
175
0
}
176
177
178
//
179
//  Grow the table to the next larger size.
180
//      It has gotten too full for efficient operation.
181
//     (We never fill it all the way)
182
//
183
void DOMNodeIDMap::growTable()
184
0
{
185
0
    DOMAttr     **oldTable = fTable;
186
0
    XMLSize_t oldSize  = fSize;
187
188
    //
189
    //  Figure the new table size.
190
    //
191
#if defined(XERCES_DEBUG)
192
    fprintf(stderr, "growing...\n");
193
#endif
194
0
    fSizeIndex++;
195
0
    fSize = gPrimes[fSizeIndex];
196
0
    if (fSize == 0)
197
0
    {
198
        // We need to grow bigger than the largest available size.
199
        //   Big trouble.
200
0
        fSizeIndex--;
201
0
        ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::NodeIDMap_GrowErr, ((DOMDocumentImpl *)fDoc)->getMemoryManager());
202
0
    }
203
204
    //
205
    //  Allocate the new table.
206
    //
207
    //fTable = new (fDoc) DOMAttr *[fSize];
208
0
    fTable = (DOMAttr**) ((DOMDocumentImpl *)fDoc)->allocate(sizeof(DOMAttr*) * fSize);
209
0
    XMLSize_t i;
210
0
    for (i=0; i<fSize; i++)
211
0
        fTable[i] = 0;
212
213
0
    fMaxEntries = (XMLSize_t)(float(fSize) * gMaxFill);
214
215
    //
216
    // Move entries over from the old table to the new one.
217
    //
218
0
    for (i=0; i<oldSize; i++)
219
0
    {
220
0
        if ((oldTable[i] != 0)  &&  (oldTable[i] != (DOMAttr *)-1))
221
0
            add(oldTable[i]);
222
0
    }
223
224
    // delete [] oldTable;   (The document owns the storage.  The old table will just
225
    //                        need to leak until until the document is discarded.)
226
227
0
}
228
229
230
XERCES_CPP_NAMESPACE_END