File indexing completed on 2025-01-18 10:15:13
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/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
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
0111 fBucketList = (RefHash2KeysTableBucketElem<TVal>**) fMemoryManager->allocate
0112 (
0113 fHashModulus * sizeof(RefHash2KeysTableBucketElem<TVal>*)
0114 );
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
0124 fMemoryManager->deallocate(fBucketList);
0125 fBucketList = 0;
0126 }
0127
0128
0129
0130
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
0152 XMLSize_t hashVal = fHasher.getHashVal(key1, fHashModulus);
0153 assert(hashVal < fHashModulus);
0154
0155
0156
0157
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
0169 fBucketList[hashVal] = curElem->fNext;
0170 }
0171 else
0172 {
0173
0174 lastElem->fNext = curElem->fNext;
0175 }
0176
0177
0178 if (fAdoptedElems)
0179 delete curElem->fData;
0180
0181
0182
0183
0184
0185 fMemoryManager->deallocate(curElem);
0186 fCount--;
0187 return;
0188 }
0189
0190
0191 lastElem = curElem;
0192 curElem = curElem->fNext;
0193 }
0194
0195
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
0204 XMLSize_t hashVal = fHasher.getHashVal(key1, fHashModulus);
0205 assert(hashVal < fHashModulus);
0206
0207
0208
0209
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
0221 fBucketList[hashVal] = curElem->fNext;
0222 }
0223 else
0224 {
0225
0226 lastElem->fNext = curElem->fNext;
0227 }
0228
0229
0230 if (fAdoptedElems)
0231 delete curElem->fData;
0232
0233 RefHash2KeysTableBucketElem<TVal>* toBeDeleted=curElem;
0234 curElem = curElem->fNext;
0235
0236
0237
0238
0239
0240 fMemoryManager->deallocate(toBeDeleted);
0241 fCount--;
0242 }
0243 else
0244 {
0245
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
0259 for (XMLSize_t buckInd = 0; buckInd < fHashModulus; buckInd++)
0260 {
0261
0262 RefHash2KeysTableBucketElem<TVal>* curElem = fBucketList[buckInd];
0263 RefHash2KeysTableBucketElem<TVal>* nextElem;
0264 while (curElem)
0265 {
0266
0267 nextElem = curElem->fNext;
0268
0269
0270
0271
0272
0273 if (fAdoptedElems)
0274 delete curElem->fData;
0275
0276
0277
0278
0279 fMemoryManager->deallocate(curElem);
0280 curElem = nextElem;
0281 }
0282
0283
0284 fBucketList[buckInd] = 0;
0285 }
0286 fCount=0;
0287 }
0288
0289
0290 template <class TVal, class THasher>
0291 void RefHash2KeysTableOf<TVal, THasher>::transferElement(const void* const key1, void* key2)
0292 {
0293
0294 XMLSize_t hashVal = fHasher.getHashVal(key1, fHashModulus);
0295 assert(hashVal < fHashModulus);
0296
0297
0298
0299
0300
0301 RefHash2KeysTableBucketElem<TVal>* curElem = fBucketList[hashVal];
0302 RefHash2KeysTableBucketElem<TVal>* lastElem = 0;
0303
0304 while (curElem)
0305 {
0306
0307 if(fHasher.equals(key1, curElem->fKey1))
0308 {
0309 if (!lastElem)
0310 {
0311
0312 fBucketList[hashVal] = curElem->fNext;
0313 }
0314 else
0315 {
0316
0317 lastElem->fNext = curElem->fNext;
0318 }
0319
0320
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
0342 curElem = curElem->fNext;
0343
0344
0345
0346
0347
0348 fMemoryManager->deallocate(elemToDelete);
0349 }
0350 else
0351 {
0352
0353 lastElem = curElem;
0354 curElem = curElem->fNext;
0355 }
0356 }
0357 }
0358
0359
0360
0361
0362
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
0399
0400 template <class TVal, class THasher>
0401 void RefHash2KeysTableOf<TVal, THasher>::put(void* key1, int key2, TVal* const valueToAdopt)
0402 {
0403
0404 XMLSize_t threshold = fHashModulus * 4;
0405
0406
0407 if (fCount >= threshold)
0408 rehash();
0409
0410
0411 XMLSize_t hashVal;
0412 RefHash2KeysTableBucketElem<TVal>* newBucket = findBucketElem(key1, key2, hashVal);
0413
0414
0415
0416
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
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
0446 hashVal = fHasher.getHashVal(key1, fHashModulus);
0447 assert(hashVal < fHashModulus);
0448
0449
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
0466 hashVal = fHasher.getHashVal(key1, fHashModulus);
0467 assert(hashVal < fHashModulus);
0468
0469
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 );
0493
0494
0495
0496 ArrayJanitor<RefHash2KeysTableBucketElem<TVal>*> guard(newBucketList, fMemoryManager);
0497
0498 memset(newBucketList, 0, newMod * sizeof(newBucketList[0]));
0499
0500
0501 for (XMLSize_t index = 0; index < fHashModulus; index++)
0502 {
0503
0504 RefHash2KeysTableBucketElem<TVal>* curElem = fBucketList[index];
0505 while (curElem)
0506 {
0507
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
0516 curElem->fNext = newHeadElem;
0517 newBucketList[hashVal] = curElem;
0518
0519 curElem = nextElem;
0520 }
0521 }
0522
0523 RefHash2KeysTableBucketElem<TVal>** const oldBucketList = fBucketList;
0524
0525
0526
0527 fBucketList = guard.release();
0528 fHashModulus = newMod;
0529
0530
0531 fMemoryManager->deallocate(oldBucketList);
0532
0533 }
0534
0535
0536
0537
0538
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
0554
0555
0556
0557
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
0572
0573 template <class TVal, class THasher>
0574 bool RefHash2KeysTableOfEnumerator<TVal, THasher>::hasMoreElements() const
0575 {
0576
0577
0578
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
0589 if (!hasMoreElements())
0590 ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::Enum_NoMoreElements, fMemoryManager);
0591
0592
0593
0594
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
0606 if (!hasMoreElements())
0607 ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::Enum_NoMoreElements, fMemoryManager);
0608
0609
0610
0611
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
0644
0645 template <class TVal, class THasher>
0646 void RefHash2KeysTableOfEnumerator<TVal, THasher>::findNext()
0647 {
0648
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
0658 if(!fCurElem)
0659 fCurHash = fToEnum->fHashModulus;
0660 return;
0661 }
0662
0663
0664
0665
0666 if (fCurElem)
0667 fCurElem = fCurElem->fNext;
0668
0669
0670
0671
0672
0673
0674 if (!fCurElem)
0675 {
0676 fCurHash++;
0677 if (fCurHash == fToEnum->fHashModulus)
0678 return;
0679
0680
0681 while (fToEnum->fBucketList[fCurHash]==0)
0682 {
0683
0684 fCurHash++;
0685 if (fCurHash == fToEnum->fHashModulus)
0686 return;
0687 }
0688 fCurElem = fToEnum->fBucketList[fCurHash];
0689 }
0690 }
0691
0692 XERCES_CPP_NAMESPACE_END