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

Revision 188, 15.7 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) 1999-2000 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: NameIdPool.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/10/29 16:18:05  peiyongz
63 * size() added and Reset() bug fixed
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:04:35  knoaman
69 * Partial implementation of the configurable memory manager.
70 *
71 * Revision 1.4  2002/11/04 15:22:04  tng
72 * C++ Namespace Support.
73 *
74 * Revision 1.3  2002/09/24 19:51:24  tng
75 * Performance: use XMLString::equals instead of XMLString::compareString
76 *
77 * Revision 1.2  2002/05/08 19:05:29  knoaman
78 * [Bug 7701] NameIdPoolEnumerator copy constructor should call base class - fix by Martin Kalen
79 *
80 * Revision 1.1.1.1  2002/02/01 22:22:11  peiyongz
81 * sane_include
82 *
83 * Revision 1.3  2000/03/02 19:54:42  roddey
84 * This checkin includes many changes done while waiting for the
85 * 1.1.0 code to be finished. I can't list them all here, but a list is
86 * available elsewhere.
87 *
88 * Revision 1.2  2000/02/06 07:48:02  rahulj
89 * Year 2K copyright swat.
90 *
91 * Revision 1.1.1.1  1999/11/09 01:04:47  twl
92 * Initial checkin
93 *
94 * Revision 1.3  1999/11/08 20:45:10  rahul
95 * Swat for adding in Product name and CVS comment log variable.
96 *
97 */
98
99
100// ---------------------------------------------------------------------------
101//  Includes
102// ---------------------------------------------------------------------------
103#if defined(XERCES_TMPLSINC)
104#include <xercesc/util/NameIdPool.hpp>
105#endif
106
107#include <xercesc/util/IllegalArgumentException.hpp>
108#include <xercesc/util/NoSuchElementException.hpp>
109#include <xercesc/util/RuntimeException.hpp>
110
111XERCES_CPP_NAMESPACE_BEGIN
112
113// ---------------------------------------------------------------------------
114//  NameIdPoolBucketElem: Constructors and Destructor
115// ---------------------------------------------------------------------------
116template <class TElem> NameIdPoolBucketElem<TElem>::
117NameIdPoolBucketElem(TElem* const                           value
118                    , NameIdPoolBucketElem<TElem>* const    next) :
119    fData(value)
120    , fNext(next)
121{
122}
123
124template <class TElem> NameIdPoolBucketElem<TElem>::~NameIdPoolBucketElem()
125{
126    // Nothing to do
127}
128
129
130// ---------------------------------------------------------------------------
131//  NameIdPool: Constructors and Destructor
132// ---------------------------------------------------------------------------
133template <class TElem>
134NameIdPool<TElem>::NameIdPool( const unsigned int hashModulus
135                             , const unsigned int initSize
136                             , MemoryManager* const manager) :
137    fMemoryManager(manager)
138    , fBucketList(0)
139    , fIdPtrs(0)
140    , fIdPtrsCount(initSize)
141    , fIdCounter(0)
142    , fHashModulus(hashModulus)
143{
144    if (!fHashModulus)
145        ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Pool_ZeroModulus, fMemoryManager);
146
147    // Allocate the bucket list and zero them
148    fBucketList = (NameIdPoolBucketElem<TElem>**) fMemoryManager->allocate
149    (
150        fHashModulus * sizeof(NameIdPoolBucketElem<TElem>*)
151    ); //new NameIdPoolBucketElem<TElem>*[fHashModulus];
152    for (unsigned int index = 0; index < fHashModulus; index++)
153        fBucketList[index] = 0;
154
155    //
156    //  Allocate the initial id pointers array. We don't have to zero them
157    //  out since the fIdCounter value tells us which ones are valid. The
158    //  zeroth element is never used (and represents an invalid pool id.)
159    //
160    if (!fIdPtrsCount)
161        fIdPtrsCount = 256;
162    fIdPtrs = (TElem**) fMemoryManager->allocate
163    (
164        fIdPtrsCount * sizeof(TElem*)
165    ); //new TElem*[fIdPtrsCount];
166    fIdPtrs[0] = 0;
167}
168
169template <class TElem> NameIdPool<TElem>::~NameIdPool()
170{
171    //
172    //  Delete the id pointers list. The stuff it points to will be cleaned
173    //  up when we clean the bucket lists.
174    //
175    fMemoryManager->deallocate(fIdPtrs); //delete [] fIdPtrs;
176
177    // Remove all elements then delete the bucket list
178    removeAll();
179    fMemoryManager->deallocate(fBucketList); //delete [] fBucketList;
180}
181
182
183// ---------------------------------------------------------------------------
184//  NameIdPool: Element management
185// ---------------------------------------------------------------------------
186template <class TElem> bool
187NameIdPool<TElem>::containsKey(const XMLCh* const key) const
188{
189    unsigned int hashVal;
190    const NameIdPoolBucketElem<TElem>* findIt = findBucketElem(key, hashVal);
191    return (findIt != 0);
192}
193
194
195template <class TElem> void NameIdPool<TElem>::removeAll()
196{
197    // Clean up the buckets first
198    for (unsigned int buckInd = 0; buckInd < fHashModulus; buckInd++)
199    {
200        NameIdPoolBucketElem<TElem>* curElem = fBucketList[buckInd];
201        NameIdPoolBucketElem<TElem>* nextElem;
202        while (curElem)
203        {
204            // Save the next element before we hose this one
205            nextElem = curElem->fNext;
206
207            delete curElem->fData;
208            delete curElem;
209
210            curElem = nextElem;
211        }
212
213        // Empty out the bucket
214        fBucketList[buckInd] = 0;
215    }
216
217    // Reset the id counter
218    fIdCounter = 0;
219}
220
221
222// ---------------------------------------------------------------------------
223//  NameIdPool: Getters
224// ---------------------------------------------------------------------------
225template <class TElem> TElem*
226NameIdPool<TElem>::getByKey(const XMLCh* const key)
227{
228    unsigned int hashVal;
229    NameIdPoolBucketElem<TElem>* findIt = findBucketElem(key, hashVal);
230    if (!findIt)
231        return 0;
232    return findIt->fData;
233}
234
235template <class TElem> const TElem*
236NameIdPool<TElem>::getByKey(const XMLCh* const key) const
237{
238    unsigned int hashVal;
239    const NameIdPoolBucketElem<TElem>* findIt = findBucketElem(key, hashVal);
240    if (!findIt)
241        return 0;
242    return findIt->fData;
243}
244
245template <class TElem> TElem*
246NameIdPool<TElem>::getById(const unsigned int elemId)
247{
248    // If its either zero or beyond our current id, its an error
249    if (!elemId || (elemId > fIdCounter))
250        ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Pool_InvalidId, fMemoryManager);
251
252    return fIdPtrs[elemId];
253}
254
255template <class TElem>
256const TElem* NameIdPool<TElem>::getById(const unsigned int elemId) const
257{
258    // If its either zero or beyond our current id, its an error
259    if (!elemId || (elemId > fIdCounter))
260        ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Pool_InvalidId, fMemoryManager);
261
262    return fIdPtrs[elemId];
263}
264
265template <class TElem>
266MemoryManager* NameIdPool<TElem>::getMemoryManager() const
267{
268    return fMemoryManager;
269}
270
271// ---------------------------------------------------------------------------
272//  NameIdPool: Setters
273// ---------------------------------------------------------------------------
274template <class TElem>
275unsigned int NameIdPool<TElem>::put(TElem* const elemToAdopt)
276{
277    // First see if the key exists already. If so, its an error
278    unsigned int hashVal;
279    if (findBucketElem(elemToAdopt->getKey(), hashVal))
280    {
281        ThrowXMLwithMemMgr1
282        (
283            IllegalArgumentException
284            , XMLExcepts::Pool_ElemAlreadyExists
285            , elemToAdopt->getKey()
286            , fMemoryManager
287        );
288    }
289
290    // Create a new bucket element and add it to the appropriate list
291    NameIdPoolBucketElem<TElem>* newBucket = new (fMemoryManager) NameIdPoolBucketElem<TElem>
292    (
293        elemToAdopt
294        , fBucketList[hashVal]
295    );
296    fBucketList[hashVal] = newBucket;
297
298    //
299    //  Give this new one the next available id and add to the pointer list.
300    //  Expand the list if that is now required.
301    //
302    if (fIdCounter + 1 == fIdPtrsCount)
303    {
304        // Create a new count 1.5 times larger and allocate a new array
305        unsigned int newCount = (unsigned int)(fIdPtrsCount * 1.5);
306        TElem** newArray = (TElem**) fMemoryManager->allocate
307        (
308            newCount * sizeof(TElem*)
309        ); //new TElem*[newCount];
310
311        // Copy over the old contents to the new array
312        memcpy(newArray, fIdPtrs, fIdPtrsCount * sizeof(TElem*));
313
314        // Ok, toss the old array and store the new data
315        fMemoryManager->deallocate(fIdPtrs); //delete [] fIdPtrs;
316        fIdPtrs = newArray;
317        fIdPtrsCount = newCount;
318    }
319    const unsigned int retId = ++fIdCounter;
320    fIdPtrs[retId] = elemToAdopt;
321
322    // Set the id on the passed element
323    elemToAdopt->setId(retId);
324
325    // Return the id that we gave to this element
326    return retId;
327}
328
329
330// ---------------------------------------------------------------------------
331//  NameIdPool: Private methods
332// ---------------------------------------------------------------------------
333template <class TElem>
334NameIdPoolBucketElem<TElem>* NameIdPool<TElem>::
335findBucketElem(const XMLCh* const key, unsigned int& hashVal)
336{
337    // Hash the key
338    hashVal = XMLString::hash(key, fHashModulus, fMemoryManager);
339
340    if (hashVal > fHashModulus)
341        ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Pool_BadHashFromKey, fMemoryManager);
342
343    // Search that bucket for the key
344    NameIdPoolBucketElem<TElem>* curElem = fBucketList[hashVal];
345    while (curElem)
346    {
347        if (XMLString::equals(key, curElem->fData->getKey()))
348            return curElem;
349        curElem = curElem->fNext;
350    }
351    return 0;
352}
353
354template <class TElem>
355const NameIdPoolBucketElem<TElem>* NameIdPool<TElem>::
356findBucketElem(const XMLCh* const key, unsigned int& hashVal) const
357{
358    // Hash the key
359    hashVal = XMLString::hash(key, fHashModulus, fMemoryManager);
360
361    if (hashVal > fHashModulus)
362        ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Pool_BadHashFromKey, fMemoryManager);
363
364    // Search that bucket for the key
365    const NameIdPoolBucketElem<TElem>* curElem = fBucketList[hashVal];
366    while (curElem)
367    {
368        if (XMLString::equals(key, curElem->fData->getKey()))
369            return curElem;
370
371        curElem = curElem->fNext;
372    }
373    return 0;
374}
375
376
377
378// ---------------------------------------------------------------------------
379//  NameIdPoolEnumerator: Constructors and Destructor
380// ---------------------------------------------------------------------------
381template <class TElem> NameIdPoolEnumerator<TElem>::
382NameIdPoolEnumerator(NameIdPool<TElem>* const toEnum
383                     , MemoryManager* const manager) :
384
385    XMLEnumerator<TElem>()
386    , fCurIndex(0)
387    , fToEnum(toEnum)
388    , fMemoryManager(manager)
389{
390        Reset();
391}
392
393template <class TElem> NameIdPoolEnumerator<TElem>::
394NameIdPoolEnumerator(const NameIdPoolEnumerator<TElem>& toCopy) :
395
396    fCurIndex(toCopy.fCurIndex)
397    , fToEnum(toCopy.fToEnum)
398    , fMemoryManager(toCopy.fMemoryManager)
399{
400}
401
402template <class TElem> NameIdPoolEnumerator<TElem>::~NameIdPoolEnumerator()
403{
404    // We don't own the pool being enumerated, so no cleanup required
405}
406
407
408// ---------------------------------------------------------------------------
409//  NameIdPoolEnumerator: Public operators
410// ---------------------------------------------------------------------------
411template <class TElem> NameIdPoolEnumerator<TElem>& NameIdPoolEnumerator<TElem>::
412operator=(const NameIdPoolEnumerator<TElem>& toAssign)
413{
414    if (this == &toAssign)
415        return *this;
416    fMemoryManager = toAssign.fMemoryManager;
417    fCurIndex      = toAssign.fCurIndex;
418    fToEnum        = toAssign.fToEnum;
419    return *this;
420}
421
422// ---------------------------------------------------------------------------
423//  NameIdPoolEnumerator: Enum interface
424// ---------------------------------------------------------------------------
425template <class TElem> bool NameIdPoolEnumerator<TElem>::
426hasMoreElements() const
427{
428    // If our index is zero or past the end, then we are done
429    if (!fCurIndex || (fCurIndex > fToEnum->fIdCounter))
430        return false;
431    return true;
432}
433
434template <class TElem> TElem& NameIdPoolEnumerator<TElem>::nextElement()
435{
436    // If our index is zero or past the end, then we are done
437    if (!fCurIndex || (fCurIndex > fToEnum->fIdCounter))
438        ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::Enum_NoMoreElements, fMemoryManager);
439
440    // Return the current element and bump the index
441    return *fToEnum->fIdPtrs[fCurIndex++];
442}
443
444
445template <class TElem> void NameIdPoolEnumerator<TElem>::Reset()
446{
447    //
448    //  Find the next available bucket element in the pool. We use the id
449    //  array since its very easy to enumerator through by just maintaining
450    //  an index. If the id counter is zero, then its empty and we leave the
451    //  current index to zero.
452    //
453    fCurIndex = fToEnum->fIdCounter ? 1:0;
454}
455
456template <class TElem> int NameIdPoolEnumerator<TElem>::size() const
457{
458    return fToEnum->fIdCounter;
459}
460
461XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.