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: RefHash2KeysTableOf.c 679340 2008-07-24 10:28:29Z borisk $ 00020 */ 00021 00022 00023 // --------------------------------------------------------------------------- 00024 // Include 00025 // --------------------------------------------------------------------------- 00026 #if defined(XERCES_TMPLSINC) 00027 #include <xercesc/util/RefHash2KeysTableOf.hpp> 00028 #endif 00029 00030 #include <xercesc/util/Janitor.hpp> 00031 #include <xercesc/util/NullPointerException.hpp> 00032 #include <assert.h> 00033 #include <new> 00034 00035 XERCES_CPP_NAMESPACE_BEGIN 00036 00037 // --------------------------------------------------------------------------- 00038 // RefHash2KeysTableOf: Constructors and Destructor 00039 // --------------------------------------------------------------------------- 00040 00041 template <class TVal, class THasher> 00042 RefHash2KeysTableOf<TVal, THasher>::RefHash2KeysTableOf( 00043 const XMLSize_t modulus, 00044 MemoryManager* const manager) 00045 00046 : fMemoryManager(manager) 00047 , fAdoptedElems(true) 00048 , fBucketList(0) 00049 , fHashModulus(modulus) 00050 , fCount(0) 00051 { 00052 initialize(modulus); 00053 } 00054 00055 template <class TVal, class THasher> 00056 RefHash2KeysTableOf<TVal, THasher>::RefHash2KeysTableOf( 00057 const XMLSize_t modulus, 00058 const THasher& hasher, 00059 MemoryManager* const manager) 00060 00061 : fMemoryManager(manager) 00062 , fAdoptedElems(true) 00063 , fBucketList(0) 00064 , fHashModulus(modulus) 00065 , fCount(0) 00066 , fHasher (hasher) 00067 { 00068 initialize(modulus); 00069 } 00070 00071 template <class TVal, class THasher> 00072 RefHash2KeysTableOf<TVal, THasher>::RefHash2KeysTableOf( 00073 const XMLSize_t modulus, 00074 const bool adoptElems, 00075 MemoryManager* const manager) 00076 00077 : fMemoryManager(manager) 00078 , fAdoptedElems(adoptElems) 00079 , fBucketList(0) 00080 , fHashModulus(modulus) 00081 , fCount(0) 00082 00083 { 00084 initialize(modulus); 00085 } 00086 00087 template <class TVal, class THasher> 00088 RefHash2KeysTableOf<TVal, THasher>::RefHash2KeysTableOf( 00089 const XMLSize_t modulus, 00090 const bool adoptElems, 00091 const THasher& hasher, 00092 MemoryManager* const manager) 00093 00094 : fMemoryManager(manager) 00095 , fAdoptedElems(adoptElems) 00096 , fBucketList(0) 00097 , fHashModulus(modulus) 00098 , fCount(0) 00099 , fHasher (hasher) 00100 { 00101 initialize(modulus); 00102 } 00103 00104 template <class TVal, class THasher> 00105 void RefHash2KeysTableOf<TVal, THasher>::initialize(const XMLSize_t modulus) 00106 { 00107 if (modulus == 0) 00108 ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::HshTbl_ZeroModulus, fMemoryManager); 00109 00110 // Allocate the bucket list and zero them 00111 fBucketList = (RefHash2KeysTableBucketElem<TVal>**) fMemoryManager->allocate 00112 ( 00113 fHashModulus * sizeof(RefHash2KeysTableBucketElem<TVal>*) 00114 ); //new RefHash2KeysTableBucketElem<TVal>*[fHashModulus]; 00115 memset(fBucketList, 0, sizeof(fBucketList[0]) * fHashModulus); 00116 } 00117 00118 template <class TVal, class THasher> 00119 RefHash2KeysTableOf<TVal, THasher>::~RefHash2KeysTableOf() 00120 { 00121 removeAll(); 00122 00123 // Then delete the bucket list & hasher 00124 fMemoryManager->deallocate(fBucketList); //delete [] fBucketList; 00125 fBucketList = 0; 00126 } 00127 00128 00129 // --------------------------------------------------------------------------- 00130 // RefHash2KeysTableOf: Element management 00131 // --------------------------------------------------------------------------- 00132 template <class TVal, class THasher> 00133 bool RefHash2KeysTableOf<TVal, THasher>::isEmpty() const 00134 { 00135 return (fCount==0); 00136 } 00137 00138 template <class TVal, class THasher> 00139 bool RefHash2KeysTableOf<TVal, THasher>:: 00140 containsKey(const void* const key1, const int key2) const 00141 { 00142 XMLSize_t hashVal; 00143 const RefHash2KeysTableBucketElem<TVal>* findIt = findBucketElem(key1, key2, hashVal); 00144 return (findIt != 0); 00145 } 00146 00147 template <class TVal, class THasher> 00148 void RefHash2KeysTableOf<TVal, THasher>:: 00149 removeKey(const void* const key1, const int key2) 00150 { 00151 // Hash the key 00152 XMLSize_t hashVal = fHasher.getHashVal(key1, fHashModulus); 00153 assert(hashVal < fHashModulus); 00154 00155 // 00156 // Search the given bucket for this key. Keep up with the previous 00157 // element so we can patch around it. 00158 // 00159 RefHash2KeysTableBucketElem<TVal>* curElem = fBucketList[hashVal]; 00160 RefHash2KeysTableBucketElem<TVal>* lastElem = 0; 00161 00162 while (curElem) 00163 { 00164 if((key2==curElem->fKey2) && (fHasher.equals(key1, curElem->fKey1))) 00165 { 00166 if (!lastElem) 00167 { 00168 // It was the first in the bucket 00169 fBucketList[hashVal] = curElem->fNext; 00170 } 00171 else 00172 { 00173 // Patch around the current element 00174 lastElem->fNext = curElem->fNext; 00175 } 00176 00177 // If we adopted the elements, then delete the data 00178 if (fAdoptedElems) 00179 delete curElem->fData; 00180 00181 // Delete the current element 00182 // delete curElem; 00183 // destructor is empty... 00184 // curElem->~RefHash2KeysTableBucketElem(); 00185 fMemoryManager->deallocate(curElem); 00186 fCount--; 00187 return; 00188 } 00189 00190 // Move both pointers upwards 00191 lastElem = curElem; 00192 curElem = curElem->fNext; 00193 } 00194 00195 // We never found that key 00196 ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::HshTbl_NoSuchKeyExists, fMemoryManager); 00197 } 00198 00199 template <class TVal, class THasher> 00200 void RefHash2KeysTableOf<TVal, THasher>:: 00201 removeKey(const void* const key1) 00202 { 00203 // Hash the key 00204 XMLSize_t hashVal = fHasher.getHashVal(key1, fHashModulus); 00205 assert(hashVal < fHashModulus); 00206 00207 // 00208 // Search the given bucket for this key. Keep up with the previous 00209 // element so we can patch around it. 00210 // 00211 RefHash2KeysTableBucketElem<TVal>* curElem = fBucketList[hashVal]; 00212 RefHash2KeysTableBucketElem<TVal>* lastElem = 0; 00213 00214 while (curElem) 00215 { 00216 if(fHasher.equals(key1, curElem->fKey1)) 00217 { 00218 if (!lastElem) 00219 { 00220 // It was the first in the bucket 00221 fBucketList[hashVal] = curElem->fNext; 00222 } 00223 else 00224 { 00225 // Patch around the current element 00226 lastElem->fNext = curElem->fNext; 00227 } 00228 00229 // If we adopted the elements, then delete the data 00230 if (fAdoptedElems) 00231 delete curElem->fData; 00232 00233 RefHash2KeysTableBucketElem<TVal>* toBeDeleted=curElem; 00234 curElem = curElem->fNext; 00235 00236 // Delete the current element 00237 // delete curElem; 00238 // destructor is empty... 00239 // curElem->~RefHash2KeysTableBucketElem(); 00240 fMemoryManager->deallocate(toBeDeleted); 00241 fCount--; 00242 } 00243 else 00244 { 00245 // Move both pointers upwards 00246 lastElem = curElem; 00247 curElem = curElem->fNext; 00248 } 00249 } 00250 } 00251 00252 template <class TVal, class THasher> 00253 void RefHash2KeysTableOf<TVal, THasher>::removeAll() 00254 { 00255 if(isEmpty()) 00256 return; 00257 00258 // Clean up the buckets first 00259 for (XMLSize_t buckInd = 0; buckInd < fHashModulus; buckInd++) 00260 { 00261 // Get the bucket list head for this entry 00262 RefHash2KeysTableBucketElem<TVal>* curElem = fBucketList[buckInd]; 00263 RefHash2KeysTableBucketElem<TVal>* nextElem; 00264 while (curElem) 00265 { 00266 // Save the next element before we hose this one 00267 nextElem = curElem->fNext; 00268 00269 // If we adopted the data, then delete it too 00270 // (Note: the userdata hash table instance has data type of void *. 00271 // This will generate compiler warnings here on some platforms, but they 00272 // can be ignored since fAdoptedElements is false. 00273 if (fAdoptedElems) 00274 delete curElem->fData; 00275 00276 // Then delete the current element and move forward 00277 // destructor is empty... 00278 // curElem->~RefHash2KeysTableBucketElem(); 00279 fMemoryManager->deallocate(curElem); 00280 curElem = nextElem; 00281 } 00282 00283 // Clean out this entry 00284 fBucketList[buckInd] = 0; 00285 } 00286 fCount=0; 00287 } 00288 00289 // this function transfer the data from key1 to key2 00290 template <class TVal, class THasher> 00291 void RefHash2KeysTableOf<TVal, THasher>::transferElement(const void* const key1, void* key2) 00292 { 00293 // Hash the key 00294 XMLSize_t hashVal = fHasher.getHashVal(key1, fHashModulus); 00295 assert(hashVal < fHashModulus); 00296 00297 // 00298 // Search the given bucket for this key. Keep up with the previous 00299 // element so we can patch around it. 00300 // 00301 RefHash2KeysTableBucketElem<TVal>* curElem = fBucketList[hashVal]; 00302 RefHash2KeysTableBucketElem<TVal>* lastElem = 0; 00303 00304 while (curElem) 00305 { 00306 // if this element has the same primary key, remove it and add it using the new primary key 00307 if(fHasher.equals(key1, curElem->fKey1)) 00308 { 00309 if (!lastElem) 00310 { 00311 // It was the first in the bucket 00312 fBucketList[hashVal] = curElem->fNext; 00313 } 00314 else 00315 { 00316 // Patch around the current element 00317 lastElem->fNext = curElem->fNext; 00318 } 00319 00320 // this code comes from put(), but it doesn't update fCount 00321 XMLSize_t hashVal2; 00322 RefHash2KeysTableBucketElem<TVal>* newBucket = findBucketElem(key2, curElem->fKey2, hashVal2); 00323 if (newBucket) 00324 { 00325 if (fAdoptedElems) 00326 delete newBucket->fData; 00327 newBucket->fData = curElem->fData; 00328 newBucket->fKey1 = key2; 00329 newBucket->fKey2 = curElem->fKey2; 00330 } 00331 else 00332 { 00333 newBucket = 00334 new (fMemoryManager->allocate(sizeof(RefHash2KeysTableBucketElem<TVal>))) 00335 RefHash2KeysTableBucketElem<TVal>(key2, curElem->fKey2, curElem->fData, fBucketList[hashVal2]); 00336 fBucketList[hashVal2] = newBucket; 00337 } 00338 00339 RefHash2KeysTableBucketElem<TVal>* elemToDelete = curElem; 00340 00341 // Update just curElem; lastElem must stay the same 00342 curElem = curElem->fNext; 00343 00344 // Delete the current element 00345 // delete elemToDelete; 00346 // destructor is empty... 00347 // curElem->~RefHash2KeysTableBucketElem(); 00348 fMemoryManager->deallocate(elemToDelete); 00349 } 00350 else 00351 { 00352 // Move both pointers upwards 00353 lastElem = curElem; 00354 curElem = curElem->fNext; 00355 } 00356 } 00357 } 00358 00359 00360 00361 // --------------------------------------------------------------------------- 00362 // RefHash2KeysTableOf: Getters 00363 // --------------------------------------------------------------------------- 00364 template <class TVal, class THasher> 00365 TVal* RefHash2KeysTableOf<TVal, THasher>::get(const void* const key1, const int key2) 00366 { 00367 XMLSize_t hashVal; 00368 RefHash2KeysTableBucketElem<TVal>* findIt = findBucketElem(key1, key2, hashVal); 00369 if (!findIt) 00370 return 0; 00371 return findIt->fData; 00372 } 00373 00374 template <class TVal, class THasher> 00375 const TVal* RefHash2KeysTableOf<TVal, THasher>:: 00376 get(const void* const key1, const int key2) const 00377 { 00378 XMLSize_t hashVal; 00379 const RefHash2KeysTableBucketElem<TVal>* findIt = findBucketElem(key1, key2, hashVal); 00380 if (!findIt) 00381 return 0; 00382 return findIt->fData; 00383 } 00384 00385 template <class TVal, class THasher> 00386 MemoryManager* RefHash2KeysTableOf<TVal, THasher>::getMemoryManager() const 00387 { 00388 return fMemoryManager; 00389 } 00390 00391 template <class TVal, class THasher> 00392 XMLSize_t RefHash2KeysTableOf<TVal, THasher>::getHashModulus() const 00393 { 00394 return fHashModulus; 00395 } 00396 00397 // --------------------------------------------------------------------------- 00398 // RefHash2KeysTableOf: Putters 00399 // --------------------------------------------------------------------------- 00400 template <class TVal, class THasher> 00401 void RefHash2KeysTableOf<TVal, THasher>::put(void* key1, int key2, TVal* const valueToAdopt) 00402 { 00403 // Apply 4 load factor to find threshold. 00404 XMLSize_t threshold = fHashModulus * 4; 00405 00406 // If we've grown too big, expand the table and rehash. 00407 if (fCount >= threshold) 00408 rehash(); 00409 00410 // First see if the key exists already 00411 XMLSize_t hashVal; 00412 RefHash2KeysTableBucketElem<TVal>* newBucket = findBucketElem(key1, key2, hashVal); 00413 00414 // 00415 // If so,then update its value. If not, then we need to add it to 00416 // the right bucket 00417 // 00418 if (newBucket) 00419 { 00420 if (fAdoptedElems) 00421 delete newBucket->fData; 00422 newBucket->fData = valueToAdopt; 00423 newBucket->fKey1 = key1; 00424 newBucket->fKey2 = key2; 00425 } 00426 else 00427 { 00428 newBucket = 00429 new (fMemoryManager->allocate(sizeof(RefHash2KeysTableBucketElem<TVal>))) 00430 RefHash2KeysTableBucketElem<TVal>(key1, key2, valueToAdopt, fBucketList[hashVal]); 00431 fBucketList[hashVal] = newBucket; 00432 fCount++; 00433 } 00434 } 00435 00436 00437 00438 // --------------------------------------------------------------------------- 00439 // RefHash2KeysTableOf: Private methods 00440 // --------------------------------------------------------------------------- 00441 template <class TVal, class THasher> 00442 inline RefHash2KeysTableBucketElem<TVal>* RefHash2KeysTableOf<TVal, THasher>:: 00443 findBucketElem(const void* const key1, const int key2, XMLSize_t& hashVal) 00444 { 00445 // Hash the key 00446 hashVal = fHasher.getHashVal(key1, fHashModulus); 00447 assert(hashVal < fHashModulus); 00448 00449 // Search that bucket for the key 00450 RefHash2KeysTableBucketElem<TVal>* curElem = fBucketList[hashVal]; 00451 while (curElem) 00452 { 00453 if((key2==curElem->fKey2) && (fHasher.equals(key1, curElem->fKey1))) 00454 return curElem; 00455 00456 curElem = curElem->fNext; 00457 } 00458 return 0; 00459 } 00460 00461 template <class TVal, class THasher> 00462 inline const RefHash2KeysTableBucketElem<TVal>* RefHash2KeysTableOf<TVal, THasher>:: 00463 findBucketElem(const void* const key1, const int key2, XMLSize_t& hashVal) const 00464 { 00465 // Hash the key 00466 hashVal = fHasher.getHashVal(key1, fHashModulus); 00467 assert(hashVal < fHashModulus); 00468 00469 // Search that bucket for the key 00470 const RefHash2KeysTableBucketElem<TVal>* curElem = fBucketList[hashVal]; 00471 while (curElem) 00472 { 00473 if((key2==curElem->fKey2) && (fHasher.equals(key1, curElem->fKey1))) 00474 return curElem; 00475 00476 curElem = curElem->fNext; 00477 } 00478 return 0; 00479 } 00480 00481 00482 template <class TVal, class THasher> 00483 void RefHash2KeysTableOf<TVal, THasher>:: 00484 rehash() 00485 { 00486 const XMLSize_t newMod = (fHashModulus * 8)+1; 00487 00488 RefHash2KeysTableBucketElem<TVal>** newBucketList = 00489 (RefHash2KeysTableBucketElem<TVal>**) fMemoryManager->allocate 00490 ( 00491 newMod * sizeof(RefHash2KeysTableBucketElem<TVal>*) 00492 );//new RefHash2KeysTableBucketElem<TVal>*[fHashModulus]; 00493 00494 // Make sure the new bucket list is destroyed if an 00495 // exception is thrown. 00496 ArrayJanitor<RefHash2KeysTableBucketElem<TVal>*> guard(newBucketList, fMemoryManager); 00497 00498 memset(newBucketList, 0, newMod * sizeof(newBucketList[0])); 00499 00500 // Rehash all existing entries. 00501 for (XMLSize_t index = 0; index < fHashModulus; index++) 00502 { 00503 // Get the bucket list head for this entry 00504 RefHash2KeysTableBucketElem<TVal>* curElem = fBucketList[index]; 00505 while (curElem) 00506 { 00507 // Save the next element before we detach this one 00508 RefHash2KeysTableBucketElem<TVal>* nextElem = curElem->fNext; 00509 00510 const XMLSize_t hashVal = fHasher.getHashVal(curElem->fKey1, newMod); 00511 assert(hashVal < newMod); 00512 00513 RefHash2KeysTableBucketElem<TVal>* newHeadElem = newBucketList[hashVal]; 00514 00515 // Insert at the start of this bucket's list. 00516 curElem->fNext = newHeadElem; 00517 newBucketList[hashVal] = curElem; 00518 00519 curElem = nextElem; 00520 } 00521 } 00522 00523 RefHash2KeysTableBucketElem<TVal>** const oldBucketList = fBucketList; 00524 00525 // Everything is OK at this point, so update the 00526 // member variables. 00527 fBucketList = guard.release(); 00528 fHashModulus = newMod; 00529 00530 // Delete the old bucket list. 00531 fMemoryManager->deallocate(oldBucketList);//delete[] oldBucketList; 00532 00533 } 00534 00535 00536 00537 // --------------------------------------------------------------------------- 00538 // RefHash2KeysTableOfEnumerator: Constructors and Destructor 00539 // --------------------------------------------------------------------------- 00540 template <class TVal, class THasher> 00541 RefHash2KeysTableOfEnumerator<TVal, THasher>:: 00542 RefHash2KeysTableOfEnumerator(RefHash2KeysTableOf<TVal, THasher>* const toEnum 00543 , const bool adopt 00544 , MemoryManager* const manager) 00545 : fAdopted(adopt), fCurElem(0), fCurHash((XMLSize_t)-1), fToEnum(toEnum) 00546 , fMemoryManager(manager) 00547 , fLockPrimaryKey(0) 00548 { 00549 if (!toEnum) 00550 ThrowXMLwithMemMgr(NullPointerException, XMLExcepts::CPtr_PointerIsZero, fMemoryManager); 00551 00552 // 00553 // Find the next available bucket element in the hash table. If it 00554 // comes back zero, that just means the table is empty. 00555 // 00556 // Note that the -1 in the current hash tells it to start 00557 // from the beginning. 00558 // 00559 findNext(); 00560 } 00561 00562 template <class TVal, class THasher> 00563 RefHash2KeysTableOfEnumerator<TVal, THasher>::~RefHash2KeysTableOfEnumerator() 00564 { 00565 if (fAdopted) 00566 delete fToEnum; 00567 } 00568 00569 00570 // --------------------------------------------------------------------------- 00571 // RefHash2KeysTableOfEnumerator: Enum interface 00572 // --------------------------------------------------------------------------- 00573 template <class TVal, class THasher> 00574 bool RefHash2KeysTableOfEnumerator<TVal, THasher>::hasMoreElements() const 00575 { 00576 // 00577 // If our current has is at the max and there are no more elements 00578 // in the current bucket, then no more elements. 00579 // 00580 if (!fCurElem && (fCurHash == fToEnum->fHashModulus)) 00581 return false; 00582 return true; 00583 } 00584 00585 template <class TVal, class THasher> 00586 TVal& RefHash2KeysTableOfEnumerator<TVal, THasher>::nextElement() 00587 { 00588 // Make sure we have an element to return 00589 if (!hasMoreElements()) 00590 ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::Enum_NoMoreElements, fMemoryManager); 00591 00592 // 00593 // Save the current element, then move up to the next one for the 00594 // next time around. 00595 // 00596 RefHash2KeysTableBucketElem<TVal>* saveElem = fCurElem; 00597 findNext(); 00598 00599 return *saveElem->fData; 00600 } 00601 00602 template <class TVal, class THasher> 00603 void RefHash2KeysTableOfEnumerator<TVal, THasher>::nextElementKey(void*& retKey1, int& retKey2) 00604 { 00605 // Make sure we have an element to return 00606 if (!hasMoreElements()) 00607 ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::Enum_NoMoreElements, fMemoryManager); 00608 00609 // 00610 // Save the current element, then move up to the next one for the 00611 // next time around. 00612 // 00613 RefHash2KeysTableBucketElem<TVal>* saveElem = fCurElem; 00614 findNext(); 00615 00616 retKey1 = saveElem->fKey1; 00617 retKey2 = saveElem->fKey2; 00618 00619 return; 00620 } 00621 00622 template <class TVal, class THasher> 00623 void RefHash2KeysTableOfEnumerator<TVal, THasher>::Reset() 00624 { 00625 if(fLockPrimaryKey) 00626 fCurHash=fToEnum->fHasher.getHashVal(fLockPrimaryKey, fToEnum->fHashModulus); 00627 else 00628 fCurHash = (XMLSize_t)-1; 00629 00630 fCurElem = 0; 00631 findNext(); 00632 } 00633 00634 00635 template <class TVal, class THasher> 00636 void RefHash2KeysTableOfEnumerator<TVal, THasher>::setPrimaryKey(const void* key) 00637 { 00638 fLockPrimaryKey=key; 00639 Reset(); 00640 } 00641 00642 // --------------------------------------------------------------------------- 00643 // RefHash2KeysTableOfEnumerator: Private helper methods 00644 // --------------------------------------------------------------------------- 00645 template <class TVal, class THasher> 00646 void RefHash2KeysTableOfEnumerator<TVal, THasher>::findNext() 00647 { 00648 // Code to execute if we have to return only values with the primary key 00649 if(fLockPrimaryKey) 00650 { 00651 if(!fCurElem) 00652 fCurElem = fToEnum->fBucketList[fCurHash]; 00653 else 00654 fCurElem = fCurElem->fNext; 00655 while (fCurElem && (!fToEnum->fHasher.equals(fLockPrimaryKey, fCurElem->fKey1))) 00656 fCurElem = fCurElem->fNext; 00657 // if we didn't found it, make so hasMoreElements() returns false 00658 if(!fCurElem) 00659 fCurHash = fToEnum->fHashModulus; 00660 return; 00661 } 00662 // 00663 // If there is a current element, move to its next element. If this 00664 // hits the end of the bucket, the next block will handle the rest. 00665 // 00666 if (fCurElem) 00667 fCurElem = fCurElem->fNext; 00668 00669 // 00670 // If the current element is null, then we have to move up to the 00671 // next hash value. If that is the hash modulus, then we cannot 00672 // go further. 00673 // 00674 if (!fCurElem) 00675 { 00676 fCurHash++; 00677 if (fCurHash == fToEnum->fHashModulus) 00678 return; 00679 00680 // Else find the next non-empty bucket 00681 while (fToEnum->fBucketList[fCurHash]==0) 00682 { 00683 // Bump to the next hash value. If we max out return 00684 fCurHash++; 00685 if (fCurHash == fToEnum->fHashModulus) 00686 return; 00687 } 00688 fCurElem = fToEnum->fBucketList[fCurHash]; 00689 } 00690 } 00691 00692 XERCES_CPP_NAMESPACE_END