source: NonGTP/Xerces/xercesc/dom/impl/DOMDeepNodeListPool.c @ 188

Revision 188, 17.0 KB checked in by mattausch, 19 years ago (diff)

added xercesc to support

Line 
1/*
2 * The Apache Software License, Version 1.1
3 *
4 * Copyright (c) 2001-2002 The Apache Software Foundation.  All rights
5 * reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 *
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in
16 *    the documentation and/or other materials provided with the
17 *    distribution.
18 *
19 * 3. The end-user documentation included with the redistribution,
20 *    if any, must include the following acknowledgment:
21 *       "This product includes software developed by the
22 *        Apache Software Foundation (http://www.apache.org/)."
23 *    Alternately, this acknowledgment may appear in the software itself,
24 *    if and wherever such third-party acknowledgments normally appear.
25 *
26 * 4. The names "Xerces" and "Apache Software Foundation" must
27 *    not be used to endorse or promote products derived from this
28 *    software without prior written permission. For written
29 *    permission, please contact apache\@apache.org.
30 *
31 * 5. Products derived from this software may not be called "Apache",
32 *    nor may "Apache" appear in their name, without prior written
33 *    permission of the Apache Software Foundation.
34 *
35 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46 * SUCH DAMAGE.
47 * ====================================================================
48 *
49 * This software consists of voluntary contributions made by many
50 * individuals on behalf of the Apache Software Foundation, and was
51 * originally based on software copyright (c) 2001, International
52 * Business Machines, Inc., http://www.ibm.com .  For more information
53 * on the Apache Software Foundation, please see
54 * <http://www.apache.org/>.
55 */
56
57/**
58 * $Id: DOMDeepNodeListPool.c,v 1.9 2003/12/17 00:18:33 cargilld Exp $
59 */
60
61
62// ---------------------------------------------------------------------------
63//  Include
64// ---------------------------------------------------------------------------
65#include <xercesc/util/XercesDefs.hpp>
66#if defined(XERCES_TMPLSINC)
67#include <xercesc/dom/impl/DOMDeepNodeListPool.hpp>
68#endif
69
70XERCES_CPP_NAMESPACE_BEGIN
71
72
73
74// ---------------------------------------------------------------------------
75//  DOMDeepNodeListPool: Constructors and Destructor
76// ---------------------------------------------------------------------------
77template <class TVal>
78DOMDeepNodeListPool<TVal>::DOMDeepNodeListPool( const XMLSize_t modulus
79                                              , const bool adoptElems
80                                              , const XMLSize_t initSize) :
81         fAdoptedElems(adoptElems)
82    , fBucketList(0)
83    , fHashModulus(modulus)
84    , fHash(0)
85    , fIdPtrs(0)
86    , fIdPtrsCount(initSize)
87    , fIdCounter(0)
88    , fMemoryManager(XMLPlatformUtils::fgMemoryManager)
89{
90    initialize(modulus);
91
92    // create default hasher
93#if defined (XML_GCC_VERSION) && (XML_GCC_VERSION < 29600)
94    fHash = new HashPtr();
95#else
96    fHash = new (fMemoryManager) HashPtr();
97#endif
98    //
99    //  Allocate the initial id pointers array. We don't have to zero them
100    //  out since the fIdCounter value tells us which ones are valid. The
101    //  zeroth element is never used (and represents an invalid pool id.)
102    //
103    if (!fIdPtrsCount)
104        fIdPtrsCount = 256;
105
106    fIdPtrs = (TVal**) fMemoryManager->allocate(fIdPtrsCount * sizeof(TVal*));//new TVal*[fIdPtrsCount];
107    fIdPtrs[0] = 0;
108}
109
110template <class TVal>
111DOMDeepNodeListPool<TVal>::DOMDeepNodeListPool( const XMLSize_t modulus
112                                              , const bool adoptElems
113                                              , HashBase* hash
114                                              , const XMLSize_t initSize) :
115         fAdoptedElems(adoptElems)
116    , fBucketList(0)
117    , fHashModulus(modulus)
118    , fHash(0)
119    , fIdPtrs(0)
120    , fIdPtrsCount(initSize)
121    , fIdCounter(0)
122    , fMemoryManager(XMLPlatformUtils::fgMemoryManager)
123{
124    initialize(modulus);
125    // set hasher
126    fHash = hash;
127
128    //
129    //  Allocate the initial id pointers array. We don't have to zero them
130    //  out since the fIdCounter value tells us which ones are valid. The
131    //  zeroth element is never used (and represents an invalid pool id.)
132    //
133    if (!fIdPtrsCount)
134        fIdPtrsCount = 256;
135
136    fIdPtrs = (TVal**) fMemoryManager->allocate(fIdPtrsCount * sizeof(TVal*));//new TVal*[fIdPtrsCount];
137    fIdPtrs[0] = 0;
138}
139
140template <class TVal>
141DOMDeepNodeListPool<TVal>::DOMDeepNodeListPool( const XMLSize_t modulus
142                                              , const XMLSize_t initSize) :
143         fAdoptedElems(true)
144    , fBucketList(0)
145    , fHashModulus(modulus)
146    , fHash(0)
147    , fIdPtrs(0)
148    , fIdPtrsCount(initSize)
149    , fIdCounter(0)
150    , fMemoryManager(XMLPlatformUtils::fgMemoryManager)
151{
152    initialize(modulus);
153
154    // create default hasher
155    fHash = new (fMemoryManager) HashPtr();
156
157    //
158    //  Allocate the initial id pointers array. We don't have to zero them
159    //  out since the fIdCounter value tells us which ones are valid. The
160    //  zeroth element is never used (and represents an invalid pool id.)
161    //
162    if (!fIdPtrsCount)
163        fIdPtrsCount = 256;
164
165    fIdPtrs = (TVal**) fMemoryManager->allocate(fIdPtrsCount * sizeof(TVal*));//new TVal*[fIdPtrsCount];
166    fIdPtrs[0] = 0;
167}
168
169template <class TVal>
170void DOMDeepNodeListPool<TVal>::initialize(const XMLSize_t modulus)
171{
172        if (modulus == 0)
173        ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::HshTbl_ZeroModulus, fMemoryManager);
174
175    // Allocate the bucket list and zero them
176    fBucketList = (DOMDeepNodeListPoolTableBucketElem<TVal>**)
177        fMemoryManager->allocate
178        (
179            fHashModulus * sizeof(DOMDeepNodeListPoolTableBucketElem<TVal>*)
180        );//new DOMDeepNodeListPoolTableBucketElem<TVal>*[fHashModulus];
181    for (XMLSize_t index = 0; index < fHashModulus; index++)
182        fBucketList[index] = 0;
183}
184
185template <class TVal> DOMDeepNodeListPool<TVal>::~DOMDeepNodeListPool()
186{
187    removeAll();
188
189    // Then delete the bucket list & hasher & id pointers list
190    fMemoryManager->deallocate(fIdPtrs);//delete [] fIdPtrs;
191    fMemoryManager->deallocate(fBucketList);//delete [] fBucketList;
192    delete fHash;
193}
194
195
196// ---------------------------------------------------------------------------
197//  DOMDeepNodeListPool: Element management
198// ---------------------------------------------------------------------------
199template <class TVal>
200bool DOMDeepNodeListPool<TVal>::isEmpty() const
201{
202    // Just check the bucket list for non-empty elements
203    for (XMLSize_t buckInd = 0; buckInd < fHashModulus; buckInd++)
204    {
205        if (fBucketList[buckInd] != 0)
206            return false;
207    }
208    return true;
209}
210
211template <class TVal>
212bool DOMDeepNodeListPool<TVal>::containsKey( const void* const key1
213                                           , const XMLCh* const key2
214                                           , const XMLCh* const key3) const
215{
216    XMLSize_t hashVal;
217    const DOMDeepNodeListPoolTableBucketElem<TVal>* findIt = findBucketElem(key1, key2, key3, hashVal);
218    return (findIt != 0);
219}
220
221template <class TVal>
222void DOMDeepNodeListPool<TVal>::removeAll()
223{
224    // Clean up the buckets first
225    for (XMLSize_t buckInd = 0; buckInd < fHashModulus; buckInd++)
226    {
227        // Get the bucket list head for this entry
228        DOMDeepNodeListPoolTableBucketElem<TVal>* curElem = fBucketList[buckInd];
229        DOMDeepNodeListPoolTableBucketElem<TVal>* nextElem;
230        while (curElem)
231        {
232            // Save the next element before we hose this one
233            nextElem = curElem->fNext;
234
235            // If we adopted the data, then delete it too
236            //    (Note:  the userdata hash table instance has data type of void *.
237            //    This will generate compiler warnings here on some platforms, but they
238            //    can be ignored since fAdoptedElements is false.
239            if (fAdoptedElems)
240                delete curElem->fData;
241
242            // Then delete the current element and move forward
243            fMemoryManager->deallocate(curElem->fKey2);//delete [] curElem->fKey2;
244            fMemoryManager->deallocate(curElem->fKey3);//delete [] curElem->fKey3;
245
246            delete curElem;
247            curElem = nextElem;
248        }
249
250        // Clean out this entry
251        fBucketList[buckInd] = 0;
252    }
253
254    // Reset the id counter
255    fIdCounter = 0;
256}
257
258template <class TVal> void DOMDeepNodeListPool<TVal>::cleanup()
259{
260    removeAll();
261
262    // Then delete the bucket list & hasher & id pointers list
263    fMemoryManager->deallocate(fIdPtrs);//delete [] fIdPtrs;
264    fMemoryManager->deallocate(fBucketList);//delete [] fBucketList;
265    delete fHash;
266}
267
268
269
270// ---------------------------------------------------------------------------
271//  DOMDeepNodeListPool: Getters
272// ---------------------------------------------------------------------------
273template <class TVal> TVal*
274DOMDeepNodeListPool<TVal>::getByKey(const void* const key1, const XMLCh* const key2, const XMLCh* const key3)
275{
276    XMLSize_t hashVal;
277    DOMDeepNodeListPoolTableBucketElem<TVal>* findIt = findBucketElem(key1, key2, key3, hashVal);
278    if (!findIt)
279        return 0;
280    return findIt->fData;
281}
282
283template <class TVal> const TVal*
284DOMDeepNodeListPool<TVal>::getByKey(const void* const key1, const XMLCh* const key2, const XMLCh* const key3) const
285{
286    XMLSize_t hashVal;
287    const DOMDeepNodeListPoolTableBucketElem<TVal>* findIt = findBucketElem(key1, key2, key3, hashVal);
288    if (!findIt)
289        return 0;
290    return findIt->fData;
291}
292
293template <class TVal> TVal*
294DOMDeepNodeListPool<TVal>::getById(const XMLSize_t elemId)
295{
296    // If its either zero or beyond our current id, its an error
297    if (!elemId || (elemId > fIdCounter))
298        ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Pool_InvalidId, fMemoryManager);
299
300    return fIdPtrs[elemId];
301}
302
303template <class TVal> const TVal*
304DOMDeepNodeListPool<TVal>::getById(const XMLSize_t elemId) const
305{
306    // If its either zero or beyond our current id, its an error
307    if (!elemId || (elemId > fIdCounter))
308        ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Pool_InvalidId, fMemoryManager);
309
310    return fIdPtrs[elemId];
311}
312
313// ---------------------------------------------------------------------------
314//  DOMDeepNodeListPool: Putters
315// ---------------------------------------------------------------------------
316template <class TVal> XMLSize_t
317DOMDeepNodeListPool<TVal>::put(void* key1, XMLCh* key2, XMLCh* key3, TVal* const valueToAdopt)
318{
319    // First see if the key exists already
320    XMLSize_t hashVal;
321    DOMDeepNodeListPoolTableBucketElem<TVal>* newBucket = findBucketElem(key1, key2, key3, hashVal);
322
323    //
324    //  If so,then update its value. If not, then we need to add it to
325    //  the right bucket
326    //
327    if (newBucket)
328    {
329        if (fAdoptedElems)
330            delete newBucket->fData;
331
332        fMemoryManager->deallocate(newBucket->fKey2);//delete[] newBucket->fKey2;
333        fMemoryManager->deallocate(newBucket->fKey3);//delete[] newBucket->fKey3;
334
335        newBucket->fData = valueToAdopt;
336        newBucket->fKey1 = key1;
337        newBucket->fKey2 = XMLString::replicate(key2, fMemoryManager);
338        newBucket->fKey3 = XMLString::replicate(key3, fMemoryManager);
339    }
340    else
341    {
342    // Revisit: the gcc compiler 2.95.x is generating an
343    // internal compiler error message. So we use the default
344    // memory manager for now.
345#if defined (XML_GCC_VERSION) && (XML_GCC_VERSION < 29600)
346        newBucket = new DOMDeepNodeListPoolTableBucketElem<TVal>
347        (
348            key1
349            , key2
350            , key3
351            , valueToAdopt
352            , fBucketList[hashVal]
353            , fMemoryManager
354        );
355#else
356        newBucket = new (fMemoryManager) DOMDeepNodeListPoolTableBucketElem<TVal>
357        (
358            key1
359            , key2
360            , key3
361            , valueToAdopt
362            , fBucketList[hashVal]
363            , fMemoryManager
364        );
365#endif
366        fBucketList[hashVal] = newBucket;
367    }
368
369    //
370    //  Give this new one the next available id and add to the pointer list.
371    //  Expand the list if that is now required.
372    //
373    if (fIdCounter + 1 == fIdPtrsCount)
374    {
375        // Create a new count 1.5 times larger and allocate a new array
376        XMLSize_t newCount = (XMLSize_t)(fIdPtrsCount * 1.5);
377        TVal** newArray = (TVal**) fMemoryManager->allocate
378        (
379            newCount * sizeof(TVal*)
380        );//new TVal*[newCount];
381
382        // Copy over the old contents to the new array
383        memcpy(newArray, fIdPtrs, fIdPtrsCount * sizeof(TVal*));
384
385        // Ok, toss the old array and store the new data
386        fMemoryManager->deallocate(fIdPtrs); //delete [] fIdPtrs;
387        fIdPtrs = newArray;
388        fIdPtrsCount = newCount;
389    }
390    const XMLSize_t retId = ++fIdCounter;
391    fIdPtrs[retId] = valueToAdopt;
392
393    // Return the id that we gave to this element
394    return retId;
395}
396
397// ---------------------------------------------------------------------------
398//  DOMDeepNodeListPool: Private methods
399// ---------------------------------------------------------------------------
400template <class TVal> DOMDeepNodeListPoolTableBucketElem<TVal>* DOMDeepNodeListPool<TVal>::
401findBucketElem(const void* const key1, const XMLCh* const key2, const XMLCh* const key3, XMLSize_t& hashVal)
402{
403    // Hash the key
404    hashVal = fHash->getHashVal(key1, fHashModulus, fMemoryManager);
405    if (hashVal > fHashModulus)
406        ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::HshTbl_BadHashFromKey, fMemoryManager);
407
408    // Search that bucket for the key
409    DOMDeepNodeListPoolTableBucketElem<TVal>* curElem = fBucketList[hashVal];
410    while (curElem)
411    {
412        //key2 and key3 are XMLCh*, compareString takes null pointer vs zero len string the same
413        //but we need them to be treated as different keys in this case
414        if (fHash->equals(key1, curElem->fKey1) && (XMLString::equals(key2, curElem->fKey2)) && (XMLString::equals(key3, curElem->fKey3))) {
415            if (!key2 || !curElem->fKey2) {
416                if (key2 || curElem->fKey2) {
417                    curElem = curElem->fNext;
418                    continue;
419                }
420            }
421            if (!key3 || !curElem->fKey3) {
422                if (key3 || curElem->fKey3) {
423                    curElem = curElem->fNext;
424                    continue;
425                }
426            }
427
428            return curElem;
429        }
430
431        curElem = curElem->fNext;
432    }
433    return 0;
434}
435
436template <class TVal> const DOMDeepNodeListPoolTableBucketElem<TVal>* DOMDeepNodeListPool<TVal>::
437findBucketElem(const void* const key1, const XMLCh* const key2, const XMLCh* const key3, XMLSize_t& hashVal) const
438{
439    // Hash the key
440    hashVal = fHash->getHashVal(key1, fHashModulus, fMemoryManager);
441    if (hashVal > fHashModulus)
442        ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::HshTbl_BadHashFromKey, fMemoryManager);
443
444    // Search that bucket for the key
445    const DOMDeepNodeListPoolTableBucketElem<TVal>* curElem = fBucketList[hashVal];
446    while (curElem)
447    {
448        //key2 and key3 are XMLCh*, compareString takes null pointer vs zero len string the same
449        //but we need them to be treated as different keys in this case
450        if (fHash->equals(key1, curElem->fKey1) && (XMLString::equals(key2, curElem->fKey2)) && (XMLString::equals(key3, curElem->fKey3))) {
451            if (!key2 || !curElem->fKey2) {
452                if (key2 || curElem->fKey2) {
453                    curElem = curElem->fNext;
454                    continue;
455                }
456            }
457            if (!key3 || !curElem->fKey3) {
458                if (key3 || curElem->fKey3) {
459                    curElem = curElem->fNext;
460                    continue;
461                }
462            }
463            return curElem;
464        }
465
466        curElem = curElem->fNext;
467    }
468    return 0;
469}
470
471XERCES_CPP_NAMESPACE_END
472
Note: See TracBrowser for help on using the repository browser.