File indexing completed on 2025-11-04 10:30:59
0001 
0002 
0003 
0004 
0005 
0006 
0007 
0008 
0009 
0010 
0011 
0012 
0013 
0014 
0015 
0016 
0017 
0018 
0019 
0020 
0021 
0022 
0023 
0024 
0025 
0026 #if defined(XERCES_TMPLSINC)
0027 #include <xercesc/util/RefHashTableOf.hpp>
0028 #endif
0029 
0030 #include <xercesc/util/Janitor.hpp>
0031 #include <xercesc/util/XMLString.hpp>
0032 #include <xercesc/util/NullPointerException.hpp>
0033 #include <new>
0034 
0035 XERCES_CPP_NAMESPACE_BEGIN
0036 
0037 
0038 
0039 
0040 template <class TVal, class THasher>
0041 RefHashTableOf<TVal, THasher>::RefHashTableOf(
0042   const XMLSize_t modulus,
0043   MemoryManager* const manager)
0044 
0045     : fMemoryManager(manager)
0046     , fAdoptedElems(true)
0047     , fBucketList(0)
0048     , fHashModulus(modulus)
0049     , fInitialModulus(modulus)
0050     , fCount(0)
0051 {
0052     initialize(modulus);
0053 }
0054 
0055 template <class TVal, class THasher>
0056 RefHashTableOf<TVal, THasher>::RefHashTableOf(
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     , fInitialModulus(modulus)
0066     , fCount(0)
0067     , fHasher (hasher)
0068 {
0069     initialize(modulus);
0070 }
0071 
0072 template <class TVal, class THasher>
0073 RefHashTableOf<TVal, THasher>::RefHashTableOf(
0074   const XMLSize_t modulus,
0075   const bool adoptElems,
0076   MemoryManager* const manager)
0077 
0078     : fMemoryManager(manager)
0079     , fAdoptedElems(adoptElems)
0080     , fBucketList(0)
0081     , fHashModulus(modulus)
0082     , fInitialModulus(modulus)
0083     , fCount(0)
0084 
0085 {
0086     initialize(modulus);
0087 }
0088 
0089 template <class TVal, class THasher>
0090 RefHashTableOf<TVal, THasher>::RefHashTableOf(
0091   const XMLSize_t modulus,
0092   const bool adoptElems,
0093   const THasher& hasher,
0094   MemoryManager* const manager)
0095 
0096     : fMemoryManager(manager)
0097     , fAdoptedElems(adoptElems)
0098     , fBucketList(0)
0099     , fHashModulus(modulus)
0100     , fInitialModulus(modulus)
0101     , fCount(0)
0102     , fHasher (hasher)
0103 {
0104     initialize(modulus);
0105 }
0106 
0107 template <class TVal, class THasher>
0108 void RefHashTableOf<TVal, THasher>::initialize(const XMLSize_t modulus)
0109 {
0110     if (modulus == 0)
0111         ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::HshTbl_ZeroModulus, fMemoryManager);
0112 
0113     
0114     fBucketList = (RefHashTableBucketElem<TVal>**) fMemoryManager->allocate
0115     (
0116         fHashModulus * sizeof(RefHashTableBucketElem<TVal>*)
0117     );
0118     for (XMLSize_t index = 0; index < fHashModulus; index++)
0119         fBucketList[index] = 0;
0120 }
0121 
0122 template <class TVal, class THasher>
0123 RefHashTableOf<TVal, THasher>::~RefHashTableOf()
0124 {
0125     cleanup();
0126 }
0127 
0128 
0129 
0130 
0131 
0132 template <class TVal, class THasher>
0133 inline bool RefHashTableOf<TVal, THasher>::isEmpty() const
0134 {
0135     return fCount==0;
0136 }
0137 
0138 template <class TVal, class THasher>
0139 inline bool RefHashTableOf<TVal, THasher>::containsKey(const void* const key) const
0140 {
0141     XMLSize_t hashVal;
0142     const RefHashTableBucketElem<TVal>* findIt = findBucketElem(key, hashVal);
0143     return (findIt != 0);
0144 }
0145 
0146 template <class TVal, class THasher>
0147 void RefHashTableOf<TVal, THasher>::
0148 removeKey(const void* const key)
0149 {
0150     
0151     XMLSize_t hashVal = fHasher.getHashVal(key, fHashModulus);
0152 
0153     
0154     
0155     
0156     
0157     RefHashTableBucketElem<TVal>* curElem = fBucketList[hashVal];
0158     RefHashTableBucketElem<TVal>* lastElem = 0;
0159 
0160     while (curElem)
0161     {
0162         if (fHasher.equals(key, curElem->fKey))
0163         {
0164             if (!lastElem)
0165             {
0166                 
0167                 fBucketList[hashVal] = curElem->fNext;
0168             }
0169              else
0170             {
0171                 
0172                 lastElem->fNext = curElem->fNext;
0173             }
0174 
0175             
0176             
0177             
0178             
0179             if (fAdoptedElems)
0180                 delete curElem->fData;
0181 
0182             
0183             
0184             
0185             fMemoryManager->deallocate(curElem);
0186 
0187             fCount--;
0188 
0189             return;
0190         }
0191 
0192         
0193         lastElem = curElem;
0194         curElem = curElem->fNext;
0195     }
0196 
0197     
0198     ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::HshTbl_NoSuchKeyExists, fMemoryManager);
0199 }
0200 
0201 template <class TVal, class THasher>
0202 void RefHashTableOf<TVal, THasher>::removeAll()
0203 {
0204     if(isEmpty())
0205         return;
0206 
0207     
0208     for (XMLSize_t buckInd = 0; buckInd < fHashModulus; buckInd++)
0209     {
0210         
0211         RefHashTableBucketElem<TVal>* curElem = fBucketList[buckInd];
0212         RefHashTableBucketElem<TVal>* nextElem;
0213         while (curElem)
0214         {
0215             
0216             nextElem = curElem->fNext;
0217 
0218             
0219             
0220             
0221             
0222             if (fAdoptedElems)
0223                 delete curElem->fData;
0224 
0225             
0226              
0227             
0228             
0229             fMemoryManager->deallocate(curElem);
0230             curElem = nextElem;
0231         }
0232 
0233         
0234         fBucketList[buckInd] = 0;
0235     }
0236 
0237     fCount = 0;
0238 }
0239 
0240 
0241 
0242 
0243 
0244 template <class TVal, class THasher> TVal* RefHashTableOf<TVal, THasher>::
0245 orphanKey(const void* const key)
0246 {
0247     
0248     TVal* retVal = 0;
0249     XMLSize_t hashVal = fHasher.getHashVal(key, fHashModulus);
0250 
0251     
0252     
0253     
0254     
0255     RefHashTableBucketElem<TVal>* curElem = fBucketList[hashVal];
0256     RefHashTableBucketElem<TVal>* lastElem = 0;
0257 
0258     while (curElem)
0259     {
0260         if (fHasher.equals(key, curElem->fKey))
0261         {
0262             if (!lastElem)
0263             {
0264                 
0265                 fBucketList[hashVal] = curElem->fNext;
0266             }
0267             else
0268             {
0269                 
0270                 lastElem->fNext = curElem->fNext;
0271             }
0272 
0273             retVal = curElem->fData;
0274 
0275             
0276             
0277             
0278             
0279             fMemoryManager->deallocate(curElem);
0280             break;
0281         }
0282 
0283         
0284         lastElem = curElem;
0285         curElem = curElem->fNext;
0286     }
0287 
0288     
0289     if (!retVal)
0290         ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::HshTbl_NoSuchKeyExists, fMemoryManager);
0291 
0292     return retVal;
0293 }
0294 
0295 
0296 
0297 
0298 
0299 
0300 template <class TVal, class THasher>
0301 void RefHashTableOf<TVal, THasher>::cleanup()
0302 {
0303     removeAll();
0304 
0305     
0306     fMemoryManager->deallocate(fBucketList);
0307     fBucketList = 0;
0308 }
0309 
0310 
0311 
0312 
0313 
0314 
0315 template <class TVal, class THasher>
0316 void RefHashTableOf<TVal, THasher>::reinitialize(const THasher& hasher)
0317 {
0318     if (fBucketList)
0319         cleanup();
0320 
0321     fHasher = hasher;
0322 
0323     fHashModulus = fInitialModulus;
0324     initialize(fHashModulus);
0325 }
0326 
0327 
0328 
0329 
0330 
0331 
0332 
0333 
0334 
0335 
0336 
0337 template <class TVal, class THasher>
0338 inline void RefHashTableOf<TVal, THasher>::transferElement(const void* const key1, void* key2)
0339 {
0340     put(key2, orphanKey(key1));
0341 }
0342 
0343 
0344 
0345 
0346 
0347 template <class TVal, class THasher>
0348 inline TVal* RefHashTableOf<TVal, THasher>::get(const void* const key)
0349 {
0350     XMLSize_t hashVal;
0351     RefHashTableBucketElem<TVal>* findIt = findBucketElem(key, hashVal);
0352     return findIt ? findIt->fData : 0;
0353 }
0354 
0355 template <class TVal, class THasher>
0356 inline const TVal* RefHashTableOf<TVal, THasher>::
0357 get(const void* const key) const
0358 {
0359     XMLSize_t hashVal;
0360     const RefHashTableBucketElem<TVal>* findIt = findBucketElem(key, hashVal);
0361     return findIt ? findIt->fData : 0;
0362 }
0363 
0364 template <class TVal, class THasher>
0365 inline MemoryManager* RefHashTableOf<TVal, THasher>::getMemoryManager() const
0366 {
0367     return fMemoryManager;
0368 }
0369 
0370 template <class TVal, class THasher>
0371 inline XMLSize_t RefHashTableOf<TVal, THasher>::getHashModulus() const
0372 {
0373     return fHashModulus;
0374 }
0375 
0376 template <class TVal, class THasher>
0377 inline XMLSize_t RefHashTableOf<TVal, THasher>::getCount() const
0378 {
0379     return fCount;
0380 }
0381 
0382 
0383 
0384 
0385 template <class TVal, class THasher>
0386 inline void RefHashTableOf<TVal, THasher>::setAdoptElements(const bool aValue)
0387 {
0388     fAdoptedElems = aValue;
0389 }
0390 
0391 
0392 
0393 
0394 template <class TVal, class THasher>
0395 void RefHashTableOf<TVal, THasher>::put(void* key, TVal* const valueToAdopt)
0396 {
0397     
0398     XMLSize_t threshold = fHashModulus * 3 / 4;
0399 
0400     
0401     if (fCount >= threshold)
0402         rehash();
0403 
0404     
0405     XMLSize_t hashVal;
0406     RefHashTableBucketElem<TVal>* newBucket = findBucketElem(key, hashVal);
0407 
0408     
0409     
0410     
0411     
0412     if (newBucket)
0413     {
0414         if (fAdoptedElems)
0415             delete newBucket->fData;
0416         newBucket->fData = valueToAdopt;
0417         newBucket->fKey = key;
0418     }
0419     else
0420     {
0421         newBucket =
0422              new (fMemoryManager->allocate(sizeof(RefHashTableBucketElem<TVal>)))
0423              RefHashTableBucketElem<TVal>(key, valueToAdopt, fBucketList[hashVal]);
0424         fBucketList[hashVal] = newBucket;
0425         fCount++;
0426     }
0427 }
0428 
0429 
0430 
0431 
0432 
0433 
0434 template <class TVal, class THasher>
0435 void RefHashTableOf<TVal, THasher>::rehash()
0436 {
0437     const XMLSize_t newMod = (fHashModulus * 2) + 1;
0438 
0439     RefHashTableBucketElem<TVal>** newBucketList =
0440         (RefHashTableBucketElem<TVal>**) fMemoryManager->allocate
0441     (
0442         newMod * sizeof(RefHashTableBucketElem<TVal>*)
0443     );
0444 
0445     
0446     
0447     ArrayJanitor<RefHashTableBucketElem<TVal>*>  guard(newBucketList, fMemoryManager);
0448 
0449     memset(newBucketList, 0, newMod * sizeof(newBucketList[0]));
0450 
0451 
0452     
0453     for (XMLSize_t index = 0; index < fHashModulus; index++)
0454     {
0455         
0456         RefHashTableBucketElem<TVal>* curElem = fBucketList[index];
0457 
0458         while (curElem)
0459         {
0460             
0461             RefHashTableBucketElem<TVal>* const nextElem = curElem->fNext;
0462 
0463             const XMLSize_t hashVal = fHasher.getHashVal(curElem->fKey, newMod);
0464 
0465             RefHashTableBucketElem<TVal>* const newHeadElem = newBucketList[hashVal];
0466 
0467             
0468             curElem->fNext = newHeadElem;
0469             newBucketList[hashVal] = curElem;
0470 
0471             curElem = nextElem;
0472         }
0473     }
0474 
0475     RefHashTableBucketElem<TVal>** const oldBucketList = fBucketList;
0476 
0477     
0478     
0479     fBucketList = guard.release();
0480     fHashModulus = newMod;
0481 
0482     
0483     fMemoryManager->deallocate(oldBucketList);
0484 
0485 }
0486 
0487 template <class TVal, class THasher>
0488 inline RefHashTableBucketElem<TVal>* RefHashTableOf<TVal, THasher>::
0489 findBucketElem(const void* const key, XMLSize_t& hashVal)
0490 {
0491     
0492     hashVal = fHasher.getHashVal(key, fHashModulus);
0493 
0494     
0495     RefHashTableBucketElem<TVal>* curElem = fBucketList[hashVal];
0496     while (curElem)
0497     {
0498         if (fHasher.equals(key, curElem->fKey))
0499             return curElem;
0500 
0501         curElem = curElem->fNext;
0502     }
0503     return 0;
0504 }
0505 
0506 template <class TVal, class THasher>
0507 inline const RefHashTableBucketElem<TVal>* RefHashTableOf<TVal, THasher>::
0508 findBucketElem(const void* const key, XMLSize_t& hashVal) const
0509 {
0510     
0511     hashVal = fHasher.getHashVal(key, fHashModulus);
0512 
0513     
0514     const RefHashTableBucketElem<TVal>* curElem = fBucketList[hashVal];
0515     while (curElem)
0516     {
0517         if (fHasher.equals(key, curElem->fKey))
0518             return curElem;
0519 
0520         curElem = curElem->fNext;
0521     }
0522     return 0;
0523 }
0524 
0525 
0526 
0527 
0528 
0529 template <class TVal, class THasher> RefHashTableOfEnumerator<TVal, THasher>::
0530 RefHashTableOfEnumerator(RefHashTableOf<TVal, THasher>* const toEnum
0531                          , const bool adopt
0532                          , MemoryManager* const manager)
0533     : fAdopted(adopt), fCurElem(0), fCurHash((XMLSize_t)-1), fToEnum(toEnum)
0534     , fMemoryManager(manager)
0535 {
0536     if (!toEnum)
0537         ThrowXMLwithMemMgr(NullPointerException, XMLExcepts::CPtr_PointerIsZero, fMemoryManager);
0538 
0539     
0540     
0541     
0542     
0543     
0544     
0545     
0546     findNext();
0547 }
0548 
0549 template <class TVal, class THasher>
0550 RefHashTableOfEnumerator<TVal, THasher>::~RefHashTableOfEnumerator()
0551 {
0552     if (fAdopted)
0553         delete fToEnum;
0554 }
0555 
0556 
0557 template <class TVal, class THasher> RefHashTableOfEnumerator<TVal, THasher>::
0558 RefHashTableOfEnumerator(const RefHashTableOfEnumerator<TVal, THasher>& toCopy) :
0559     XMLEnumerator<TVal>(toCopy)
0560     , XMemory(toCopy)
0561     , fAdopted(toCopy.fAdopted)
0562     , fCurElem(toCopy.fCurElem)
0563     , fCurHash(toCopy.fCurHash)
0564     , fToEnum(toCopy.fToEnum)
0565     , fMemoryManager(toCopy.fMemoryManager)
0566 {
0567 }
0568 
0569 
0570 
0571 template <class TVal, class THasher>
0572 bool RefHashTableOfEnumerator<TVal, THasher>::hasMoreElements() const
0573 {
0574     
0575     
0576     
0577     
0578     if (!fCurElem && (fCurHash == fToEnum->fHashModulus))
0579         return false;
0580     return true;
0581 }
0582 
0583 template <class TVal, class THasher>
0584 TVal& RefHashTableOfEnumerator<TVal, THasher>::nextElement()
0585 {
0586     
0587     if (!hasMoreElements())
0588         ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::Enum_NoMoreElements, fMemoryManager);
0589 
0590     
0591     
0592     
0593     
0594     RefHashTableBucketElem<TVal>* saveElem = fCurElem;
0595     findNext();
0596 
0597     return *saveElem->fData;
0598 }
0599 
0600 template <class TVal, class THasher>
0601 void* RefHashTableOfEnumerator<TVal, THasher>::nextElementKey()
0602 {
0603     
0604     if (!hasMoreElements())
0605         ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::Enum_NoMoreElements, fMemoryManager);
0606 
0607     
0608     
0609     
0610     
0611     RefHashTableBucketElem<TVal>* saveElem = fCurElem;
0612     findNext();
0613 
0614     return saveElem->fKey;
0615 }
0616 
0617 template <class TVal, class THasher>
0618 void RefHashTableOfEnumerator<TVal, THasher>::Reset()
0619 {
0620     fCurHash = (XMLSize_t)-1;
0621     fCurElem = 0;
0622     findNext();
0623 }
0624 
0625 
0626 
0627 
0628 
0629 
0630 template <class TVal, class THasher>
0631 void RefHashTableOfEnumerator<TVal, THasher>::findNext()
0632 {
0633     
0634     
0635     
0636     
0637     if (fCurElem)
0638         fCurElem = fCurElem->fNext;
0639 
0640     
0641     
0642     
0643     
0644     
0645     if (!fCurElem)
0646     {
0647         fCurHash++;
0648         if (fCurHash == fToEnum->fHashModulus)
0649             return;
0650 
0651         
0652         while (fToEnum->fBucketList[fCurHash]==0)
0653         {
0654             
0655             fCurHash++;
0656             if (fCurHash == fToEnum->fHashModulus)
0657                 return;
0658         }
0659         fCurElem = fToEnum->fBucketList[fCurHash];
0660     }
0661 }
0662 
0663 XERCES_CPP_NAMESPACE_END