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

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