source: NonGTP/Xerces/xerces/include/xercesc/util/RefHash3KeysIdPool.c @ 358

Revision 358, 19.4 KB checked in by bittner, 19 years ago (diff)

xerces added

Line 
1/*
2 * Copyright 2001,2004 The Apache Software Foundation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/**
18 * $Log: RefHash3KeysIdPool.c,v $
19 * Revision 1.13  2004/09/08 13:56:22  peiyongz
20 * Apache License Version 2.0
21 *
22 * Revision 1.12  2004/08/30 18:56:21  amassari
23 * Change the order of testing to save some CPU cycles
24 *
25 * Revision 1.11  2004/03/01 15:03:08  peiyongz
26 * new getter: getHashModulus
27 *
28 * Revision 1.10  2004/01/29 11:48:46  cargilld
29 * Code cleanup changes to get rid of various compiler diagnostic messages.
30 *
31 * Revision 1.9  2003/12/17 00:18:35  cargilld
32 * Update to memory management so that the static memory manager (one used to call Initialize) is only for static data.
33 *
34 * Revision 1.8  2003/11/03 22:00:31  peiyongz
35 * RefHashTable-like enumeration accessing added
36 *
37 * Revision 1.7  2003/10/29 16:18:05  peiyongz
38 * size() added and Reset() bug fixed
39 *
40 * Revision 1.6  2003/06/02 15:18:08  neilg
41 * fix for bug #20092; thanks to Berin Lautenbach
42 *
43 * Revision 1.5  2003/05/21 21:08:04  knoaman
44 * gcc 2.95.x is generating an internal error for some template definitions, so
45 * we use the default memory manger in such cases.
46 *
47 * Revision 1.4  2003/05/16 06:01:52  knoaman
48 * Partial implementation of the configurable memory manager.
49 *
50 * Revision 1.3  2003/05/15 19:04:35  knoaman
51 * Partial implementation of the configurable memory manager.
52 *
53 * Revision 1.2  2002/11/04 15:22:04  tng
54 * C++ Namespace Support.
55 *
56 * Revision 1.1.1.1  2002/02/01 22:22:12  peiyongz
57 * sane_include
58 *
59 * Revision 1.4  2001/07/19 18:43:18  peiyongz
60 * fix: detect null poiniter in enumerator's ctor.
61 *
62 * Revision 1.3  2001/06/04 13:45:04  tng
63 * The "hash" argument clashes with STL hash.  Fixed by Pei Yong Zhang.
64 *
65 * Revision 1.2  2001/05/11 13:26:29  tng
66 * Copyright update.
67 *
68 * Revision 1.1  2001/03/21 21:56:12  tng
69 * Schema: Add Schema Grammar, Schema Validator, and split the DTDValidator into DTDValidator, DTDScanner, and DTDGrammar.
70 *
71 */
72
73
74// ---------------------------------------------------------------------------
75//  Include
76// ---------------------------------------------------------------------------
77#if defined(XERCES_TMPLSINC)
78#include <xercesc/util/RefHash3KeysIdPool.hpp>
79#endif
80
81#include <xercesc/util/NullPointerException.hpp>
82
83XERCES_CPP_NAMESPACE_BEGIN
84
85// ---------------------------------------------------------------------------
86//  RefHash3KeysIdPool: Constructors and Destructor
87// ---------------------------------------------------------------------------
88template <class TVal>
89RefHash3KeysIdPool<TVal>::RefHash3KeysIdPool( const unsigned int modulus
90                                            , const bool         adoptElems
91                                            , const unsigned int initSize
92                                            , MemoryManager* const manager) :
93    fMemoryManager(manager)
94    , fAdoptedElems(adoptElems)
95    , fBucketList(0)
96    , fHashModulus(modulus)
97    , fHash(0)
98    , fIdPtrs(0)
99    , fIdPtrsCount(initSize)
100    , fIdCounter(0)
101{
102    initialize(modulus);
103
104    // create default hasher
105#if defined (XML_GCC_VERSION) && (XML_GCC_VERSION < 29600)
106                 fHash = new HashXMLCh();
107#else
108    fHash = new (fMemoryManager) HashXMLCh();
109#endif
110
111    //
112    //  Allocate the initial id pointers array. We don't have to zero them
113    //  out since the fIdCounter value tells us which ones are valid. The
114    //  zeroth element is never used (and represents an invalid pool id.)
115    //
116    if (!fIdPtrsCount)
117        fIdPtrsCount = 256;
118    fIdPtrs = (TVal**) fMemoryManager->allocate(fIdPtrsCount * sizeof(TVal*)); //new TVal*[fIdPtrsCount];
119    fIdPtrs[0] = 0;
120}
121
122template <class TVal>
123RefHash3KeysIdPool<TVal>::RefHash3KeysIdPool( const unsigned int modulus
124                                            , const bool         adoptElems
125                                            , HashBase*          hashBase
126                                            , const unsigned int initSize
127                                            , MemoryManager* const manager) :
128        fMemoryManager(manager)
129    , fAdoptedElems(adoptElems)
130    , fBucketList(0)
131    , fHashModulus(modulus)
132    , fHash(0)
133    , fIdPtrs(0)
134    , fIdPtrsCount(initSize)
135    , fIdCounter(0)
136{
137    initialize(modulus);
138    // set hasher
139    fHash = hashBase;
140
141    //
142    //  Allocate the initial id pointers array. We don't have to zero them
143    //  out since the fIdCounter value tells us which ones are valid. The
144    //  zeroth element is never used (and represents an invalid pool id.)
145    //
146    if (!fIdPtrsCount)
147        fIdPtrsCount = 256;
148    fIdPtrs = (TVal**) fMemoryManager->allocate(fIdPtrsCount * sizeof(TVal*)); //new TVal*[fIdPtrsCount];
149    fIdPtrs[0] = 0;
150}
151
152template <class TVal>
153RefHash3KeysIdPool<TVal>::RefHash3KeysIdPool( const unsigned int modulus
154                                            , const unsigned int initSize
155                                            , MemoryManager* const manager) :
156        fMemoryManager(manager)
157    , fAdoptedElems(true)
158    , fBucketList(0)
159    , fHashModulus(modulus)
160    , fHash(0)
161    , fIdPtrs(0)
162    , fIdPtrsCount(initSize)
163    , fIdCounter(0)
164{
165    initialize(modulus);
166
167    // create default hasher
168
169    fHash = new (fMemoryManager) HashXMLCh();
170
171    //
172    //  Allocate the initial id pointers array. We don't have to zero them
173    //  out since the fIdCounter value tells us which ones are valid. The
174    //  zeroth element is never used (and represents an invalid pool id.)
175    //
176    if (!fIdPtrsCount)
177        fIdPtrsCount = 256;
178    fIdPtrs = (TVal**) fMemoryManager->allocate(fIdPtrsCount * sizeof(TVal*)); //new TVal*[fIdPtrsCount];
179    fIdPtrs[0] = 0;
180}
181
182template <class TVal> void RefHash3KeysIdPool<TVal>::initialize(const unsigned int modulus)
183{
184        if (modulus == 0)
185        ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::HshTbl_ZeroModulus, fMemoryManager);
186
187    // Allocate the bucket list and zero them
188    fBucketList = (RefHash3KeysTableBucketElem<TVal>**) fMemoryManager->allocate
189    (
190        fHashModulus * sizeof(RefHash3KeysTableBucketElem<TVal>*)
191    ); //new RefHash3KeysTableBucketElem<TVal>*[fHashModulus];
192    for (unsigned int index = 0; index < fHashModulus; index++)
193        fBucketList[index] = 0;
194}
195
196template <class TVal> RefHash3KeysIdPool<TVal>::~RefHash3KeysIdPool()
197{
198    removeAll();
199
200    // Then delete the bucket list & hasher & id pointers list
201    fMemoryManager->deallocate(fIdPtrs); //delete [] fIdPtrs;
202    fMemoryManager->deallocate(fBucketList); //delete [] fBucketList;
203    delete fHash;
204}
205
206
207// ---------------------------------------------------------------------------
208//  RefHash3KeysIdPool: Element management
209// ---------------------------------------------------------------------------
210template <class TVal> bool RefHash3KeysIdPool<TVal>::isEmpty() const
211{
212    // Just check the bucket list for non-empty elements
213    for (unsigned int buckInd = 0; buckInd < fHashModulus; buckInd++)
214    {
215        if (fBucketList[buckInd] != 0)
216            return false;
217    }
218    return true;
219}
220
221template <class TVal> bool RefHash3KeysIdPool<TVal>::
222containsKey(const void* const key1, const int key2, const int key3) const
223{
224    unsigned int hashVal;
225    const RefHash3KeysTableBucketElem<TVal>* findIt = findBucketElem(key1, key2, key3, hashVal);
226    return (findIt != 0);
227}
228
229template <class TVal> void RefHash3KeysIdPool<TVal>::removeAll()
230{
231    // Clean up the buckets first
232    for (unsigned int buckInd = 0; buckInd < fHashModulus; buckInd++)
233    {
234        // Get the bucket list head for this entry
235        RefHash3KeysTableBucketElem<TVal>* curElem = fBucketList[buckInd];
236        RefHash3KeysTableBucketElem<TVal>* nextElem;
237        while (curElem)
238        {
239            // Save the next element before we hose this one
240            nextElem = curElem->fNext;
241
242            // If we adopted the data, then delete it too
243            //    (Note:  the userdata hash table instance has data type of void *.
244            //    This will generate compiler warnings here on some platforms, but they
245            //    can be ignored since fAdoptedElements is false.
246            if (fAdoptedElems)
247                delete curElem->fData;
248
249            // Then delete the current element and move forward
250            delete curElem;
251            curElem = nextElem;
252        }
253
254        // Clean out this entry
255        fBucketList[buckInd] = 0;
256    }
257
258    // Reset the id counter
259    fIdCounter = 0;
260}
261
262
263// ---------------------------------------------------------------------------
264//  RefHash3KeysIdPool: Getters
265// ---------------------------------------------------------------------------
266template <class TVal> TVal*
267RefHash3KeysIdPool<TVal>::getByKey(const void* const key1, const int key2, const int key3)
268{
269    unsigned int hashVal;
270    RefHash3KeysTableBucketElem<TVal>* findIt = findBucketElem(key1, key2, key3, hashVal);
271    if (!findIt)
272        return 0;
273    return findIt->fData;
274}
275
276template <class TVal> const TVal*
277RefHash3KeysIdPool<TVal>::getByKey(const void* const key1, const int key2, const int key3) const
278{
279    unsigned int hashVal;
280    const RefHash3KeysTableBucketElem<TVal>* findIt = findBucketElem(key1, key2, key3, hashVal);
281    if (!findIt)
282        return 0;
283    return findIt->fData;
284}
285
286template <class TVal> TVal*
287RefHash3KeysIdPool<TVal>::getById(const unsigned int elemId)
288{
289    // If its either zero or beyond our current id, its an error
290    if (!elemId || (elemId > fIdCounter))
291        ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Pool_InvalidId, fMemoryManager);
292
293    return fIdPtrs[elemId];
294}
295
296template <class TVal> const TVal*
297RefHash3KeysIdPool<TVal>::getById(const unsigned int elemId) const
298{
299    // If its either zero or beyond our current id, its an error
300    if (!elemId || (elemId > fIdCounter))
301        ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Pool_InvalidId, fMemoryManager);
302
303    return fIdPtrs[elemId];
304}
305
306template <class TVal>
307MemoryManager* RefHash3KeysIdPool<TVal>::getMemoryManager() const
308{
309    return fMemoryManager;
310}
311
312template <class TVal>
313unsigned int RefHash3KeysIdPool<TVal>::getHashModulus() const
314{
315    return fHashModulus;
316}
317
318// ---------------------------------------------------------------------------
319//  RefHash3KeysIdPool: Putters
320// ---------------------------------------------------------------------------
321template <class TVal> unsigned int
322RefHash3KeysIdPool<TVal>::put(void* key1, int key2, int key3, TVal* const valueToAdopt)
323{
324    // First see if the key exists already
325    unsigned int hashVal;
326    RefHash3KeysTableBucketElem<TVal>* newBucket = findBucketElem(key1, key2, key3, hashVal);
327
328    //
329    //  If so,then update its value. If not, then we need to add it to
330    //  the right bucket
331    //
332    if (newBucket)
333    {
334        if (fAdoptedElems)
335            delete newBucket->fData;
336        newBucket->fData = valueToAdopt;
337        newBucket->fKey1 = key1;
338        newBucket->fKey2 = key2;
339        newBucket->fKey3 = key3;
340    }
341     else
342    {
343    // Revisit: the gcc compiler 2.95.x is generating an
344    // internal compiler error message. So we use the default
345    // memory manager for now.
346#if defined (XML_GCC_VERSION) && (XML_GCC_VERSION < 29600)
347        newBucket = new RefHash3KeysTableBucketElem<TVal>(key1, key2, key3, valueToAdopt, fBucketList[hashVal]);
348#else
349        newBucket = new (fMemoryManager) RefHash3KeysTableBucketElem<TVal>(key1, key2, key3, valueToAdopt, fBucketList[hashVal]);
350#endif
351        fBucketList[hashVal] = newBucket;
352    }
353
354    //
355    //  Give this new one the next available id and add to the pointer list.
356    //  Expand the list if that is now required.
357    //
358    if (fIdCounter + 1 == fIdPtrsCount)
359    {
360        // Create a new count 1.5 times larger and allocate a new array
361        unsigned int newCount = (unsigned int)(fIdPtrsCount * 1.5);
362        TVal** newArray = (TVal**) fMemoryManager->allocate
363        (
364            newCount * sizeof(TVal*)
365        ); //new TVal*[newCount];
366
367        // Copy over the old contents to the new array
368        memcpy(newArray, fIdPtrs, fIdPtrsCount * sizeof(TVal*));
369
370        // Ok, toss the old array and store the new data
371        fMemoryManager->deallocate(fIdPtrs); //delete [] fIdPtrs;
372        fIdPtrs = newArray;
373        fIdPtrsCount = newCount;
374    }
375    const unsigned int retId = ++fIdCounter;
376    fIdPtrs[retId] = valueToAdopt;
377
378    // Set the id on the passed element
379    valueToAdopt->setId(retId);
380
381    // Return the id that we gave to this element
382    return retId;
383}
384
385// ---------------------------------------------------------------------------
386//  RefHash3KeysIdPool: Private methods
387// ---------------------------------------------------------------------------
388template <class TVal> RefHash3KeysTableBucketElem<TVal>* RefHash3KeysIdPool<TVal>::
389findBucketElem(const void* const key1, const int key2, const int key3, unsigned int& hashVal)
390{
391    // Hash the key
392    hashVal = fHash->getHashVal(key1, fHashModulus, fMemoryManager);
393    if (hashVal > fHashModulus)
394        ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::HshTbl_BadHashFromKey, fMemoryManager);
395
396    // Search that bucket for the key
397    RefHash3KeysTableBucketElem<TVal>* curElem = fBucketList[hashVal];
398    while (curElem)
399    {
400                if (key2==curElem->fKey2 && key3==curElem->fKey3 && fHash->equals(key1, curElem->fKey1))
401            return curElem;
402
403        curElem = curElem->fNext;
404    }
405    return 0;
406}
407
408template <class TVal> const RefHash3KeysTableBucketElem<TVal>* RefHash3KeysIdPool<TVal>::
409findBucketElem(const void* const key1, const int key2, const int key3, unsigned int& hashVal) const
410{
411    // Hash the key
412    hashVal = fHash->getHashVal(key1, fHashModulus);
413    if (hashVal > fHashModulus)
414        ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::HshTbl_BadHashFromKey, fMemoryManager);
415
416    // Search that bucket for the key
417    const RefHash3KeysTableBucketElem<TVal>* curElem = fBucketList[hashVal];
418    while (curElem)
419    {
420        if (fHash->equals(key1, curElem->fKey1) && (key2==curElem->fKey2) && (key3==curElem->fKey3))
421            return curElem;
422
423        curElem = curElem->fNext;
424    }
425    return 0;
426}
427
428
429// ---------------------------------------------------------------------------
430//  RefHash3KeysIdPoolEnumerator: Constructors and Destructor
431// ---------------------------------------------------------------------------
432template <class TVal> RefHash3KeysIdPoolEnumerator<TVal>::
433RefHash3KeysIdPoolEnumerator(RefHash3KeysIdPool<TVal>* const toEnum
434                             , const bool adopt
435                             , MemoryManager* const manager)
436        : fAdoptedElems(adopt), fCurIndex(0), fToEnum(toEnum), fMemoryManager(manager)
437{
438    if (!toEnum)
439        ThrowXMLwithMemMgr(NullPointerException, XMLExcepts::CPtr_PointerIsZero, fMemoryManager);
440
441    Reset();
442    resetKey();
443}
444
445template <class TVal> RefHash3KeysIdPoolEnumerator<TVal>::~RefHash3KeysIdPoolEnumerator()
446{
447    if (fAdoptedElems)
448        delete fToEnum;
449}
450
451template <class TVal> RefHash3KeysIdPoolEnumerator<TVal>::
452RefHash3KeysIdPoolEnumerator(const RefHash3KeysIdPoolEnumerator<TVal>& toCopy) :
453    fAdoptedElems(toCopy.fAdoptedElems)
454    , fCurIndex(toCopy.fCurIndex)
455    , fToEnum(toCopy.fToEnum)
456    , fCurElem(toCopy.fCurElem)
457    , fCurHash(toCopy.fCurHash)   
458    , fMemoryManager(toCopy.fMemoryManager)
459{
460}
461
462// ---------------------------------------------------------------------------
463//  RefHash3KeysIdPoolEnumerator: Enum interface
464// ---------------------------------------------------------------------------
465template <class TVal> bool RefHash3KeysIdPoolEnumerator<TVal>::hasMoreElements() const
466{
467    // If our index is zero or past the end, then we are done
468    if (!fCurIndex || (fCurIndex > fToEnum->fIdCounter))
469        return false;
470    return true;
471}
472
473template <class TVal> TVal& RefHash3KeysIdPoolEnumerator<TVal>::nextElement()
474{
475    // If our index is zero or past the end, then we are done
476    if (!fCurIndex || (fCurIndex > fToEnum->fIdCounter))
477        ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::Enum_NoMoreElements, fMemoryManager);
478
479    // Return the current element and bump the index
480    return *fToEnum->fIdPtrs[fCurIndex++];
481}
482
483template <class TVal> void RefHash3KeysIdPoolEnumerator<TVal>::Reset()
484{
485    //
486    //  Find the next available bucket element in the pool. We use the id
487    //  array since its very easy to enumerator through by just maintaining
488    //  an index. If the id counter is zero, then its empty and we leave the
489    //  current index to zero.
490    //
491    fCurIndex = fToEnum->fIdCounter ? 1:0;
492
493}
494
495template <class TVal> int RefHash3KeysIdPoolEnumerator<TVal>::size() const
496{
497    return fToEnum->fIdCounter;
498}
499
500template <class TVal> void RefHash3KeysIdPoolEnumerator<TVal>::resetKey()
501{
502    fCurHash = (unsigned int)-1;
503    fCurElem = 0;
504    findNext();
505}
506
507template <class TVal> bool RefHash3KeysIdPoolEnumerator<TVal>::hasMoreKeys() const
508{
509    //
510    //  If our current has is at the max and there are no more elements
511    //  in the current bucket, then no more elements.
512    //
513    if (!fCurElem && (fCurHash == fToEnum->fHashModulus))
514        return false;
515
516    return true;
517}
518
519template <class TVal> void RefHash3KeysIdPoolEnumerator<TVal>::nextElementKey(void*& retKey1, int& retKey2, int& retKey3)
520{
521    // Make sure we have an element to return
522    if (!hasMoreKeys())
523        ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::Enum_NoMoreElements, fMemoryManager);
524
525    //
526    //  Save the current element, then move up to the next one for the
527    //  next time around.
528    //
529    RefHash3KeysTableBucketElem<TVal>* saveElem = fCurElem;
530    findNext();
531
532    retKey1 = saveElem->fKey1;
533    retKey2 = saveElem->fKey2;
534    retKey3 = saveElem->fKey3;
535
536    return;
537}
538
539template <class TVal> void RefHash3KeysIdPoolEnumerator<TVal>::findNext()
540{
541    //
542    //  If there is a current element, move to its next element. If this
543    //  hits the end of the bucket, the next block will handle the rest.
544    //
545    if (fCurElem)
546        fCurElem = fCurElem->fNext;
547
548    //
549    //  If the current element is null, then we have to move up to the
550    //  next hash value. If that is the hash modulus, then we cannot
551    //  go further.
552    //
553    if (!fCurElem)
554    {
555        fCurHash++;
556        if (fCurHash == fToEnum->fHashModulus)
557            return;
558
559        // Else find the next non-empty bucket
560        while (true)
561        {
562            if (fToEnum->fBucketList[fCurHash])
563                break;
564
565            // Bump to the next hash value. If we max out return
566            fCurHash++;
567            if (fCurHash == fToEnum->fHashModulus)
568                return;
569        }
570        fCurElem = fToEnum->fBucketList[fCurHash];
571    }
572}
573
574XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.