source: NonGTP/Xerces/xercesc/util/ValueHashTableOf.c @ 188

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