GME  13
NameIdPool.c
Go to the documentation of this file.
00001 /*
00002  * Licensed to the Apache Software Foundation (ASF) under one or more
00003  * contributor license agreements.  See the NOTICE file distributed with
00004  * this work for additional information regarding copyright ownership.
00005  * The ASF licenses this file to You under the Apache License, Version 2.0
00006  * (the "License"); you may not use this file except in compliance with
00007  * the License.  You may obtain a copy of the License at
00008  *
00009  *      http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 /*
00019  * $Id: NameIdPool.c 883368 2009-11-23 15:28:19Z amassari $
00020  */
00021 
00022 
00023 // ---------------------------------------------------------------------------
00024 //  Includes
00025 // ---------------------------------------------------------------------------
00026 #if defined(XERCES_TMPLSINC)
00027 #include <xercesc/util/NameIdPool.hpp>
00028 #endif
00029 
00030 #include <xercesc/util/IllegalArgumentException.hpp>
00031 #include <xercesc/util/NoSuchElementException.hpp>
00032 #include <xercesc/util/RuntimeException.hpp>
00033 #include <new>
00034 #include <assert.h>
00035 
00036 XERCES_CPP_NAMESPACE_BEGIN
00037 
00038 // ---------------------------------------------------------------------------
00039 //  NameIdPool: Constructors and Destructor
00040 // ---------------------------------------------------------------------------
00041 template <class TElem>
00042 NameIdPool<TElem>::NameIdPool( const XMLSize_t      hashModulus
00043                              , const XMLSize_t      initSize
00044                              , MemoryManager* const manager) :
00045     fMemoryManager(manager)
00046     , fIdPtrs(0)
00047     , fIdPtrsCount(initSize)
00048     , fIdCounter(0)
00049     , fBucketList(hashModulus, manager)
00050 {
00051     if (!hashModulus)
00052         ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Pool_ZeroModulus, fMemoryManager);
00053 
00054     //
00055     //  Allocate the initial id pointers array. We don't have to zero them
00056     //  out since the fIdCounter value tells us which ones are valid. The
00057     //  zeroth element is never used (and represents an invalid pool id.)
00058     //
00059     if (!fIdPtrsCount)
00060         fIdPtrsCount = 256;
00061     fIdPtrs = (TElem**) fMemoryManager->allocate
00062     (
00063         fIdPtrsCount * sizeof(TElem*)
00064     );
00065     fIdPtrs[0] = 0;
00066 }
00067 
00068 template <class TElem> NameIdPool<TElem>::~NameIdPool()
00069 {
00070     //
00071     //  Delete the id pointers list. The stuff it points to will be cleaned
00072     //  up when we clean the bucket lists.
00073     //
00074     fMemoryManager->deallocate(fIdPtrs); //delete [] fIdPtrs;
00075 }
00076 
00077 
00078 // ---------------------------------------------------------------------------
00079 //  NameIdPool: Element management
00080 // ---------------------------------------------------------------------------
00081 template <class TElem>
00082 inline bool NameIdPool<TElem>::
00083 containsKey(const XMLCh* const key) const
00084 {
00085     if (fIdCounter == 0) return false;
00086     return fBucketList.containsKey(key);
00087 }
00088 
00089 
00090 template <class TElem> void NameIdPool<TElem>::removeAll()
00091 {
00092     if (fIdCounter == 0) return;
00093 
00094     fBucketList.removeAll();
00095 
00096     // Reset the id counter
00097     fIdCounter = 0;
00098 }
00099 
00100 
00101 // ---------------------------------------------------------------------------
00102 //  NameIdPool: Getters
00103 // ---------------------------------------------------------------------------
00104 template <class TElem>
00105 inline TElem* NameIdPool<TElem>::
00106 getByKey(const XMLCh* const key)
00107 {
00108     if (fIdCounter == 0) return 0;
00109     return fBucketList.get(key);
00110 }
00111 
00112 template <class TElem>
00113 inline const TElem* NameIdPool<TElem>::
00114 getByKey(const XMLCh* const key) const
00115 {
00116     if (fIdCounter == 0) return 0;
00117     return fBucketList.get(key);
00118 }
00119 
00120 template <class TElem>
00121 inline TElem* NameIdPool<TElem>::
00122 getById(const XMLSize_t elemId)
00123 {
00124     // If its either zero or beyond our current id, its an error
00125     if (!elemId || (elemId > fIdCounter))
00126         ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Pool_InvalidId, fMemoryManager);
00127 
00128     return fIdPtrs[elemId];
00129 }
00130 
00131 template <class TElem>
00132 inline const TElem* NameIdPool<TElem>::
00133 getById(const XMLSize_t elemId) const
00134 {
00135     // If its either zero or beyond our current id, its an error
00136     if (!elemId || (elemId > fIdCounter))
00137         ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::Pool_InvalidId, fMemoryManager);
00138 
00139     return fIdPtrs[elemId];
00140 }
00141 
00142 template <class TElem>
00143 inline MemoryManager* NameIdPool<TElem>::getMemoryManager() const
00144 {
00145     return fMemoryManager;
00146 }
00147 
00148 // ---------------------------------------------------------------------------
00149 //  NameIdPool: Setters
00150 // ---------------------------------------------------------------------------
00151 template <class TElem>
00152 XMLSize_t NameIdPool<TElem>::put(TElem* const elemToAdopt)
00153 {
00154     // First see if the key exists already. If so, its an error
00155     if(containsKey(elemToAdopt->getKey()))
00156     {
00157         ThrowXMLwithMemMgr1
00158         (
00159             IllegalArgumentException
00160             , XMLExcepts::Pool_ElemAlreadyExists
00161             , elemToAdopt->getKey()
00162             , fMemoryManager
00163         );
00164     }
00165 
00166     fBucketList.put((void*)elemToAdopt->getKey(), elemToAdopt);
00167 
00168     //
00169     //  Give this new one the next available id and add to the pointer list.
00170     //  Expand the list if that is now required.
00171     //
00172     if (fIdCounter + 1 == fIdPtrsCount)
00173     {
00174         // Create a new count 1.5 times larger and allocate a new array
00175         XMLSize_t newCount = (XMLSize_t)(fIdPtrsCount * 1.5);
00176         TElem** newArray = (TElem**) fMemoryManager->allocate
00177         (
00178             newCount * sizeof(TElem*)
00179         ); //new TElem*[newCount];
00180 
00181         // Copy over the old contents to the new array
00182         memcpy(newArray, fIdPtrs, fIdPtrsCount * sizeof(TElem*));
00183 
00184         // Ok, toss the old array and store the new data
00185         fMemoryManager->deallocate(fIdPtrs); //delete [] fIdPtrs;
00186         fIdPtrs = newArray;
00187         fIdPtrsCount = newCount;
00188     }
00189     const XMLSize_t retId = ++fIdCounter;
00190     fIdPtrs[retId] = elemToAdopt;
00191 
00192     // Set the id on the passed element
00193     elemToAdopt->setId(retId);
00194 
00195     // Return the id that we gave to this element
00196     return retId;
00197 }
00198 
00199 
00200 // ---------------------------------------------------------------------------
00201 //  NameIdPoolEnumerator: Constructors and Destructor
00202 // ---------------------------------------------------------------------------
00203 template <class TElem> NameIdPoolEnumerator<TElem>::
00204 NameIdPoolEnumerator(NameIdPool<TElem>* const toEnum
00205                      , MemoryManager* const manager) :
00206 
00207     XMLEnumerator<TElem>()
00208     , fCurIndex(0)
00209     , fToEnum(toEnum)
00210     , fMemoryManager(manager)
00211 {
00212     Reset();
00213 }
00214 
00215 template <class TElem> NameIdPoolEnumerator<TElem>::
00216 NameIdPoolEnumerator(const NameIdPoolEnumerator<TElem>& toCopy) :
00217     XMLEnumerator<TElem>(toCopy)
00218     , XMemory(toCopy)
00219     , fCurIndex(toCopy.fCurIndex)
00220     , fToEnum(toCopy.fToEnum)
00221     , fMemoryManager(toCopy.fMemoryManager)
00222 {
00223 }
00224 
00225 template <class TElem> NameIdPoolEnumerator<TElem>::~NameIdPoolEnumerator()
00226 {
00227     // We don't own the pool being enumerated, so no cleanup required
00228 }
00229 
00230 
00231 // ---------------------------------------------------------------------------
00232 //  NameIdPoolEnumerator: Public operators
00233 // ---------------------------------------------------------------------------
00234 template <class TElem> NameIdPoolEnumerator<TElem>& NameIdPoolEnumerator<TElem>::
00235 operator=(const NameIdPoolEnumerator<TElem>& toAssign)
00236 {
00237     if (this == &toAssign)
00238         return *this;
00239     fMemoryManager = toAssign.fMemoryManager;
00240     fCurIndex      = toAssign.fCurIndex;
00241     fToEnum        = toAssign.fToEnum;
00242     return *this;
00243 }
00244 
00245 // ---------------------------------------------------------------------------
00246 //  NameIdPoolEnumerator: Enum interface
00247 // ---------------------------------------------------------------------------
00248 template <class TElem> bool NameIdPoolEnumerator<TElem>::
00249 hasMoreElements() const
00250 {
00251     // If our index is zero or past the end, then we are done
00252     if (!fCurIndex || (fCurIndex > fToEnum->fIdCounter))
00253         return false;
00254     return true;
00255 }
00256 
00257 template <class TElem> TElem& NameIdPoolEnumerator<TElem>::nextElement()
00258 {
00259     // If our index is zero or past the end, then we are done
00260     if (!fCurIndex || (fCurIndex > fToEnum->fIdCounter))
00261         ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::Enum_NoMoreElements, fMemoryManager);
00262 
00263     // Return the current element and bump the index
00264     return *fToEnum->fIdPtrs[fCurIndex++];
00265 }
00266 
00267 
00268 template <class TElem> void NameIdPoolEnumerator<TElem>::Reset()
00269 {
00270     //
00271     //  Find the next available bucket element in the pool. We use the id
00272     //  array since its very easy to enumerator through by just maintaining
00273     //  an index. If the id counter is zero, then its empty and we leave the
00274     //  current index to zero.
00275     //
00276     fCurIndex = fToEnum->fIdCounter ? 1:0;
00277 }
00278 
00279 template <class TElem> XMLSize_t NameIdPoolEnumerator<TElem>::size() const
00280 {
00281     return fToEnum->fIdCounter;
00282 }
00283 
00284 XERCES_CPP_NAMESPACE_END