Warning, file /include/xercesc/util/RefHash2KeysTableOf.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/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