File indexing completed on 2025-01-18 10:15:12
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/Hash2KeysSetOf.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 THasher>
0042 Hash2KeysSetOf<THasher>::Hash2KeysSetOf(
0043 const XMLSize_t modulus,
0044 MemoryManager* const manager)
0045
0046 : fMemoryManager(manager)
0047 , fBucketList(0)
0048 , fHashModulus(modulus)
0049 , fCount(0)
0050 , fAvailable(0)
0051 {
0052 initialize(modulus);
0053 }
0054
0055 template <class THasher>
0056 Hash2KeysSetOf<THasher>::Hash2KeysSetOf(
0057 const XMLSize_t modulus,
0058 const THasher& hasher,
0059 MemoryManager* const manager)
0060
0061 : fMemoryManager(manager)
0062 , fBucketList(0)
0063 , fHashModulus(modulus)
0064 , fCount(0)
0065 , fAvailable(0)
0066 , fHasher (hasher)
0067 {
0068 initialize(modulus);
0069 }
0070
0071 template <class THasher>
0072 void Hash2KeysSetOf<THasher>::initialize(const XMLSize_t modulus)
0073 {
0074 if (modulus == 0)
0075 ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::HshTbl_ZeroModulus, fMemoryManager);
0076
0077
0078 fBucketList = (Hash2KeysSetBucketElem**) fMemoryManager->allocate
0079 (
0080 fHashModulus * sizeof(Hash2KeysSetBucketElem*)
0081 );
0082 memset(fBucketList, 0, sizeof(fBucketList[0]) * fHashModulus);
0083 }
0084
0085 template <class THasher>
0086 Hash2KeysSetOf<THasher>::~Hash2KeysSetOf()
0087 {
0088 Hash2KeysSetBucketElem* nextElem;
0089 if(!isEmpty())
0090 {
0091
0092 for (XMLSize_t buckInd = 0; buckInd < fHashModulus; buckInd++)
0093 {
0094
0095 Hash2KeysSetBucketElem* curElem = fBucketList[buckInd];
0096 while (curElem)
0097 {
0098
0099 nextElem = curElem->fNext;
0100 fMemoryManager->deallocate(curElem);
0101 curElem = nextElem;
0102 }
0103
0104
0105 fBucketList[buckInd] = 0;
0106 }
0107 }
0108
0109 Hash2KeysSetBucketElem* curElem = fAvailable;
0110 while (curElem)
0111 {
0112
0113 nextElem = curElem->fNext;
0114 fMemoryManager->deallocate(curElem);
0115 curElem = nextElem;
0116 }
0117 fAvailable = 0;
0118
0119
0120 fMemoryManager->deallocate(fBucketList);
0121 fBucketList = 0;
0122 }
0123
0124
0125
0126
0127
0128 template <class THasher>
0129 bool Hash2KeysSetOf<THasher>::isEmpty() const
0130 {
0131 return (fCount==0);
0132 }
0133
0134 template <class THasher>
0135 bool Hash2KeysSetOf<THasher>::containsKey(const void* const key1, const int key2) const
0136 {
0137 XMLSize_t hashVal;
0138 const Hash2KeysSetBucketElem* findIt = findBucketElem(key1, key2, hashVal);
0139 return (findIt != 0);
0140 }
0141
0142 template <class THasher>
0143 void Hash2KeysSetOf<THasher>::removeKey(const void* const key1, const int key2)
0144 {
0145
0146 XMLSize_t hashVal = fHasher.getHashVal(key1, fHashModulus);
0147 assert(hashVal < fHashModulus);
0148
0149
0150
0151
0152
0153 Hash2KeysSetBucketElem* curElem = fBucketList[hashVal];
0154 Hash2KeysSetBucketElem* lastElem = 0;
0155
0156 while (curElem)
0157 {
0158 if((key2==curElem->fKey2) && (fHasher.equals(key1, curElem->fKey1)))
0159 {
0160 if (!lastElem)
0161 {
0162
0163 fBucketList[hashVal] = curElem->fNext;
0164 }
0165 else
0166 {
0167
0168 lastElem->fNext = curElem->fNext;
0169 }
0170
0171
0172 curElem->fNext=fAvailable;
0173 fAvailable=curElem;
0174
0175 fCount--;
0176 return;
0177 }
0178
0179
0180 lastElem = curElem;
0181 curElem = curElem->fNext;
0182 }
0183
0184
0185 ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::HshTbl_NoSuchKeyExists, fMemoryManager);
0186 }
0187
0188 template <class THasher>
0189 void Hash2KeysSetOf<THasher>::
0190 removeKey(const void* const key1)
0191 {
0192
0193 XMLSize_t hashVal = fHasher.getHashVal(key1, fHashModulus);
0194 assert(hashVal < fHashModulus);
0195
0196
0197
0198
0199
0200 Hash2KeysSetBucketElem* curElem = fBucketList[hashVal];
0201 Hash2KeysSetBucketElem* lastElem = 0;
0202
0203 while (curElem)
0204 {
0205 if(fHasher.equals(key1, curElem->fKey1))
0206 {
0207 if (!lastElem)
0208 {
0209
0210 fBucketList[hashVal] = curElem->fNext;
0211 }
0212 else
0213 {
0214
0215 lastElem->fNext = curElem->fNext;
0216 }
0217
0218 Hash2KeysSetBucketElem* toBeDeleted=curElem;
0219 curElem = curElem->fNext;
0220
0221
0222 toBeDeleted->fNext=fAvailable;
0223 fAvailable=toBeDeleted;
0224
0225 fCount--;
0226 }
0227 else
0228 {
0229
0230 lastElem = curElem;
0231 curElem = curElem->fNext;
0232 }
0233 }
0234 }
0235
0236 template <class THasher>
0237 void Hash2KeysSetOf<THasher>::removeAll()
0238 {
0239 if(isEmpty())
0240 return;
0241
0242 for (XMLSize_t buckInd = 0; buckInd < fHashModulus; buckInd++)
0243 {
0244 if(fBucketList[buckInd]!=0)
0245 {
0246
0247
0248 Hash2KeysSetBucketElem* curElem = fBucketList[buckInd];
0249 while (curElem->fNext)
0250 curElem = curElem->fNext;
0251 curElem->fNext=fAvailable;
0252 fAvailable=fBucketList[buckInd];
0253 fBucketList[buckInd] = 0;
0254 }
0255 }
0256 fCount=0;
0257 }
0258
0259
0260
0261
0262 template <class THasher>
0263 MemoryManager* Hash2KeysSetOf<THasher>::getMemoryManager() const
0264 {
0265 return fMemoryManager;
0266 }
0267
0268 template <class THasher>
0269 XMLSize_t Hash2KeysSetOf<THasher>::getHashModulus() const
0270 {
0271 return fHashModulus;
0272 }
0273
0274
0275
0276
0277 template <class THasher>
0278 void Hash2KeysSetOf<THasher>::put(const void* key1, int key2)
0279 {
0280
0281 XMLSize_t threshold = fHashModulus * 4;
0282
0283
0284 if (fCount >= threshold)
0285 rehash();
0286
0287
0288 XMLSize_t hashVal;
0289 Hash2KeysSetBucketElem* newBucket = findBucketElem(key1, key2, hashVal);
0290
0291
0292
0293
0294
0295 if (newBucket)
0296 {
0297 newBucket->fKey1 = key1;
0298 newBucket->fKey2 = key2;
0299 }
0300 else
0301 {
0302 if(fAvailable==0)
0303 newBucket = (Hash2KeysSetBucketElem*)fMemoryManager->allocate(sizeof(Hash2KeysSetBucketElem));
0304 else
0305 {
0306 newBucket = fAvailable;
0307 fAvailable = fAvailable->fNext;
0308 }
0309 newBucket->fKey1 = key1;
0310 newBucket->fKey2 = key2;
0311 newBucket->fNext = fBucketList[hashVal];
0312 fBucketList[hashVal] = newBucket;
0313 fCount++;
0314 }
0315 }
0316
0317 template <class THasher>
0318 bool Hash2KeysSetOf<THasher>::putIfNotPresent(const void* key1, int key2)
0319 {
0320
0321 XMLSize_t hashVal;
0322 Hash2KeysSetBucketElem* newBucket = findBucketElem(key1, key2, hashVal);
0323
0324
0325
0326
0327
0328 if (newBucket)
0329 return false;
0330
0331
0332 XMLSize_t threshold = fHashModulus * 4;
0333
0334
0335 if (fCount >= threshold)
0336 rehash();
0337
0338 if(fAvailable==0)
0339 newBucket = (Hash2KeysSetBucketElem*)fMemoryManager->allocate(sizeof(Hash2KeysSetBucketElem));
0340 else
0341 {
0342 newBucket = fAvailable;
0343 fAvailable = fAvailable->fNext;
0344 }
0345 newBucket->fKey1 = key1;
0346 newBucket->fKey2 = key2;
0347 newBucket->fNext = fBucketList[hashVal];
0348 fBucketList[hashVal] = newBucket;
0349 fCount++;
0350 return true;
0351 }
0352
0353
0354
0355
0356
0357 template <class THasher>
0358 inline Hash2KeysSetBucketElem* Hash2KeysSetOf<THasher>::
0359 findBucketElem(const void* const key1, const int key2, XMLSize_t& hashVal)
0360 {
0361
0362 hashVal = fHasher.getHashVal(key1, fHashModulus);
0363 assert(hashVal < fHashModulus);
0364
0365
0366 Hash2KeysSetBucketElem* curElem = fBucketList[hashVal];
0367 while (curElem)
0368 {
0369 if((key2==curElem->fKey2) && (fHasher.equals(key1, curElem->fKey1)))
0370 return curElem;
0371
0372 curElem = curElem->fNext;
0373 }
0374 return 0;
0375 }
0376
0377 template <class THasher>
0378 inline const Hash2KeysSetBucketElem* Hash2KeysSetOf<THasher>::
0379 findBucketElem(const void* const key1, const int key2, XMLSize_t& hashVal) const
0380 {
0381
0382 hashVal = fHasher.getHashVal(key1, fHashModulus);
0383 assert(hashVal < fHashModulus);
0384
0385
0386 const Hash2KeysSetBucketElem* curElem = fBucketList[hashVal];
0387 while (curElem)
0388 {
0389 if((key2==curElem->fKey2) && (fHasher.equals(key1, curElem->fKey1)))
0390 return curElem;
0391
0392 curElem = curElem->fNext;
0393 }
0394 return 0;
0395 }
0396
0397
0398 template <class THasher>
0399 void Hash2KeysSetOf<THasher>::
0400 rehash()
0401 {
0402 const XMLSize_t newMod = (fHashModulus * 8)+1;
0403
0404 Hash2KeysSetBucketElem** newBucketList =
0405 (Hash2KeysSetBucketElem**) fMemoryManager->allocate
0406 (
0407 newMod * sizeof(Hash2KeysSetBucketElem*)
0408 );
0409
0410
0411
0412 ArrayJanitor<Hash2KeysSetBucketElem*> guard(newBucketList, fMemoryManager);
0413
0414 memset(newBucketList, 0, newMod * sizeof(newBucketList[0]));
0415
0416
0417 for (XMLSize_t index = 0; index < fHashModulus; index++)
0418 {
0419
0420 Hash2KeysSetBucketElem* curElem = fBucketList[index];
0421 while (curElem)
0422 {
0423
0424 Hash2KeysSetBucketElem* nextElem = curElem->fNext;
0425
0426 const XMLSize_t hashVal = fHasher.getHashVal(curElem->fKey1, newMod);
0427 assert(hashVal < newMod);
0428
0429 Hash2KeysSetBucketElem* newHeadElem = newBucketList[hashVal];
0430
0431
0432 curElem->fNext = newHeadElem;
0433 newBucketList[hashVal] = curElem;
0434
0435 curElem = nextElem;
0436 }
0437 }
0438
0439 Hash2KeysSetBucketElem** const oldBucketList = fBucketList;
0440
0441
0442
0443 fBucketList = guard.release();
0444 fHashModulus = newMod;
0445
0446
0447 fMemoryManager->deallocate(oldBucketList);
0448
0449 }
0450
0451
0452
0453
0454
0455
0456 template <class THasher>
0457 Hash2KeysSetOfEnumerator<THasher>::
0458 Hash2KeysSetOfEnumerator(Hash2KeysSetOf<THasher>* const toEnum
0459 , const bool adopt
0460 , MemoryManager* const manager)
0461 : fAdopted(adopt), fCurElem(0), fCurHash((XMLSize_t)-1), fToEnum(toEnum)
0462 , fMemoryManager(manager)
0463 , fLockPrimaryKey(0)
0464 {
0465 if (!toEnum)
0466 ThrowXMLwithMemMgr(NullPointerException, XMLExcepts::CPtr_PointerIsZero, fMemoryManager);
0467
0468
0469
0470
0471
0472
0473
0474
0475 findNext();
0476 }
0477
0478 template <class THasher>
0479 Hash2KeysSetOfEnumerator<THasher>::~Hash2KeysSetOfEnumerator()
0480 {
0481 if (fAdopted)
0482 delete fToEnum;
0483 }
0484
0485
0486
0487
0488
0489 template <class THasher>
0490 bool Hash2KeysSetOfEnumerator<THasher>::hasMoreElements() const
0491 {
0492
0493
0494
0495
0496 if (!fCurElem && (fCurHash == fToEnum->fHashModulus))
0497 return false;
0498 return true;
0499 }
0500
0501 template <class THasher>
0502 void Hash2KeysSetOfEnumerator<THasher>::nextElementKey(const void*& retKey1, int& retKey2)
0503 {
0504
0505 if (!hasMoreElements())
0506 ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::Enum_NoMoreElements, fMemoryManager);
0507
0508
0509
0510
0511
0512 Hash2KeysSetBucketElem* saveElem = fCurElem;
0513 findNext();
0514
0515 retKey1 = saveElem->fKey1;
0516 retKey2 = saveElem->fKey2;
0517
0518 return;
0519 }
0520
0521 template <class THasher>
0522 void Hash2KeysSetOfEnumerator<THasher>::Reset()
0523 {
0524 if(fLockPrimaryKey)
0525 fCurHash=fToEnum->fHasher.getHashVal(fLockPrimaryKey, fToEnum->fHashModulus);
0526 else
0527 fCurHash = (XMLSize_t)-1;
0528
0529 fCurElem = 0;
0530 findNext();
0531 }
0532
0533
0534 template <class THasher>
0535 void Hash2KeysSetOfEnumerator<THasher>::setPrimaryKey(const void* key)
0536 {
0537 fLockPrimaryKey=key;
0538 Reset();
0539 }
0540
0541
0542
0543
0544 template <class THasher>
0545 void Hash2KeysSetOfEnumerator<THasher>::findNext()
0546 {
0547
0548 if(fLockPrimaryKey)
0549 {
0550 if(!fCurElem)
0551 fCurElem = fToEnum->fBucketList[fCurHash];
0552 else
0553 fCurElem = fCurElem->fNext;
0554 while (fCurElem && (!fToEnum->fHasher.equals(fLockPrimaryKey, fCurElem->fKey1)))
0555 fCurElem = fCurElem->fNext;
0556
0557 if(!fCurElem)
0558 fCurHash = fToEnum->fHashModulus;
0559 return;
0560 }
0561
0562
0563
0564
0565 if (fCurElem)
0566 fCurElem = fCurElem->fNext;
0567
0568
0569
0570
0571
0572
0573 if (!fCurElem)
0574 {
0575 fCurHash++;
0576 if (fCurHash == fToEnum->fHashModulus)
0577 return;
0578
0579
0580 while (fToEnum->fBucketList[fCurHash]==0)
0581 {
0582
0583 fCurHash++;
0584 if (fCurHash == fToEnum->fHashModulus)
0585 return;
0586 }
0587 fCurElem = fToEnum->fBucketList[fCurHash];
0588 }
0589 }
0590
0591 XERCES_CPP_NAMESPACE_END