File indexing completed on 2025-01-30 10:27:25
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