Warning, file /include/xercesc/util/RefHashTableOf.c was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
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