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

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

xerces added

Line 
1/*
2 * Copyright 2002,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: ValueHashTableOf.c,v $
19 * Revision 1.9  2004/09/08 13:56:23  peiyongz
20 * Apache License Version 2.0
21 *
22 * Revision 1.8  2003/12/17 00:18:35  cargilld
23 * Update to memory management so that the static memory manager (one used to call Initialize) is only for static data.
24 *
25 * Revision 1.7  2003/12/16 18:37:14  knoaman
26 * Add nextElementKey method
27 *
28 * Revision 1.6  2003/05/16 06:01:52  knoaman
29 * Partial implementation of the configurable memory manager.
30 *
31 * Revision 1.5  2003/05/15 19:07:46  knoaman
32 * Partial implementation of the configurable memory manager.
33 *
34 * Revision 1.4  2002/11/04 15:22:05  tng
35 * C++ Namespace Support.
36 *
37 * Revision 1.3  2002/05/24 19:46:40  knoaman
38 * Initial checkin.
39 *
40 */
41
42
43// ---------------------------------------------------------------------------
44//  Include
45// ---------------------------------------------------------------------------
46#if defined(XERCES_TMPLSINC)
47#include <xercesc/util/ValueHashTableOf.hpp>
48#endif
49
50#include <xercesc/util/NullPointerException.hpp>
51
52XERCES_CPP_NAMESPACE_BEGIN
53
54// ---------------------------------------------------------------------------
55//  ValueHashTableOf: Constructors and Destructor
56// ---------------------------------------------------------------------------
57template <class TVal>
58ValueHashTableOf<TVal>::ValueHashTableOf( const unsigned int modulus
59                                        , HashBase* hashBase
60                                        , MemoryManager* const manager)
61    : fMemoryManager(manager)
62    , fBucketList(0)
63    , fHashModulus(modulus)
64    , fHash(0)
65{
66        initialize(modulus);
67        // set hasher
68        fHash = hashBase;
69}
70
71template <class TVal>
72ValueHashTableOf<TVal>::ValueHashTableOf( const unsigned int modulus
73                                        , MemoryManager* const manager)
74        : fMemoryManager(manager)
75    , fBucketList(0)
76    , fHashModulus(modulus)
77    , fHash(0)
78{
79        initialize(modulus);
80
81        // create default hasher
82        fHash = new (fMemoryManager) HashXMLCh();
83}
84
85template <class TVal> void ValueHashTableOf<TVal>::initialize(const unsigned int modulus)
86{
87        if (modulus == 0)
88        ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::HshTbl_ZeroModulus, fMemoryManager);
89
90    // Allocate the bucket list and zero them
91    fBucketList = (ValueHashTableBucketElem<TVal>**) fMemoryManager->allocate
92    (
93        fHashModulus * sizeof(ValueHashTableBucketElem<TVal>*)
94    ); //new ValueHashTableBucketElem<TVal>*[fHashModulus];
95    for (unsigned int index = 0; index < fHashModulus; index++)
96        fBucketList[index] = 0;
97}
98
99template <class TVal> ValueHashTableOf<TVal>::~ValueHashTableOf()
100{
101    removeAll();
102
103    // Then delete the bucket list & hasher
104    fMemoryManager->deallocate(fBucketList); //delete [] fBucketList;
105        delete fHash;
106}
107
108
109// ---------------------------------------------------------------------------
110//  ValueHashTableOf: Element management
111// ---------------------------------------------------------------------------
112template <class TVal> bool ValueHashTableOf<TVal>::isEmpty() const
113{
114    // Just check the bucket list for non-empty elements
115    for (unsigned int buckInd = 0; buckInd < fHashModulus; buckInd++)
116    {
117        if (fBucketList[buckInd] != 0)
118            return false;
119    }
120    return true;
121}
122
123template <class TVal> bool ValueHashTableOf<TVal>::
124containsKey(const void* const key) const
125{
126    unsigned int hashVal;
127    const ValueHashTableBucketElem<TVal>* findIt = findBucketElem(key, hashVal);
128    return (findIt != 0);
129}
130
131template <class TVal> void ValueHashTableOf<TVal>::
132removeKey(const void* const key)
133{
134    unsigned int hashVal;
135    removeBucketElem(key, hashVal);
136}
137
138template <class TVal> void ValueHashTableOf<TVal>::removeAll()
139{
140    // Clean up the buckets first
141    for (unsigned int buckInd = 0; buckInd < fHashModulus; buckInd++)
142    {
143        // Get the bucket list head for this entry
144        ValueHashTableBucketElem<TVal>* curElem = fBucketList[buckInd];
145        ValueHashTableBucketElem<TVal>* nextElem;
146        while (curElem)
147        {
148            // Save the next element before we hose this one
149            nextElem = curElem->fNext;
150
151            // delete the current element and move forward
152            delete curElem;
153            curElem = nextElem;
154        }
155
156        // Clean out this entry
157        fBucketList[buckInd] = 0;
158    }
159}
160
161
162// ---------------------------------------------------------------------------
163//  ValueHashTableOf: Getters
164// ---------------------------------------------------------------------------
165template <class TVal> TVal& ValueHashTableOf<TVal>::get(const void* const key, MemoryManager* const manager)
166{
167    unsigned int hashVal;
168    ValueHashTableBucketElem<TVal>* findIt = findBucketElem(key, hashVal);
169    if (!findIt)
170        ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::HshTbl_NoSuchKeyExists, manager);
171
172    return findIt->fData;
173}
174
175template <class TVal> const TVal& ValueHashTableOf<TVal>::
176get(const void* const key) const
177{
178    unsigned int hashVal;
179    const ValueHashTableBucketElem<TVal>* findIt = findBucketElem(key, hashVal);
180    if (!findIt)
181        ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::HshTbl_NoSuchKeyExists, fMemoryManager);
182
183    return findIt->fData;
184}
185
186
187// ---------------------------------------------------------------------------
188//  ValueHashTableOf: Putters
189// ---------------------------------------------------------------------------
190template <class TVal> void ValueHashTableOf<TVal>::put(void* key, const TVal& valueToAdopt)
191{
192    // First see if the key exists already
193    unsigned int hashVal;
194    ValueHashTableBucketElem<TVal>* newBucket = findBucketElem(key, hashVal);
195
196    //
197    //  If so,then update its value. If not, then we need to add it to
198    //  the right bucket
199    //
200    if (newBucket)
201    {
202        newBucket->fData = valueToAdopt;
203                newBucket->fKey = key;
204    }
205     else
206    {
207        newBucket = new (fMemoryManager) ValueHashTableBucketElem<TVal>(key, valueToAdopt, fBucketList[hashVal]);
208        fBucketList[hashVal] = newBucket;
209    }
210}
211
212
213
214// ---------------------------------------------------------------------------
215//  ValueHashTableOf: Private methods
216// ---------------------------------------------------------------------------
217template <class TVal> ValueHashTableBucketElem<TVal>* ValueHashTableOf<TVal>::
218findBucketElem(const void* const key, unsigned int& hashVal)
219{
220    // Hash the key
221    hashVal = fHash->getHashVal(key, fHashModulus, fMemoryManager);
222    if (hashVal > fHashModulus)
223        ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::HshTbl_BadHashFromKey, fMemoryManager);
224
225    // Search that bucket for the key
226    ValueHashTableBucketElem<TVal>* curElem = fBucketList[hashVal];
227    while (curElem)
228    {
229                if (fHash->equals(key, curElem->fKey))
230            return curElem;
231
232        curElem = curElem->fNext;
233    }
234    return 0;
235}
236
237template <class TVal> const ValueHashTableBucketElem<TVal>* ValueHashTableOf<TVal>::
238findBucketElem(const void* const key, unsigned int& hashVal) const
239{
240    // Hash the key
241    hashVal = fHash->getHashVal(key, fHashModulus, fMemoryManager);
242    if (hashVal > fHashModulus)
243        ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::HshTbl_BadHashFromKey, fMemoryManager);
244
245    // Search that bucket for the key
246    const ValueHashTableBucketElem<TVal>* curElem = fBucketList[hashVal];
247    while (curElem)
248    {
249        if (fHash->equals(key, curElem->fKey))
250            return curElem;
251
252        curElem = curElem->fNext;
253    }
254    return 0;
255}
256
257
258template <class TVal> void ValueHashTableOf<TVal>::
259removeBucketElem(const void* const key, unsigned int& hashVal)
260{
261    // Hash the key
262    hashVal = fHash->getHashVal(key, fHashModulus);
263    if (hashVal > fHashModulus)
264        ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::HshTbl_BadHashFromKey, fMemoryManager);
265
266    //
267    //  Search the given bucket for this key. Keep up with the previous
268    //  element so we can patch around it.
269    //
270    ValueHashTableBucketElem<TVal>* curElem = fBucketList[hashVal];
271    ValueHashTableBucketElem<TVal>* lastElem = 0;
272
273    while (curElem)
274    {
275        if (fHash->equals(key, curElem->fKey))
276        {
277            if (!lastElem)
278            {
279                // It was the first in the bucket
280                fBucketList[hashVal] = curElem->fNext;
281            }
282             else
283            {
284                // Patch around the current element
285                lastElem->fNext = curElem->fNext;
286            }
287
288            // Delete the current element
289            delete curElem;
290
291            return;
292        }
293
294        // Move both pointers upwards
295        lastElem = curElem;
296        curElem = curElem->fNext;
297    }
298
299    // We never found that key
300    ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::HshTbl_NoSuchKeyExists, fMemoryManager);
301}
302
303
304
305
306// ---------------------------------------------------------------------------
307//  ValueHashTableOfEnumerator: Constructors and Destructor
308// ---------------------------------------------------------------------------
309template <class TVal> ValueHashTableOfEnumerator<TVal>::
310ValueHashTableOfEnumerator(ValueHashTableOf<TVal>* const toEnum
311                           , const bool adopt
312                           , MemoryManager* const manager)
313        : fAdopted(adopt), fCurElem(0), fCurHash((unsigned int)-1), fToEnum(toEnum), fMemoryManager(manager)
314{
315    if (!toEnum)
316        ThrowXMLwithMemMgr(NullPointerException, XMLExcepts::CPtr_PointerIsZero, manager);
317
318    //
319    //  Find the next available bucket element in the hash table. If it
320    //  comes back zero, that just means the table is empty.
321    //
322    //  Note that the -1 in the current hash tells it to start from the
323    //  beginning.
324    //
325    findNext();
326}
327
328template <class TVal> ValueHashTableOfEnumerator<TVal>::~ValueHashTableOfEnumerator()
329{
330    if (fAdopted)
331        delete fToEnum;
332}
333
334
335// ---------------------------------------------------------------------------
336//  ValueHashTableOfEnumerator: Enum interface
337// ---------------------------------------------------------------------------
338template <class TVal> bool ValueHashTableOfEnumerator<TVal>::hasMoreElements() const
339{
340    //
341    //  If our current has is at the max and there are no more elements
342    //  in the current bucket, then no more elements.
343    //
344    if (!fCurElem && (fCurHash == fToEnum->fHashModulus))
345        return false;
346    return true;
347}
348
349template <class TVal> TVal& ValueHashTableOfEnumerator<TVal>::nextElement()
350{
351    // Make sure we have an element to return
352    if (!hasMoreElements())
353        ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::Enum_NoMoreElements, fMemoryManager);
354
355    //
356    //  Save the current element, then move up to the next one for the
357    //  next time around.
358    //
359    ValueHashTableBucketElem<TVal>* saveElem = fCurElem;
360    findNext();
361
362    return saveElem->fData;
363}
364
365template <class TVal> void* ValueHashTableOfEnumerator<TVal>::nextElementKey()
366{
367    // Make sure we have an element to return
368    if (!hasMoreElements())
369        ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::Enum_NoMoreElements, fMemoryManager);
370
371    //
372    //  Save the current element, then move up to the next one for the
373    //  next time around.
374    //
375    ValueHashTableBucketElem<TVal>* saveElem = fCurElem;
376    findNext();
377
378    return saveElem->fKey;
379}
380
381
382template <class TVal> void ValueHashTableOfEnumerator<TVal>::Reset()
383{
384    fCurHash = (unsigned int)-1;
385    fCurElem = 0;
386    findNext();
387}
388
389
390
391// ---------------------------------------------------------------------------
392//  ValueHashTableOfEnumerator: Private helper methods
393// ---------------------------------------------------------------------------
394template <class TVal> void ValueHashTableOfEnumerator<TVal>::findNext()
395{
396    //
397    //  If there is a current element, move to its next element. If this
398    //  hits the end of the bucket, the next block will handle the rest.
399    //
400    if (fCurElem)
401        fCurElem = fCurElem->fNext;
402
403    //
404    //  If the current element is null, then we have to move up to the
405    //  next hash value. If that is the hash modulus, then we cannot
406    //  go further.
407    //
408    if (!fCurElem)
409    {
410        fCurHash++;
411        if (fCurHash == fToEnum->fHashModulus)
412            return;
413
414        // Else find the next non-empty bucket
415        while (true)
416        {
417            if (fToEnum->fBucketList[fCurHash])
418                break;
419
420            // Bump to the next hash value. If we max out return
421            fCurHash++;
422            if (fCurHash == fToEnum->fHashModulus)
423                return;
424        }
425        fCurElem = fToEnum->fBucketList[fCurHash];
426    }
427}
428
429XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.