File indexing completed on 2025-01-18 10:04:19
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef NCollection_IndexedMap_HeaderFile
0017 #define NCollection_IndexedMap_HeaderFile
0018
0019 #include <NCollection_BaseMap.hxx>
0020 #include <NCollection_TListNode.hxx>
0021 #include <NCollection_StlIterator.hxx>
0022 #include <Standard_NoSuchObject.hxx>
0023
0024 #include <NCollection_DefaultHasher.hxx>
0025
0026 #include <Standard_OutOfRange.hxx>
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 template < class TheKeyType,
0040 class Hasher = NCollection_DefaultHasher<TheKeyType> >
0041 class NCollection_IndexedMap : public NCollection_BaseMap
0042 {
0043 public:
0044
0045 typedef TheKeyType key_type;
0046
0047 protected:
0048
0049 class IndexedMapNode : public NCollection_TListNode<TheKeyType>
0050 {
0051 public:
0052
0053 IndexedMapNode (const TheKeyType& theKey1,
0054 const Standard_Integer theIndex,
0055 NCollection_ListNode* theNext1)
0056 : NCollection_TListNode<TheKeyType> (theKey1, theNext1),
0057 myIndex (theIndex)
0058 {}
0059
0060 IndexedMapNode (TheKeyType&& theKey1,
0061 const Standard_Integer theIndex,
0062 NCollection_ListNode* theNext1)
0063 : NCollection_TListNode<TheKeyType> (std::forward<TheKeyType>(theKey1), theNext1),
0064 myIndex (theIndex)
0065 {}
0066
0067 TheKeyType& Key1() { return this->ChangeValue(); }
0068
0069
0070 Standard_Integer& Index() { return myIndex; }
0071
0072
0073 static void delNode (NCollection_ListNode * theNode,
0074 Handle(NCollection_BaseAllocator)& theAl)
0075 {
0076 ((IndexedMapNode *) theNode)->~IndexedMapNode();
0077 theAl->Free(theNode);
0078 }
0079
0080 private:
0081 Standard_Integer myIndex;
0082 };
0083
0084 public:
0085
0086 class Iterator
0087 {
0088 public:
0089
0090 Iterator (void) :
0091 myMap(NULL),
0092 myIndex(0) {}
0093
0094 Iterator (const NCollection_IndexedMap& theMap) :
0095 myMap((NCollection_IndexedMap *) &theMap),
0096 myIndex(1) {}
0097
0098 Standard_Boolean More(void) const
0099 { return (myMap != NULL) && (myIndex <= myMap->Extent()); }
0100
0101 void Next(void)
0102 { myIndex++; }
0103
0104 const TheKeyType& Value(void) const
0105 {
0106 Standard_NoSuchObject_Raise_if(!More(), "NCollection_IndexedMap::Iterator::Value");
0107 return myMap->FindKey(myIndex);
0108 }
0109
0110
0111 Standard_Boolean IsEqual (const Iterator& theOther) const
0112 {
0113 return myMap == theOther.myMap && myIndex == theOther.myIndex;
0114 }
0115
0116 private:
0117 NCollection_IndexedMap * myMap;
0118 Standard_Integer myIndex;
0119 };
0120
0121
0122 typedef NCollection_StlIterator<std::forward_iterator_tag, Iterator, TheKeyType, true> const_iterator;
0123
0124
0125 const_iterator cbegin() const { return Iterator (*this); }
0126
0127
0128 const_iterator cend() const { return Iterator(); }
0129
0130 public:
0131
0132
0133
0134 NCollection_IndexedMap() : NCollection_BaseMap (1, true, Handle(NCollection_BaseAllocator)()) {}
0135
0136
0137 explicit NCollection_IndexedMap (const Standard_Integer theNbBuckets,
0138 const Handle(NCollection_BaseAllocator)& theAllocator=0L)
0139 : NCollection_BaseMap (theNbBuckets, true, theAllocator) {}
0140
0141
0142 NCollection_IndexedMap (const NCollection_IndexedMap& theOther)
0143 : NCollection_BaseMap (theOther.NbBuckets(), true, theOther.myAllocator)
0144 { *this = theOther; }
0145
0146
0147 NCollection_IndexedMap(NCollection_IndexedMap&& theOther) noexcept :
0148 NCollection_BaseMap(std::forward<NCollection_BaseMap>(theOther))
0149 {}
0150
0151
0152
0153 void Exchange (NCollection_IndexedMap& theOther)
0154 {
0155 this->exchangeMapsData (theOther);
0156 }
0157
0158
0159
0160 NCollection_IndexedMap& Assign (const NCollection_IndexedMap& theOther)
0161 {
0162 if (this == &theOther)
0163 return *this;
0164
0165 Clear();
0166 Standard_Integer anExt = theOther.Extent();
0167 if (anExt)
0168 {
0169 ReSize (anExt-1);
0170 for (Standard_Integer anIndexIter = 1; anIndexIter <= anExt; ++anIndexIter)
0171 {
0172 const TheKeyType& aKey1 = theOther.FindKey (anIndexIter);
0173 const size_t iK1 = HashCode (aKey1, NbBuckets());
0174 IndexedMapNode* pNode = new (this->myAllocator) IndexedMapNode (aKey1, anIndexIter, myData1[iK1]);
0175 myData1[iK1] = pNode;
0176 myData2[anIndexIter - 1] = pNode;
0177 Increment();
0178 }
0179 }
0180 return *this;
0181 }
0182
0183
0184 NCollection_IndexedMap& operator= (const NCollection_IndexedMap& theOther)
0185 {
0186 return Assign (theOther);
0187 }
0188
0189
0190 NCollection_IndexedMap& operator= (NCollection_IndexedMap&& theOther) noexcept
0191 {
0192 if (this == &theOther)
0193 return *this;
0194 exchangeMapsData(theOther);
0195 return *this;
0196 }
0197
0198
0199 void ReSize (const Standard_Integer theExtent)
0200 {
0201 NCollection_ListNode** ppNewData1 = NULL;
0202 NCollection_ListNode** ppNewData2 = NULL;
0203 Standard_Integer newBuck;
0204 if (BeginResize (theExtent, newBuck, ppNewData1, ppNewData2))
0205 {
0206 if (myData1)
0207 {
0208 for (Standard_Integer aBucketIter = 0; aBucketIter <= NbBuckets(); ++aBucketIter)
0209 {
0210 if (myData1[aBucketIter])
0211 {
0212 IndexedMapNode* p = (IndexedMapNode* )myData1[aBucketIter];
0213 while (p)
0214 {
0215 const size_t iK1 = HashCode (p->Key1(), newBuck);
0216 IndexedMapNode* q = (IndexedMapNode* )p->Next();
0217 p->Next() = ppNewData1[iK1];
0218 ppNewData1[iK1] = p;
0219 p = q;
0220 }
0221 }
0222 }
0223 }
0224 EndResize (theExtent, newBuck, ppNewData1, (NCollection_ListNode**)
0225 Standard::Reallocate(myData2, (newBuck + 1) * sizeof(NCollection_ListNode*)));
0226 }
0227 }
0228
0229
0230 Standard_Integer Add (const TheKeyType& theKey1)
0231 {
0232 if (Resizable())
0233 {
0234 ReSize (Extent());
0235 }
0236 IndexedMapNode* aNode;
0237 size_t aHash;
0238 if (lookup(theKey1, aNode, aHash))
0239 {
0240 return aNode->Index();
0241 }
0242 const Standard_Integer aNewIndex = Increment();
0243 aNode = new (this->myAllocator) IndexedMapNode (theKey1, aNewIndex, myData1[aHash]);
0244 myData1[aHash] = aNode;
0245 myData2[aNewIndex - 1] = aNode;
0246 return aNewIndex;
0247 }
0248
0249
0250 Standard_Integer Add (TheKeyType&& theKey1)
0251 {
0252 if (Resizable())
0253 {
0254 ReSize(Extent());
0255 }
0256 size_t aHash;
0257 IndexedMapNode* aNode;
0258 if (lookup(theKey1, aNode, aHash))
0259 {
0260 return aNode->Index();
0261 }
0262 const Standard_Integer aNewIndex = Increment();
0263 aNode = new (this->myAllocator) IndexedMapNode(std::forward<TheKeyType>(theKey1),
0264 aNewIndex, myData1[aHash]);
0265 myData1[aHash] = aNode;
0266 myData2[aNewIndex - 1] = aNode;
0267 return aNewIndex;
0268 }
0269
0270
0271 Standard_Boolean Contains (const TheKeyType& theKey1) const
0272 {
0273 IndexedMapNode* p;
0274 return lookup(theKey1, p);
0275 }
0276
0277
0278 void Substitute (const Standard_Integer theIndex,
0279 const TheKeyType& theKey1)
0280 {
0281 Standard_OutOfRange_Raise_if (theIndex < 1 || theIndex > Extent(),
0282 "NCollection_IndexedMap::Substitute : "
0283 "Index is out of range");
0284
0285
0286 IndexedMapNode* aNode;
0287 size_t aHash;
0288 if (lookup(theKey1, aNode, aHash))
0289 {
0290 if (aNode->Index() != theIndex)
0291 {
0292 throw Standard_DomainError ("NCollection_IndexedMap::Substitute : "
0293 "Attempt to substitute existing key");
0294 }
0295 aNode->Key1() = theKey1;
0296 return;
0297 }
0298
0299 aNode = (IndexedMapNode* )myData2[theIndex - 1];
0300
0301
0302 const size_t iK = HashCode (aNode->Key1(), NbBuckets());
0303 IndexedMapNode * q = (IndexedMapNode *) myData1[iK];
0304 if (q == aNode)
0305 myData1[iK] = (IndexedMapNode *) aNode->Next();
0306 else
0307 {
0308 while (q->Next() != aNode)
0309 q = (IndexedMapNode *) q->Next();
0310 q->Next() = aNode->Next();
0311 }
0312
0313
0314 aNode->Key1() = theKey1;
0315 aNode->Next() = myData1[aHash];
0316 myData1[aHash] = aNode;
0317 }
0318
0319
0320 void Swap (const Standard_Integer theIndex1,
0321 const Standard_Integer theIndex2)
0322 {
0323 Standard_OutOfRange_Raise_if (theIndex1 < 1 || theIndex1 > Extent()
0324 || theIndex2 < 1 || theIndex2 > Extent(), "NCollection_IndexedMap::Swap");
0325
0326 if (theIndex1 == theIndex2)
0327 {
0328 return;
0329 }
0330
0331 IndexedMapNode* aP1 = (IndexedMapNode* )myData2[theIndex1 - 1];
0332 IndexedMapNode* aP2 = (IndexedMapNode* )myData2[theIndex2 - 1];
0333 std::swap (aP1->Index(), aP2->Index());
0334 myData2[theIndex2 - 1] = aP1;
0335 myData2[theIndex1 - 1] = aP2;
0336 }
0337
0338
0339 void RemoveLast (void)
0340 {
0341 const Standard_Integer aLastIndex = Extent();
0342 Standard_OutOfRange_Raise_if (aLastIndex == 0, "NCollection_IndexedMap::RemoveLast");
0343
0344
0345 IndexedMapNode* p = (IndexedMapNode* )myData2[aLastIndex - 1];
0346 myData2[aLastIndex - 1] = NULL;
0347
0348
0349 const size_t iK1 = HashCode (p->Key1(), NbBuckets());
0350 IndexedMapNode* q = (IndexedMapNode *) myData1[iK1];
0351 if (q == p)
0352 myData1[iK1] = (IndexedMapNode *) p->Next();
0353 else
0354 {
0355 while (q->Next() != p)
0356 q = (IndexedMapNode *) q->Next();
0357 q->Next() = p->Next();
0358 }
0359 p->~IndexedMapNode();
0360 this->myAllocator->Free(p);
0361 Decrement();
0362 }
0363
0364
0365
0366 void RemoveFromIndex(const Standard_Integer theIndex)
0367 {
0368 Standard_OutOfRange_Raise_if(theIndex < 1 || theIndex > Extent(), "NCollection_IndexedMap::RemoveFromIndex");
0369 const Standard_Integer aLastInd = Extent();
0370 if (theIndex != aLastInd)
0371 {
0372 Swap(theIndex, aLastInd);
0373 }
0374 RemoveLast();
0375 }
0376
0377
0378
0379 Standard_Boolean RemoveKey (const TheKeyType& theKey1)
0380 {
0381 Standard_Integer anIndToRemove = FindIndex(theKey1);
0382 if (anIndToRemove < 1)
0383 {
0384 return Standard_False;
0385 }
0386
0387 RemoveFromIndex (anIndToRemove);
0388 return Standard_True;
0389 }
0390
0391
0392 const TheKeyType& FindKey (const Standard_Integer theIndex) const
0393 {
0394 Standard_OutOfRange_Raise_if (theIndex < 1 || theIndex > Extent(), "NCollection_IndexedMap::FindKey");
0395 IndexedMapNode* pNode2 = (IndexedMapNode* )myData2[theIndex - 1];
0396 return pNode2->Key1();
0397 }
0398
0399
0400 const TheKeyType& operator() (const Standard_Integer theIndex) const
0401 { return FindKey (theIndex); }
0402
0403
0404 Standard_Integer FindIndex(const TheKeyType& theKey1) const
0405 {
0406 IndexedMapNode* aNode;
0407 if (lookup(theKey1, aNode))
0408 {
0409 return aNode->Index();
0410 }
0411 return 0;
0412 }
0413
0414
0415
0416 void Clear(const Standard_Boolean doReleaseMemory = Standard_False)
0417 { Destroy (IndexedMapNode::delNode, doReleaseMemory); }
0418
0419
0420 void Clear (const Handle(NCollection_BaseAllocator)& theAllocator)
0421 {
0422 Clear(theAllocator != this->myAllocator);
0423 this->myAllocator = ( ! theAllocator.IsNull() ? theAllocator :
0424 NCollection_BaseAllocator::CommonBaseAllocator() );
0425 }
0426
0427
0428 virtual ~NCollection_IndexedMap (void)
0429 { Clear(true); }
0430
0431
0432 Standard_Integer Size(void) const
0433 { return Extent(); }
0434
0435 protected:
0436
0437
0438
0439
0440
0441
0442 Standard_Boolean lookup(const TheKeyType& theKey, IndexedMapNode*& theNode, size_t& theHash) const
0443 {
0444 theHash = HashCode(theKey, NbBuckets());
0445 if (IsEmpty())
0446 return Standard_False;
0447 for (theNode = (IndexedMapNode*)myData1[theHash];
0448 theNode; theNode = (IndexedMapNode*)theNode->Next())
0449 {
0450 if (IsEqual(theNode->Key1(), theKey))
0451 return Standard_True;
0452 }
0453 return Standard_False;
0454 }
0455
0456
0457
0458
0459
0460 Standard_Boolean lookup(const TheKeyType& theKey, IndexedMapNode*& theNode) const
0461 {
0462 if (IsEmpty())
0463 return Standard_False;
0464 for (theNode = (IndexedMapNode*)myData1[HashCode(theKey, NbBuckets())];
0465 theNode; theNode = (IndexedMapNode*)theNode->Next())
0466 {
0467 if (IsEqual(theNode->Key1(), theKey))
0468 {
0469 return Standard_True;
0470 }
0471 }
0472 return Standard_False;
0473 }
0474
0475 bool IsEqual(const TheKeyType& theKey1,
0476 const TheKeyType& theKey2) const
0477 {
0478 return myHasher(theKey1, theKey2);
0479 }
0480
0481 size_t HashCode(const TheKeyType& theKey,
0482 const int theUpperBound) const
0483 {
0484 return myHasher(theKey) % theUpperBound + 1;
0485 }
0486
0487 protected:
0488
0489 Hasher myHasher;
0490 };
0491
0492 #endif