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

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

xerces added

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