GME
13
|
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