File indexing completed on 2025-01-30 10:27:26
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/ValueHashTableOf.hpp>
0028 #endif
0029
0030 #include <xercesc/util/NullPointerException.hpp>
0031 #include <xercesc/util/Janitor.hpp>
0032 #include <assert.h>
0033 #include <new>
0034
0035 XERCES_CPP_NAMESPACE_BEGIN
0036
0037
0038
0039
0040 template <class TVal, class THasher>
0041 ValueHashTableOf<TVal, THasher>::ValueHashTableOf( const XMLSize_t modulus
0042 , const THasher& hasher
0043 , MemoryManager* const manager)
0044 : fMemoryManager(manager)
0045 , fBucketList(0)
0046 , fHashModulus(modulus)
0047 , fInitialModulus(modulus)
0048 , fCount(0)
0049 , fHasher(hasher)
0050 {
0051 initialize(modulus);
0052 }
0053
0054 template <class TVal, class THasher>
0055 ValueHashTableOf<TVal, THasher>::ValueHashTableOf( const XMLSize_t modulus
0056 , MemoryManager* const manager)
0057 : fMemoryManager(manager)
0058 , fBucketList(0)
0059 , fHashModulus(modulus)
0060 , fInitialModulus(modulus)
0061 , fCount(0)
0062 , fHasher()
0063 {
0064 initialize(modulus);
0065 }
0066
0067 template <class TVal, class THasher>
0068 void ValueHashTableOf<TVal, THasher>::initialize(const XMLSize_t modulus)
0069 {
0070 if (modulus == 0)
0071 ThrowXMLwithMemMgr(IllegalArgumentException, XMLExcepts::HshTbl_ZeroModulus, fMemoryManager);
0072
0073
0074 fBucketList = (ValueHashTableBucketElem<TVal>**) fMemoryManager->allocate
0075 (
0076 fHashModulus * sizeof(ValueHashTableBucketElem<TVal>*)
0077 );
0078 memset(fBucketList, 0, sizeof(fBucketList[0]) * fHashModulus);
0079 }
0080
0081 template <class TVal, class THasher>
0082 ValueHashTableOf<TVal, THasher>::~ValueHashTableOf()
0083 {
0084 removeAll();
0085
0086
0087 fMemoryManager->deallocate(fBucketList);
0088 }
0089
0090
0091
0092
0093
0094 template <class TVal, class THasher>
0095 bool ValueHashTableOf<TVal, THasher>::isEmpty() const
0096 {
0097 return fCount==0;
0098 }
0099
0100 template <class TVal, class THasher>
0101 bool ValueHashTableOf<TVal, THasher>::
0102 containsKey(const void* const key) const
0103 {
0104 XMLSize_t hashVal;
0105 const ValueHashTableBucketElem<TVal>* findIt = findBucketElem(key, hashVal);
0106 return (findIt != 0);
0107 }
0108
0109 template <class TVal, class THasher>
0110 void ValueHashTableOf<TVal, THasher>::
0111 removeKey(const void* const key)
0112 {
0113 XMLSize_t hashVal;
0114 removeBucketElem(key, hashVal);
0115 }
0116
0117 template <class TVal, class THasher>
0118 void ValueHashTableOf<TVal, THasher>::removeAll()
0119 {
0120 if(isEmpty())
0121 return;
0122
0123
0124 for (XMLSize_t buckInd = 0; buckInd < fHashModulus; buckInd++)
0125 {
0126
0127 ValueHashTableBucketElem<TVal>* curElem = fBucketList[buckInd];
0128 ValueHashTableBucketElem<TVal>* nextElem;
0129 while (curElem)
0130 {
0131
0132 nextElem = curElem->fNext;
0133
0134
0135
0136
0137 fMemoryManager->deallocate(curElem);
0138 curElem = nextElem;
0139 }
0140
0141
0142 fBucketList[buckInd] = 0;
0143 }
0144 fCount = 0;
0145 }
0146
0147
0148
0149
0150
0151 template <class TVal, class THasher>
0152 TVal& ValueHashTableOf<TVal, THasher>::get(const void* const key, MemoryManager* const manager)
0153 {
0154 XMLSize_t hashVal;
0155 ValueHashTableBucketElem<TVal>* findIt = findBucketElem(key, hashVal);
0156 if (!findIt)
0157 ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::HshTbl_NoSuchKeyExists, manager);
0158
0159 return findIt->fData;
0160 }
0161
0162 template <class TVal, class THasher>
0163 const TVal& ValueHashTableOf<TVal, THasher>::
0164 get(const void* const key) const
0165 {
0166 XMLSize_t hashVal;
0167 const ValueHashTableBucketElem<TVal>* findIt = findBucketElem(key, hashVal);
0168 if (!findIt)
0169 ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::HshTbl_NoSuchKeyExists, fMemoryManager);
0170
0171 return findIt->fData;
0172 }
0173
0174
0175
0176
0177
0178 template <class TVal, class THasher>
0179 void ValueHashTableOf<TVal, THasher>::put(void* key, const TVal& valueToAdopt)
0180 {
0181
0182 XMLSize_t threshold = fHashModulus * 3 / 4;
0183
0184
0185 if (fCount >= threshold)
0186 rehash();
0187
0188
0189 XMLSize_t hashVal;
0190 ValueHashTableBucketElem<TVal>* newBucket = findBucketElem(key, hashVal);
0191
0192
0193
0194
0195
0196 if (newBucket)
0197 {
0198 newBucket->fData = valueToAdopt;
0199 newBucket->fKey = key;
0200 }
0201 else
0202 {
0203 newBucket =
0204 new (fMemoryManager->allocate(sizeof(ValueHashTableBucketElem<TVal>)))
0205 ValueHashTableBucketElem<TVal>(key, valueToAdopt, fBucketList[hashVal]);
0206 fBucketList[hashVal] = newBucket;
0207 fCount++;
0208 }
0209 }
0210
0211
0212
0213
0214
0215
0216 template <class TVal, class THasher>
0217 void ValueHashTableOf<TVal, THasher>::rehash()
0218 {
0219 const XMLSize_t newMod = (fHashModulus * 2) + 1;
0220
0221 ValueHashTableBucketElem<TVal>** newBucketList =
0222 (ValueHashTableBucketElem<TVal>**) fMemoryManager->allocate
0223 (
0224 newMod * sizeof(ValueHashTableBucketElem<TVal>*)
0225 );
0226
0227
0228
0229 ArrayJanitor<ValueHashTableBucketElem<TVal>*> guard(newBucketList, fMemoryManager);
0230
0231 memset(newBucketList, 0, newMod * sizeof(newBucketList[0]));
0232
0233
0234
0235 for (XMLSize_t index = 0; index < fHashModulus; index++)
0236 {
0237
0238 ValueHashTableBucketElem<TVal>* curElem = fBucketList[index];
0239
0240 while (curElem)
0241 {
0242
0243 ValueHashTableBucketElem<TVal>* const nextElem = curElem->fNext;
0244
0245 const XMLSize_t hashVal = fHasher.getHashVal(curElem->fKey, newMod);
0246 assert(hashVal < newMod);
0247
0248 ValueHashTableBucketElem<TVal>* const newHeadElem = newBucketList[hashVal];
0249
0250
0251 curElem->fNext = newHeadElem;
0252 newBucketList[hashVal] = curElem;
0253
0254 curElem = nextElem;
0255 }
0256 }
0257
0258 ValueHashTableBucketElem<TVal>** const oldBucketList = fBucketList;
0259
0260
0261
0262 fBucketList = guard.release();
0263 fHashModulus = newMod;
0264
0265
0266 fMemoryManager->deallocate(oldBucketList);
0267
0268 }
0269
0270 template <class TVal, class THasher>
0271 inline ValueHashTableBucketElem<TVal>* ValueHashTableOf<TVal, THasher>::
0272 findBucketElem(const void* const key, XMLSize_t& hashVal)
0273 {
0274
0275 hashVal = fHasher.getHashVal(key, fHashModulus);
0276 assert(hashVal < fHashModulus);
0277
0278
0279 ValueHashTableBucketElem<TVal>* curElem = fBucketList[hashVal];
0280 while (curElem)
0281 {
0282 if (fHasher.equals(key, curElem->fKey))
0283 return curElem;
0284
0285 curElem = curElem->fNext;
0286 }
0287 return 0;
0288 }
0289
0290 template <class TVal, class THasher>
0291 inline const ValueHashTableBucketElem<TVal>* ValueHashTableOf<TVal, THasher>::
0292 findBucketElem(const void* const key, XMLSize_t& hashVal) const
0293 {
0294
0295 hashVal = fHasher.getHashVal(key, fHashModulus);
0296 assert(hashVal < fHashModulus);
0297
0298
0299 const ValueHashTableBucketElem<TVal>* curElem = fBucketList[hashVal];
0300 while (curElem)
0301 {
0302 if (fHasher.equals(key, curElem->fKey))
0303 return curElem;
0304
0305 curElem = curElem->fNext;
0306 }
0307 return 0;
0308 }
0309
0310
0311 template <class TVal, class THasher>
0312 void ValueHashTableOf<TVal, THasher>::
0313 removeBucketElem(const void* const key, XMLSize_t& hashVal)
0314 {
0315
0316 hashVal = fHasher.getHashVal(key, fHashModulus);
0317 assert(hashVal < fHashModulus);
0318
0319
0320
0321
0322
0323 ValueHashTableBucketElem<TVal>* curElem = fBucketList[hashVal];
0324 ValueHashTableBucketElem<TVal>* lastElem = 0;
0325
0326 while (curElem)
0327 {
0328 if (fHasher.equals(key, curElem->fKey))
0329 {
0330 if (!lastElem)
0331 {
0332
0333 fBucketList[hashVal] = curElem->fNext;
0334 }
0335 else
0336 {
0337
0338 lastElem->fNext = curElem->fNext;
0339 }
0340
0341
0342
0343
0344
0345 fMemoryManager->deallocate(curElem);
0346
0347 fCount--;
0348
0349 return;
0350 }
0351
0352
0353 lastElem = curElem;
0354 curElem = curElem->fNext;
0355 }
0356
0357
0358 ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::HshTbl_NoSuchKeyExists, fMemoryManager);
0359 }
0360
0361
0362
0363
0364
0365
0366
0367 template <class TVal, class THasher>
0368 ValueHashTableOfEnumerator<TVal, THasher>::
0369 ValueHashTableOfEnumerator(ValueHashTableOf<TVal, THasher>* const toEnum
0370 , const bool adopt
0371 , MemoryManager* const manager)
0372 : fAdopted(adopt), fCurElem(0), fCurHash((XMLSize_t)-1), fToEnum(toEnum), fMemoryManager(manager)
0373 {
0374 if (!toEnum)
0375 ThrowXMLwithMemMgr(NullPointerException, XMLExcepts::CPtr_PointerIsZero, manager);
0376
0377
0378
0379
0380
0381
0382
0383
0384 findNext();
0385 }
0386
0387 template <class TVal, class THasher>
0388 ValueHashTableOfEnumerator<TVal, THasher>::~ValueHashTableOfEnumerator()
0389 {
0390 if (fAdopted)
0391 delete fToEnum;
0392 }
0393
0394
0395
0396
0397
0398 template <class TVal, class THasher>
0399 bool ValueHashTableOfEnumerator<TVal, THasher>::hasMoreElements() const
0400 {
0401
0402
0403
0404
0405 if (!fCurElem && (fCurHash == fToEnum->fHashModulus))
0406 return false;
0407 return true;
0408 }
0409
0410 template <class TVal, class THasher>
0411 TVal& ValueHashTableOfEnumerator<TVal, THasher>::nextElement()
0412 {
0413
0414 if (!hasMoreElements())
0415 ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::Enum_NoMoreElements, fMemoryManager);
0416
0417
0418
0419
0420
0421 ValueHashTableBucketElem<TVal>* saveElem = fCurElem;
0422 findNext();
0423
0424 return saveElem->fData;
0425 }
0426
0427 template <class TVal, class THasher>
0428 void* ValueHashTableOfEnumerator<TVal, THasher>::nextElementKey()
0429 {
0430
0431 if (!hasMoreElements())
0432 ThrowXMLwithMemMgr(NoSuchElementException, XMLExcepts::Enum_NoMoreElements, fMemoryManager);
0433
0434
0435
0436
0437
0438 ValueHashTableBucketElem<TVal>* saveElem = fCurElem;
0439 findNext();
0440
0441 return saveElem->fKey;
0442 }
0443
0444
0445 template <class TVal, class THasher>
0446 void ValueHashTableOfEnumerator<TVal, THasher>::Reset()
0447 {
0448 fCurHash = (XMLSize_t)-1;
0449 fCurElem = 0;
0450 findNext();
0451 }
0452
0453
0454
0455
0456
0457
0458 template <class TVal, class THasher>
0459 void ValueHashTableOfEnumerator<TVal, THasher>::findNext()
0460 {
0461
0462
0463
0464
0465 if (fCurElem)
0466 fCurElem = fCurElem->fNext;
0467
0468
0469
0470
0471
0472
0473 if (!fCurElem)
0474 {
0475 if (++fCurHash == fToEnum->fHashModulus)
0476 return;
0477
0478
0479 while (fToEnum->fBucketList[fCurHash]==0)
0480 {
0481
0482 if (++fCurHash == fToEnum->fHashModulus)
0483 return;
0484 }
0485 fCurElem = fToEnum->fBucketList[fCurHash];
0486 }
0487 }
0488
0489 XERCES_CPP_NAMESPACE_END