Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:15:13

0001 /*
0002  * Licensed to the Apache Software Foundation (ASF) under one or more
0003  * contributor license agreements.  See the NOTICE file distributed with
0004  * this work for additional information regarding copyright ownership.
0005  * The ASF licenses this file to You under the Apache License, Version 2.0
0006  * (the "License"); you may not use this file except in compliance with
0007  * the License.  You may obtain a copy of the License at
0008  *
0009  *      http://www.apache.org/licenses/LICENSE-2.0
0010  *
0011  * Unless required by applicable law or agreed to in writing, software
0012  * distributed under the License is distributed on an "AS IS" BASIS,
0013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014  * See the License for the specific language governing permissions and
0015  * limitations under the License.
0016  */
0017 
0018 /*
0019  * $Id$
0020  */
0021 
0022 
0023 // ---------------------------------------------------------------------------
0024 //  Include
0025 // ---------------------------------------------------------------------------
0026 #if defined(XERCES_TMPLSINC)
0027 #include <xercesc/util/RefHash2KeysTableOf.hpp>
0028 #endif
0029 
0030 #include <xercesc/util/Janitor.hpp>
0031 #include <xercesc/util/NullPointerException.hpp>
0032 #include <assert.h>
0033 #include <new>
0034 
0035 XERCES_CPP_NAMESPACE_BEGIN
0036 
0037 // ---------------------------------------------------------------------------
0038 //  RefHash2KeysTableOf: Constructors and Destructor
0039 // ---------------------------------------------------------------------------
0040 
0041 template <class TVal, class THasher>
0042 RefHash2KeysTableOf<TVal, THasher>::RefHash2KeysTableOf(
0043   const XMLSize_t modulus,
0044   MemoryManager* const manager)
0045 
0046     : fMemoryManager(manager)
0047     , fAdoptedElems(true)
0048     , fBucketList(0)
0049     , fHashModulus(modulus)
0050     , fCount(0)
0051 {
0052     initialize(modulus);
0053 }
0054 
0055 template <class TVal, class THasher>
0056 RefHash2KeysTableOf<TVal, THasher>::RefHash2KeysTableOf(
0057   const XMLSize_t modulus,
0058   const THasher& hasher,
0059   MemoryManager* const manager)
0060 
0061     : fMemoryManager(manager)
0062     , fAdoptedElems(true)
0063     , fBucketList(0)
0064     , fHashModulus(modulus)
0065     , fCount(0)
0066     , fHasher (hasher)
0067 {
0068     initialize(modulus);
0069 }
0070 
0071 template <class TVal, class THasher>
0072 RefHash2KeysTableOf<TVal, THasher>::RefHash2KeysTableOf(
0073   const XMLSize_t modulus,
0074   const bool adoptElems,
0075   MemoryManager* const manager)
0076 
0077     : fMemoryManager(manager)
0078     , fAdoptedElems(adoptElems)
0079     , fBucketList(0)
0080     , fHashModulus(modulus)
0081     , fCount(0)
0082 
0083 {
0084     initialize(modulus);
0085 }
0086 
0087 template <class TVal, class THasher>
0088 RefHash2KeysTableOf<TVal, THasher>::RefHash2KeysTableOf(
0089   const XMLSize_t modulus,
0090   const bool adoptElems,
0091   const THasher& hasher,
0092   MemoryManager* const manager)
0093 
0094     : fMemoryManager(manager)
0095     , fAdoptedElems(adoptElems)
0096     , fBucketList(0)
0097     , fHashModulus(modulus)
0098     , fCount(0)
0099     , fHasher (hasher)
0100 {
0101     initialize(modulus);
0102 }
0103 
0104 template <class TVal, class THasher>
0105 void RefHash2KeysTableOf<TVal, THasher>::initialize(const XMLSize_t modulus)
0106 {
0107     if (modulus == 0)
0108         ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::HshTbl_ZeroModulus, fMemoryManager);
0109 
0110     // Allocate the bucket list and zero them
0111     fBucketList = (RefHash2KeysTableBucketElem<TVal>**) fMemoryManager->allocate
0112     (
0113         fHashModulus * sizeof(RefHash2KeysTableBucketElem<TVal>*)
0114     ); //new RefHash2KeysTableBucketElem<TVal>*[fHashModulus];
0115     memset(fBucketList, 0, sizeof(fBucketList[0]) * fHashModulus);
0116 }
0117 
0118 template <class TVal, class THasher>
0119 RefHash2KeysTableOf<TVal, THasher>::~RefHash2KeysTableOf()
0120 {
0121     removeAll();
0122 
0123     // Then delete the bucket list & hasher
0124     fMemoryManager->deallocate(fBucketList); //delete [] fBucketList;
0125     fBucketList = 0;
0126 }
0127 
0128 
0129 // ---------------------------------------------------------------------------
0130 //  RefHash2KeysTableOf: Element management
0131 // ---------------------------------------------------------------------------
0132 template <class TVal, class THasher>
0133 bool RefHash2KeysTableOf<TVal, THasher>::isEmpty() const
0134 {
0135     return (fCount==0);
0136 }
0137 
0138 template <class TVal, class THasher>
0139 bool RefHash2KeysTableOf<TVal, THasher>::
0140 containsKey(const void* const key1, const int key2) const
0141 {
0142     XMLSize_t hashVal;
0143     const RefHash2KeysTableBucketElem<TVal>* findIt = findBucketElem(key1, key2, hashVal);
0144     return (findIt != 0);
0145 }
0146 
0147 template <class TVal, class THasher>
0148 void RefHash2KeysTableOf<TVal, THasher>::
0149 removeKey(const void* const key1, const int key2)
0150 {
0151     // Hash the key
0152     XMLSize_t hashVal = fHasher.getHashVal(key1, fHashModulus);
0153     assert(hashVal < fHashModulus);
0154 
0155     //
0156     //  Search the given bucket for this key. Keep up with the previous
0157     //  element so we can patch around it.
0158     //
0159     RefHash2KeysTableBucketElem<TVal>* curElem = fBucketList[hashVal];
0160     RefHash2KeysTableBucketElem<TVal>* lastElem = 0;
0161 
0162     while (curElem)
0163     {
0164         if((key2==curElem->fKey2) && (fHasher.equals(key1, curElem->fKey1)))
0165         {
0166             if (!lastElem)
0167             {
0168                 // It was the first in the bucket
0169                 fBucketList[hashVal] = curElem->fNext;
0170             }
0171             else
0172             {
0173                 // Patch around the current element
0174                 lastElem->fNext = curElem->fNext;
0175             }
0176 
0177             // If we adopted the elements, then delete the data
0178             if (fAdoptedElems)
0179                 delete curElem->fData;
0180 
0181             // Delete the current element
0182             // delete curElem;
0183             // destructor is empty...
0184             // curElem->~RefHash2KeysTableBucketElem();
0185             fMemoryManager->deallocate(curElem);
0186             fCount--;
0187             return;
0188         }
0189 
0190         // Move both pointers upwards
0191         lastElem = curElem;
0192         curElem = curElem->fNext;
0193     }
0194 
0195     // We never found that key
0196     ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::HshTbl_NoSuchKeyExists, fMemoryManager);
0197 }
0198 
0199 template <class TVal, class THasher>
0200 void RefHash2KeysTableOf<TVal, THasher>::
0201 removeKey(const void* const key1)
0202 {
0203     // Hash the key
0204     XMLSize_t hashVal = fHasher.getHashVal(key1, fHashModulus);
0205     assert(hashVal < fHashModulus);
0206 
0207     //
0208     //  Search the given bucket for this key. Keep up with the previous
0209     //  element so we can patch around it.
0210     //
0211     RefHash2KeysTableBucketElem<TVal>* curElem = fBucketList[hashVal];
0212     RefHash2KeysTableBucketElem<TVal>* lastElem = 0;
0213 
0214     while (curElem)
0215     {
0216         if(fHasher.equals(key1, curElem->fKey1))
0217         {
0218             if (!lastElem)
0219             {
0220                 // It was the first in the bucket
0221                 fBucketList[hashVal] = curElem->fNext;
0222             }
0223             else
0224             {
0225                 // Patch around the current element
0226                 lastElem->fNext = curElem->fNext;
0227             }
0228 
0229             // If we adopted the elements, then delete the data
0230             if (fAdoptedElems)
0231                 delete curElem->fData;
0232 
0233             RefHash2KeysTableBucketElem<TVal>* toBeDeleted=curElem;
0234             curElem = curElem->fNext;
0235 
0236             // Delete the current element
0237             // delete curElem;
0238             // destructor is empty...
0239             // curElem->~RefHash2KeysTableBucketElem();
0240             fMemoryManager->deallocate(toBeDeleted);
0241             fCount--;
0242         }
0243         else
0244         {
0245             // Move both pointers upwards
0246             lastElem = curElem;
0247             curElem = curElem->fNext;
0248         }
0249     }
0250 }
0251 
0252 template <class TVal, class THasher>
0253 void RefHash2KeysTableOf<TVal, THasher>::removeAll()
0254 {
0255     if(isEmpty())
0256         return;
0257 
0258     // Clean up the buckets first
0259     for (XMLSize_t buckInd = 0; buckInd < fHashModulus; buckInd++)
0260     {
0261         // Get the bucket list head for this entry
0262         RefHash2KeysTableBucketElem<TVal>* curElem = fBucketList[buckInd];
0263         RefHash2KeysTableBucketElem<TVal>* nextElem;
0264         while (curElem)
0265         {
0266             // Save the next element before we hose this one
0267             nextElem = curElem->fNext;
0268 
0269             // If we adopted the data, then delete it too
0270             //    (Note:  the userdata hash table instance has data type of void *.
0271             //    This will generate compiler warnings here on some platforms, but they
0272             //    can be ignored since fAdoptedElements is false.
0273             if (fAdoptedElems)
0274                 delete curElem->fData;
0275 
0276             // Then delete the current element and move forward
0277             // destructor is empty...
0278             // curElem->~RefHash2KeysTableBucketElem();
0279             fMemoryManager->deallocate(curElem);
0280             curElem = nextElem;
0281         }
0282 
0283         // Clean out this entry
0284         fBucketList[buckInd] = 0;
0285     }
0286     fCount=0;
0287 }
0288 
0289 // this function transfer the data from key1 to key2
0290 template <class TVal, class THasher>
0291 void RefHash2KeysTableOf<TVal, THasher>::transferElement(const void* const key1, void* key2)
0292 {
0293     // Hash the key
0294     XMLSize_t hashVal = fHasher.getHashVal(key1, fHashModulus);
0295     assert(hashVal < fHashModulus);
0296 
0297     //
0298     //  Search the given bucket for this key. Keep up with the previous
0299     //  element so we can patch around it.
0300     //
0301     RefHash2KeysTableBucketElem<TVal>* curElem = fBucketList[hashVal];
0302     RefHash2KeysTableBucketElem<TVal>* lastElem = 0;
0303 
0304     while (curElem)
0305     {
0306         // if this element has the same primary key, remove it and add it using the new primary key
0307         if(fHasher.equals(key1, curElem->fKey1))
0308         {
0309             if (!lastElem)
0310             {
0311                 // It was the first in the bucket
0312                 fBucketList[hashVal] = curElem->fNext;
0313             }
0314             else
0315             {
0316                 // Patch around the current element
0317                 lastElem->fNext = curElem->fNext;
0318             }
0319 
0320             // this code comes from put(), but it doesn't update fCount
0321             XMLSize_t hashVal2;
0322             RefHash2KeysTableBucketElem<TVal>* newBucket = findBucketElem(key2, curElem->fKey2, hashVal2);
0323             if (newBucket)
0324             {
0325                 if (fAdoptedElems)
0326                     delete newBucket->fData;
0327                 newBucket->fData = curElem->fData;
0328                 newBucket->fKey1 = key2;
0329                 newBucket->fKey2 = curElem->fKey2;
0330             }
0331              else
0332             {
0333                 newBucket =
0334                     new (fMemoryManager->allocate(sizeof(RefHash2KeysTableBucketElem<TVal>)))
0335                     RefHash2KeysTableBucketElem<TVal>(key2, curElem->fKey2, curElem->fData, fBucketList[hashVal2]);
0336                 fBucketList[hashVal2] = newBucket;
0337             }
0338 
0339             RefHash2KeysTableBucketElem<TVal>* elemToDelete = curElem;
0340 
0341             // Update just curElem; lastElem must stay the same
0342             curElem = curElem->fNext;
0343 
0344             // Delete the current element
0345             // delete elemToDelete;
0346             // destructor is empty...
0347             // curElem->~RefHash2KeysTableBucketElem();
0348             fMemoryManager->deallocate(elemToDelete);
0349         }
0350         else
0351         {
0352             // Move both pointers upwards
0353             lastElem = curElem;
0354             curElem = curElem->fNext;
0355         }
0356     }
0357 }
0358 
0359 
0360 
0361 // ---------------------------------------------------------------------------
0362 //  RefHash2KeysTableOf: Getters
0363 // ---------------------------------------------------------------------------
0364 template <class TVal, class THasher>
0365 TVal* RefHash2KeysTableOf<TVal, THasher>::get(const void* const key1, const int key2)
0366 {
0367     XMLSize_t hashVal;
0368     RefHash2KeysTableBucketElem<TVal>* findIt = findBucketElem(key1, key2, hashVal);
0369     if (!findIt)
0370         return 0;
0371     return findIt->fData;
0372 }
0373 
0374 template <class TVal, class THasher>
0375 const TVal* RefHash2KeysTableOf<TVal, THasher>::
0376 get(const void* const key1, const int key2) const
0377 {
0378     XMLSize_t hashVal;
0379     const RefHash2KeysTableBucketElem<TVal>* findIt = findBucketElem(key1, key2, hashVal);
0380     if (!findIt)
0381         return 0;
0382     return findIt->fData;
0383 }
0384 
0385 template <class TVal, class THasher>
0386 MemoryManager* RefHash2KeysTableOf<TVal, THasher>::getMemoryManager() const
0387 {
0388     return fMemoryManager;
0389 }
0390 
0391 template <class TVal, class THasher>
0392 XMLSize_t RefHash2KeysTableOf<TVal, THasher>::getHashModulus() const
0393 {
0394     return fHashModulus;
0395 }
0396 
0397 // ---------------------------------------------------------------------------
0398 //  RefHash2KeysTableOf: Putters
0399 // ---------------------------------------------------------------------------
0400 template <class TVal, class THasher>
0401 void RefHash2KeysTableOf<TVal, THasher>::put(void* key1, int key2, TVal* const valueToAdopt)
0402 {
0403     // Apply 4 load factor to find threshold.
0404     XMLSize_t threshold = fHashModulus * 4;
0405 
0406     // If we've grown too big, expand the table and rehash.
0407     if (fCount >= threshold)
0408         rehash();
0409 
0410     // First see if the key exists already
0411     XMLSize_t hashVal;
0412     RefHash2KeysTableBucketElem<TVal>* newBucket = findBucketElem(key1, key2, hashVal);
0413 
0414     //
0415     //  If so,then update its value. If not, then we need to add it to
0416     //  the right bucket
0417     //
0418     if (newBucket)
0419     {
0420         if (fAdoptedElems)
0421             delete newBucket->fData;
0422         newBucket->fData = valueToAdopt;
0423         newBucket->fKey1 = key1;
0424         newBucket->fKey2 = key2;
0425     }
0426      else
0427     {
0428         newBucket =
0429             new (fMemoryManager->allocate(sizeof(RefHash2KeysTableBucketElem<TVal>)))
0430             RefHash2KeysTableBucketElem<TVal>(key1, key2, valueToAdopt, fBucketList[hashVal]);
0431         fBucketList[hashVal] = newBucket;
0432         fCount++;
0433     }
0434 }
0435 
0436 
0437 
0438 // ---------------------------------------------------------------------------
0439 //  RefHash2KeysTableOf: Private methods
0440 // ---------------------------------------------------------------------------
0441 template <class TVal, class THasher>
0442 inline RefHash2KeysTableBucketElem<TVal>* RefHash2KeysTableOf<TVal, THasher>::
0443 findBucketElem(const void* const key1, const int key2, XMLSize_t& hashVal)
0444 {
0445     // Hash the key
0446     hashVal = fHasher.getHashVal(key1, fHashModulus);
0447     assert(hashVal < fHashModulus);
0448 
0449     // Search that bucket for the key
0450     RefHash2KeysTableBucketElem<TVal>* curElem = fBucketList[hashVal];
0451     while (curElem)
0452     {
0453         if((key2==curElem->fKey2) && (fHasher.equals(key1, curElem->fKey1)))
0454             return curElem;
0455 
0456         curElem = curElem->fNext;
0457     }
0458     return 0;
0459 }
0460 
0461 template <class TVal, class THasher>
0462 inline const RefHash2KeysTableBucketElem<TVal>* RefHash2KeysTableOf<TVal, THasher>::
0463 findBucketElem(const void* const key1, const int key2, XMLSize_t& hashVal) const
0464 {
0465     // Hash the key
0466     hashVal = fHasher.getHashVal(key1, fHashModulus);
0467     assert(hashVal < fHashModulus);
0468 
0469     // Search that bucket for the key
0470     const RefHash2KeysTableBucketElem<TVal>* curElem = fBucketList[hashVal];
0471     while (curElem)
0472     {
0473         if((key2==curElem->fKey2) && (fHasher.equals(key1, curElem->fKey1)))
0474             return curElem;
0475 
0476         curElem = curElem->fNext;
0477     }
0478     return 0;
0479 }
0480 
0481 
0482 template <class TVal, class THasher>
0483 void RefHash2KeysTableOf<TVal, THasher>::
0484 rehash()
0485 {
0486     const XMLSize_t newMod = (fHashModulus * 8)+1;
0487 
0488     RefHash2KeysTableBucketElem<TVal>** newBucketList =
0489         (RefHash2KeysTableBucketElem<TVal>**) fMemoryManager->allocate
0490     (
0491         newMod * sizeof(RefHash2KeysTableBucketElem<TVal>*)
0492     );//new RefHash2KeysTableBucketElem<TVal>*[fHashModulus];
0493 
0494     // Make sure the new bucket list is destroyed if an
0495     // exception is thrown.
0496     ArrayJanitor<RefHash2KeysTableBucketElem<TVal>*>  guard(newBucketList, fMemoryManager);
0497 
0498     memset(newBucketList, 0, newMod * sizeof(newBucketList[0]));
0499 
0500     // Rehash all existing entries.
0501     for (XMLSize_t index = 0; index < fHashModulus; index++)
0502     {
0503         // Get the bucket list head for this entry
0504         RefHash2KeysTableBucketElem<TVal>* curElem = fBucketList[index];
0505         while (curElem)
0506         {
0507             // Save the next element before we detach this one
0508             RefHash2KeysTableBucketElem<TVal>* nextElem = curElem->fNext;
0509 
0510             const XMLSize_t hashVal = fHasher.getHashVal(curElem->fKey1, newMod);
0511             assert(hashVal < newMod);
0512 
0513             RefHash2KeysTableBucketElem<TVal>* newHeadElem = newBucketList[hashVal];
0514 
0515             // Insert at the start of this bucket's list.
0516             curElem->fNext = newHeadElem;
0517             newBucketList[hashVal] = curElem;
0518 
0519             curElem = nextElem;
0520         }
0521     }
0522 
0523     RefHash2KeysTableBucketElem<TVal>** const oldBucketList = fBucketList;
0524 
0525     // Everything is OK at this point, so update the
0526     // member variables.
0527     fBucketList = guard.release();
0528     fHashModulus = newMod;
0529 
0530     // Delete the old bucket list.
0531     fMemoryManager->deallocate(oldBucketList);//delete[] oldBucketList;
0532 
0533 }
0534 
0535 
0536 
0537 // ---------------------------------------------------------------------------
0538 //  RefHash2KeysTableOfEnumerator: Constructors and Destructor
0539 // ---------------------------------------------------------------------------
0540 template <class TVal, class THasher>
0541 RefHash2KeysTableOfEnumerator<TVal, THasher>::
0542 RefHash2KeysTableOfEnumerator(RefHash2KeysTableOf<TVal, THasher>* const toEnum
0543                               , const bool adopt
0544                               , MemoryManager* const manager)
0545     : fAdopted(adopt), fCurElem(0), fCurHash((XMLSize_t)-1), fToEnum(toEnum)
0546     , fMemoryManager(manager)
0547     , fLockPrimaryKey(0)
0548 {
0549     if (!toEnum)
0550         ThrowXMLwithMemMgr(NullPointerException, XMLExcepts::CPtr_PointerIsZero, fMemoryManager);
0551 
0552     //
0553     //  Find the next available bucket element in the hash table. If it
0554     //  comes back zero, that just means the table is empty.
0555     //
0556     //  Note that the -1 in the current hash tells it to start
0557     //  from the beginning.
0558     //
0559     findNext();
0560 }
0561 
0562 template <class TVal, class THasher>
0563 RefHash2KeysTableOfEnumerator<TVal, THasher>::~RefHash2KeysTableOfEnumerator()
0564 {
0565     if (fAdopted)
0566         delete fToEnum;
0567 }
0568 
0569 
0570 // ---------------------------------------------------------------------------
0571 //  RefHash2KeysTableOfEnumerator: Enum interface
0572 // ---------------------------------------------------------------------------
0573 template <class TVal, class THasher>
0574 bool RefHash2KeysTableOfEnumerator<TVal, THasher>::hasMoreElements() const
0575 {
0576     //
0577     //  If our current has is at the max and there are no more elements
0578     //  in the current bucket, then no more elements.
0579     //
0580     if (!fCurElem && (fCurHash == fToEnum->fHashModulus))
0581         return false;
0582     return true;
0583 }
0584 
0585 template <class TVal, class THasher>
0586 TVal& RefHash2KeysTableOfEnumerator<TVal, THasher>::nextElement()
0587 {
0588     // Make sure we have an element to return
0589     if (!hasMoreElements())
0590         ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::Enum_NoMoreElements, fMemoryManager);
0591 
0592     //
0593     //  Save the current element, then move up to the next one for the
0594     //  next time around.
0595     //
0596     RefHash2KeysTableBucketElem<TVal>* saveElem = fCurElem;
0597     findNext();
0598 
0599     return *saveElem->fData;
0600 }
0601 
0602 template <class TVal, class THasher>
0603 void RefHash2KeysTableOfEnumerator<TVal, THasher>::nextElementKey(void*& retKey1, int& retKey2)
0604 {
0605     // Make sure we have an element to return
0606     if (!hasMoreElements())
0607         ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::Enum_NoMoreElements, fMemoryManager);
0608 
0609     //
0610     //  Save the current element, then move up to the next one for the
0611     //  next time around.
0612     //
0613     RefHash2KeysTableBucketElem<TVal>* saveElem = fCurElem;
0614     findNext();
0615 
0616     retKey1 = saveElem->fKey1;
0617     retKey2 = saveElem->fKey2;
0618 
0619     return;
0620 }
0621 
0622 template <class TVal, class THasher>
0623 void RefHash2KeysTableOfEnumerator<TVal, THasher>::Reset()
0624 {
0625     if(fLockPrimaryKey)
0626         fCurHash=fToEnum->fHasher.getHashVal(fLockPrimaryKey, fToEnum->fHashModulus);
0627     else
0628         fCurHash = (XMLSize_t)-1;
0629 
0630     fCurElem = 0;
0631     findNext();
0632 }
0633 
0634 
0635 template <class TVal, class THasher>
0636 void RefHash2KeysTableOfEnumerator<TVal, THasher>::setPrimaryKey(const void* key)
0637 {
0638     fLockPrimaryKey=key;
0639     Reset();
0640 }
0641 
0642 // ---------------------------------------------------------------------------
0643 //  RefHash2KeysTableOfEnumerator: Private helper methods
0644 // ---------------------------------------------------------------------------
0645 template <class TVal, class THasher>
0646 void RefHash2KeysTableOfEnumerator<TVal, THasher>::findNext()
0647 {
0648     //  Code to execute if we have to return only values with the primary key
0649     if(fLockPrimaryKey)
0650     {
0651         if(!fCurElem)
0652             fCurElem = fToEnum->fBucketList[fCurHash];
0653         else
0654             fCurElem = fCurElem->fNext;
0655         while (fCurElem && (!fToEnum->fHasher.equals(fLockPrimaryKey, fCurElem->fKey1)))
0656             fCurElem = fCurElem->fNext;
0657         // if we didn't found it, make so hasMoreElements() returns false
0658         if(!fCurElem)
0659             fCurHash = fToEnum->fHashModulus;
0660         return;
0661     }
0662     //
0663     //  If there is a current element, move to its next element. If this
0664     //  hits the end of the bucket, the next block will handle the rest.
0665     //
0666     if (fCurElem)
0667         fCurElem = fCurElem->fNext;
0668 
0669     //
0670     //  If the current element is null, then we have to move up to the
0671     //  next hash value. If that is the hash modulus, then we cannot
0672     //  go further.
0673     //
0674     if (!fCurElem)
0675     {
0676         fCurHash++;
0677         if (fCurHash == fToEnum->fHashModulus)
0678             return;
0679 
0680         // Else find the next non-empty bucket
0681         while (fToEnum->fBucketList[fCurHash]==0)
0682         {
0683             // Bump to the next hash value. If we max out return
0684             fCurHash++;
0685             if (fCurHash == fToEnum->fHashModulus)
0686                 return;
0687         }
0688         fCurElem = fToEnum->fBucketList[fCurHash];
0689     }
0690 }
0691 
0692 XERCES_CPP_NAMESPACE_END