source: icXML/icXML-devel/src/xercesc/dom/impl/DOMDeepNodeListPool.c

Last change on this file was 2722, checked in by cameron, 6 years ago

Original Xerces files with import mods for icxercesc

File size: 14.6 KB
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: DOMDeepNodeListPool.c 883368 2009-11-23 15:28:19Z amassari $
20 */
21
22
23// ---------------------------------------------------------------------------
24//  Include
25// ---------------------------------------------------------------------------
26#include <xercesc/util/XercesDefs.hpp>
27#if defined(XERCES_TMPLSINC)
28#include <xercesc/dom/impl/DOMDeepNodeListPool.hpp>
29#endif
30
31#include <assert.h>
32
33XERCES_CPP_NAMESPACE_BEGIN
34
35
36
37// ---------------------------------------------------------------------------
38//  DOMDeepNodeListPool: Constructors and Destructor
39// ---------------------------------------------------------------------------
40template <class TVal, class THasher>
41DOMDeepNodeListPool<TVal, THasher>::DOMDeepNodeListPool( const XMLSize_t modulus
42                                              , const bool adoptElems
43                                              , const XMLSize_t initSize) :
44    fAdoptedElems(adoptElems)
45    , fBucketList(0)
46    , fHashModulus(modulus)
47    , fIdPtrs(0)
48    , fIdPtrsCount(initSize)
49    , fIdCounter(0)
50    , fMemoryManager(XMLPlatformUtils::fgMemoryManager)
51{
52    initialize(modulus);
53
54    //
55    //  Allocate the initial id pointers array. We don't have to zero them
56    //  out since the fIdCounter value tells us which ones are valid. The
57    //  zeroth element is never used (and represents an invalid pool id.)
58    //
59    if (!fIdPtrsCount)
60        fIdPtrsCount = 256;
61
62    fIdPtrs = (TVal**) fMemoryManager->allocate(fIdPtrsCount * sizeof(TVal*));//new TVal*[fIdPtrsCount];
63    fIdPtrs[0] = 0;
64}
65
66template <class TVal, class THasher>
67DOMDeepNodeListPool<TVal, THasher>::DOMDeepNodeListPool( const XMLSize_t modulus
68                                              , const bool adoptElems
69                                              , const THasher& hasher
70                                              , const XMLSize_t initSize) :
71    fAdoptedElems(adoptElems)
72    , fBucketList(0)
73    , fHashModulus(modulus)
74    , fIdPtrs(0)
75    , fIdPtrsCount(initSize)
76    , fIdCounter(0)
77    , fMemoryManager(XMLPlatformUtils::fgMemoryManager)
78    , fHasher(hasher)
79{
80    initialize(modulus);
81
82    //
83    //  Allocate the initial id pointers array. We don't have to zero them
84    //  out since the fIdCounter value tells us which ones are valid. The
85    //  zeroth element is never used (and represents an invalid pool id.)
86    //
87    if (!fIdPtrsCount)
88        fIdPtrsCount = 256;
89
90    fIdPtrs = (TVal**) fMemoryManager->allocate(fIdPtrsCount * sizeof(TVal*));//new TVal*[fIdPtrsCount];
91    fIdPtrs[0] = 0;
92}
93
94template <class TVal, class THasher>
95DOMDeepNodeListPool<TVal, THasher>::DOMDeepNodeListPool( const XMLSize_t modulus
96                                              , const XMLSize_t initSize) :
97    fAdoptedElems(true)
98    , fBucketList(0)
99    , fHashModulus(modulus)
100    , fIdPtrs(0)
101    , fIdPtrsCount(initSize)
102    , fIdCounter(0)
103    , fMemoryManager(XMLPlatformUtils::fgMemoryManager)
104{
105    initialize(modulus);
106
107    //
108    //  Allocate the initial id pointers array. We don't have to zero them
109    //  out since the fIdCounter value tells us which ones are valid. The
110    //  zeroth element is never used (and represents an invalid pool id.)
111    //
112    if (!fIdPtrsCount)
113        fIdPtrsCount = 256;
114
115    fIdPtrs = (TVal**) fMemoryManager->allocate(fIdPtrsCount * sizeof(TVal*));//new TVal*[fIdPtrsCount];
116    fIdPtrs[0] = 0;
117}
118
119template <class TVal, class THasher>
120void DOMDeepNodeListPool<TVal, THasher>::initialize(const XMLSize_t modulus)
121{
122        if (modulus == 0)
123        ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::HshTbl_ZeroModulus, fMemoryManager);
124
125    // Allocate the bucket list and zero them
126    fBucketList = (DOMDeepNodeListPoolTableBucketElem<TVal>**)
127        fMemoryManager->allocate
128        (
129            fHashModulus * sizeof(DOMDeepNodeListPoolTableBucketElem<TVal>*)
130        );//new DOMDeepNodeListPoolTableBucketElem<TVal>*[fHashModulus];
131    for (XMLSize_t index = 0; index < fHashModulus; index++)
132        fBucketList[index] = 0;
133}
134
135template <class TVal, class THasher>
136DOMDeepNodeListPool<TVal, THasher>::~DOMDeepNodeListPool()
137{
138    removeAll();
139
140    // Then delete the bucket list & hasher & id pointers list
141    fMemoryManager->deallocate(fIdPtrs);//delete [] fIdPtrs;
142    fMemoryManager->deallocate(fBucketList);//delete [] fBucketList;
143}
144
145
146// ---------------------------------------------------------------------------
147//  DOMDeepNodeListPool: Element management
148// ---------------------------------------------------------------------------
149template <class TVal, class THasher>
150bool DOMDeepNodeListPool<TVal, THasher>::isEmpty() const
151{
152    // Just check the bucket list for non-empty elements
153    for (XMLSize_t buckInd = 0; buckInd < fHashModulus; buckInd++)
154    {
155        if (fBucketList[buckInd] != 0)
156            return false;
157    }
158    return true;
159}
160
161template <class TVal, class THasher>
162bool DOMDeepNodeListPool<TVal, THasher>::containsKey( const void* const key1
163                                           , const XMLCh* const key2
164                                           , const XMLCh* const key3) const
165{
166    XMLSize_t hashVal;
167    const DOMDeepNodeListPoolTableBucketElem<TVal>* findIt = findBucketElem(key1, key2, key3, hashVal);
168    return (findIt != 0);
169}
170
171template <class TVal, class THasher>
172void DOMDeepNodeListPool<TVal, THasher>::removeAll()
173{
174    if (fIdCounter == 0) return;
175
176    // Clean up the buckets first
177    for (XMLSize_t buckInd = 0; buckInd < fHashModulus; buckInd++)
178    {
179        // Get the bucket list head for this entry
180        DOMDeepNodeListPoolTableBucketElem<TVal>* curElem = fBucketList[buckInd];
181        DOMDeepNodeListPoolTableBucketElem<TVal>* nextElem;
182        while (curElem)
183        {
184            // Save the next element before we hose this one
185            nextElem = curElem->fNext;
186
187            // If we adopted the data, then delete it too
188            //    (Note:  the userdata hash table instance has data type of void *.
189            //    This will generate compiler warnings here on some platforms, but they
190            //    can be ignored since fAdoptedElements is false.
191            if (fAdoptedElems)
192                delete curElem->fData;
193
194            // Then delete the current element and move forward
195            fMemoryManager->deallocate(curElem->fKey2);//delete [] curElem->fKey2;
196            fMemoryManager->deallocate(curElem->fKey3);//delete [] curElem->fKey3;
197
198            delete curElem;
199            curElem = nextElem;
200        }
201
202        // Clean out this entry
203        fBucketList[buckInd] = 0;
204    }
205
206    // Reset the id counter
207    fIdCounter = 0;
208}
209
210template <class TVal, class THasher>
211void DOMDeepNodeListPool<TVal, THasher>::cleanup()
212{
213    removeAll();
214
215    // Then delete the bucket list & hasher & id pointers list
216    fMemoryManager->deallocate(fIdPtrs);//delete [] fIdPtrs;
217    fMemoryManager->deallocate(fBucketList);//delete [] fBucketList;
218}
219
220
221
222// ---------------------------------------------------------------------------
223//  DOMDeepNodeListPool: Getters
224// ---------------------------------------------------------------------------
225template <class TVal, class THasher>
226TVal*
227DOMDeepNodeListPool<TVal, THasher>::getByKey(const void* const key1, const XMLCh* const key2, const XMLCh* const key3)
228{
229    XMLSize_t hashVal;
230    DOMDeepNodeListPoolTableBucketElem<TVal>* findIt = findBucketElem(key1, key2, key3, hashVal);
231    if (!findIt)
232        return 0;
233    return findIt->fData;
234}
235
236template <class TVal, class THasher>
237const TVal*
238DOMDeepNodeListPool<TVal, THasher>::getByKey(const void* const key1, const XMLCh* const key2, const XMLCh* const key3) const
239{
240    XMLSize_t hashVal;
241    const DOMDeepNodeListPoolTableBucketElem<TVal>* findIt = findBucketElem(key1, key2, key3, hashVal);
242    if (!findIt)
243        return 0;
244    return findIt->fData;
245}
246
247template <class TVal, class THasher>
248TVal*
249DOMDeepNodeListPool<TVal, THasher>::getById(const XMLSize_t elemId)
250{
251    // If its either zero or beyond our current id, its an error
252    if (!elemId || (elemId > fIdCounter))
253        ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Pool_InvalidId, fMemoryManager);
254
255    return fIdPtrs[elemId];
256}
257
258template <class TVal, class THasher>
259const TVal*
260DOMDeepNodeListPool<TVal, THasher>::getById(const XMLSize_t elemId) const
261{
262    // If its either zero or beyond our current id, its an error
263    if (!elemId || (elemId > fIdCounter))
264        ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Pool_InvalidId, fMemoryManager);
265
266    return fIdPtrs[elemId];
267}
268
269// ---------------------------------------------------------------------------
270//  DOMDeepNodeListPool: Putters
271// ---------------------------------------------------------------------------
272template <class TVal, class THasher>
273XMLSize_t
274DOMDeepNodeListPool<TVal, THasher>::put(void* key1, XMLCh* key2, XMLCh* key3, TVal* const valueToAdopt)
275{
276    // First see if the key exists already
277    XMLSize_t hashVal;
278    DOMDeepNodeListPoolTableBucketElem<TVal>* newBucket = findBucketElem(key1, key2, key3, hashVal);
279
280    //
281    //  If so,then update its value. If not, then we need to add it to
282    //  the right bucket
283    //
284    if (newBucket)
285    {
286        if (fAdoptedElems)
287            delete newBucket->fData;
288
289        fMemoryManager->deallocate(newBucket->fKey2);//delete[] newBucket->fKey2;
290        fMemoryManager->deallocate(newBucket->fKey3);//delete[] newBucket->fKey3;
291
292        newBucket->fData = valueToAdopt;
293        newBucket->fKey1 = key1;
294        newBucket->fKey2 = XMLString::replicate(key2, fMemoryManager);
295        newBucket->fKey3 = XMLString::replicate(key3, fMemoryManager);
296    }
297    else
298    {
299    // Revisit: the gcc compiler 2.95.x is generating an
300    // internal compiler error message. So we use the default
301    // memory manager for now.
302#if defined (XML_GCC_VERSION) && (XML_GCC_VERSION < 29600)
303        newBucket = new DOMDeepNodeListPoolTableBucketElem<TVal>
304        (
305            key1
306            , key2
307            , key3
308            , valueToAdopt
309            , fBucketList[hashVal]
310            , fMemoryManager
311        );
312#else
313        newBucket = new (fMemoryManager) DOMDeepNodeListPoolTableBucketElem<TVal>
314        (
315            key1
316            , key2
317            , key3
318            , valueToAdopt
319            , fBucketList[hashVal]
320            , fMemoryManager
321        );
322#endif
323        fBucketList[hashVal] = newBucket;
324    }
325
326    //
327    //  Give this new one the next available id and add to the pointer list.
328    //  Expand the list if that is now required.
329    //
330    if (fIdCounter + 1 == fIdPtrsCount)
331    {
332        // Create a new count 1.5 times larger and allocate a new array
333        XMLSize_t newCount = (XMLSize_t)(fIdPtrsCount * 1.5);
334        TVal** newArray = (TVal**) fMemoryManager->allocate
335        (
336            newCount * sizeof(TVal*)
337        );//new TVal*[newCount];
338
339        // Copy over the old contents to the new array
340        memcpy(newArray, fIdPtrs, fIdPtrsCount * sizeof(TVal*));
341
342        // Ok, toss the old array and store the new data
343        fMemoryManager->deallocate(fIdPtrs); //delete [] fIdPtrs;
344        fIdPtrs = newArray;
345        fIdPtrsCount = newCount;
346    }
347    const XMLSize_t retId = ++fIdCounter;
348    fIdPtrs[retId] = valueToAdopt;
349
350    // Return the id that we gave to this element
351    return retId;
352}
353
354// ---------------------------------------------------------------------------
355//  DOMDeepNodeListPool: Private methods
356// ---------------------------------------------------------------------------
357template <class TVal, class THasher>
358DOMDeepNodeListPoolTableBucketElem<TVal>* DOMDeepNodeListPool<TVal, THasher>::
359findBucketElem(const void* const key1, const XMLCh* const key2, const XMLCh* const key3, XMLSize_t& hashVal)
360{
361    // Hash the key
362    hashVal = fHasher.getHashVal(key1, fHashModulus);
363    assert(hashVal < fHashModulus);
364
365    // Search that bucket for the key
366    DOMDeepNodeListPoolTableBucketElem<TVal>* curElem = fBucketList[hashVal];
367    while (curElem)
368    {
369        //key2 and key3 are XMLCh*, compareString takes null pointer vs zero len string the same
370        //but we need them to be treated as different keys in this case
371        if (fHasher.equals(key1, curElem->fKey1) && (XMLString::equals(key2, curElem->fKey2)) && (XMLString::equals(key3, curElem->fKey3))) {
372            if (!key2 || !curElem->fKey2) {
373                if (key2 || curElem->fKey2) {
374                    curElem = curElem->fNext;
375                    continue;
376                }
377            }
378            if (!key3 || !curElem->fKey3) {
379                if (key3 || curElem->fKey3) {
380                    curElem = curElem->fNext;
381                    continue;
382                }
383            }
384
385            return curElem;
386        }
387
388        curElem = curElem->fNext;
389    }
390    return 0;
391}
392
393template <class TVal, class THasher>
394const DOMDeepNodeListPoolTableBucketElem<TVal>* DOMDeepNodeListPool<TVal, THasher>::
395findBucketElem(const void* const key1, const XMLCh* const key2, const XMLCh* const key3, XMLSize_t& hashVal) const
396{
397    // Hash the key
398    hashVal = fHasher.getHashVal(key1, fHashModulus);
399    assert(hashVal < fHashModulus);
400
401    // Search that bucket for the key
402    const DOMDeepNodeListPoolTableBucketElem<TVal>* curElem = fBucketList[hashVal];
403    while (curElem)
404    {
405        //key2 and key3 are XMLCh*, compareString takes null pointer vs zero len string the same
406        //but we need them to be treated as different keys in this case
407        if (fHasher.equals(key1, curElem->fKey1) && (XMLString::equals(key2, curElem->fKey2)) && (XMLString::equals(key3, curElem->fKey3))) {
408            if (!key2 || !curElem->fKey2) {
409                if (key2 || curElem->fKey2) {
410                    curElem = curElem->fNext;
411                    continue;
412                }
413            }
414            if (!key3 || !curElem->fKey3) {
415                if (key3 || curElem->fKey3) {
416                    curElem = curElem->fNext;
417                    continue;
418                }
419            }
420            return curElem;
421        }
422
423        curElem = curElem->fNext;
424    }
425    return 0;
426}
427
428XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.