File indexing completed on 2026-05-02 08:23:04
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef NCollection_IndexedDataMap_HeaderFile
0017 #define NCollection_IndexedDataMap_HeaderFile
0018
0019 #include <NCollection_BaseMap.hxx>
0020 #include <NCollection_TListNode.hxx>
0021 #include <Standard_TypeMismatch.hxx>
0022 #include <Standard_NoSuchObject.hxx>
0023 #include <NCollection_StlIterator.hxx>
0024 #include <NCollection_DefaultHasher.hxx>
0025
0026 #include <Standard_OutOfRange.hxx>
0027 #include <utility>
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048 template <class TheKeyType, class TheItemType, class Hasher = NCollection_DefaultHasher<TheKeyType>>
0049 class NCollection_IndexedDataMap : public NCollection_BaseMap
0050 {
0051 public:
0052
0053 typedef TheKeyType key_type;
0054
0055 typedef TheItemType value_type;
0056 typedef Hasher hasher;
0057
0058 private:
0059
0060 class IndexedDataMapNode : public NCollection_TListNode<TheItemType>
0061 {
0062 public:
0063
0064 IndexedDataMapNode(const TheKeyType& theKey1,
0065 const Standard_Integer theIndex,
0066 const TheItemType& theItem,
0067 NCollection_ListNode* theNext1)
0068 : NCollection_TListNode<TheItemType>(theItem, theNext1),
0069 myKey1(theKey1),
0070 myIndex(theIndex)
0071 {
0072 }
0073
0074
0075 IndexedDataMapNode(TheKeyType&& theKey1,
0076 const Standard_Integer theIndex,
0077 const TheItemType& theItem,
0078 NCollection_ListNode* theNext1)
0079 : NCollection_TListNode<TheItemType>(theItem, theNext1),
0080 myKey1(std::forward<TheKeyType>(theKey1)),
0081 myIndex(theIndex)
0082 {
0083 }
0084
0085
0086 IndexedDataMapNode(const TheKeyType& theKey1,
0087 const Standard_Integer theIndex,
0088 TheItemType&& theItem,
0089 NCollection_ListNode* theNext1)
0090 : NCollection_TListNode<TheItemType>(std::forward<TheItemType>(theItem), theNext1),
0091 myKey1(theKey1),
0092 myIndex(theIndex)
0093 {
0094 }
0095
0096
0097 IndexedDataMapNode(TheKeyType&& theKey1,
0098 const Standard_Integer theIndex,
0099 TheItemType&& theItem,
0100 NCollection_ListNode* theNext1)
0101 : NCollection_TListNode<TheItemType>(std::forward<TheItemType>(theItem), theNext1),
0102 myKey1(std::forward<TheKeyType>(theKey1)),
0103 myIndex(theIndex)
0104 {
0105 }
0106
0107
0108 TheKeyType& Key1() { return myKey1; }
0109
0110
0111 Standard_Integer& Index() { return myIndex; }
0112
0113
0114 static void delNode(NCollection_ListNode* theNode, Handle(NCollection_BaseAllocator)& theAl)
0115 {
0116 ((IndexedDataMapNode*)theNode)->~IndexedDataMapNode();
0117 theAl->Free(theNode);
0118 }
0119
0120 private:
0121 TheKeyType myKey1;
0122 Standard_Integer myIndex;
0123 };
0124
0125 public:
0126
0127 class Iterator
0128 {
0129 public:
0130
0131 Iterator()
0132 : myMap(NULL),
0133 myIndex(0)
0134 {
0135 }
0136
0137
0138 Iterator(const NCollection_IndexedDataMap& theMap)
0139 : myMap((NCollection_IndexedDataMap*)&theMap),
0140 myIndex(1)
0141 {
0142 }
0143
0144
0145 Standard_Boolean More(void) const { return (myMap != NULL) && (myIndex <= myMap->Extent()); }
0146
0147
0148 void Next(void) { ++myIndex; }
0149
0150
0151 const TheItemType& Value(void) const
0152 {
0153 Standard_NoSuchObject_Raise_if(!More(), "NCollection_IndexedDataMap::Iterator::Value");
0154 return myMap->FindFromIndex(myIndex);
0155 }
0156
0157
0158 TheItemType& ChangeValue(void) const
0159 {
0160 Standard_NoSuchObject_Raise_if(!More(), "NCollection_IndexedDataMap::Iterator::ChangeValue");
0161 return myMap->ChangeFromIndex(myIndex);
0162 }
0163
0164
0165 const TheKeyType& Key() const
0166 {
0167 Standard_NoSuchObject_Raise_if(!More(), "NCollection_IndexedDataMap::Iterator::Key");
0168 return myMap->FindKey(myIndex);
0169 }
0170
0171
0172 Standard_Boolean IsEqual(const Iterator& theOther) const
0173 {
0174 return myMap == theOther.myMap && myIndex == theOther.myIndex;
0175 }
0176
0177 private:
0178 NCollection_IndexedDataMap* myMap;
0179 Standard_Integer myIndex;
0180 };
0181
0182
0183 typedef NCollection_StlIterator<std::forward_iterator_tag, Iterator, TheItemType, false> iterator;
0184
0185
0186 typedef NCollection_StlIterator<std::forward_iterator_tag, Iterator, TheItemType, true>
0187 const_iterator;
0188
0189
0190 iterator begin() const { return Iterator(*this); }
0191
0192
0193 iterator end() const { return Iterator(); }
0194
0195
0196 const_iterator cbegin() const { return Iterator(*this); }
0197
0198
0199 const_iterator cend() const { return Iterator(); }
0200
0201 public:
0202
0203
0204
0205 NCollection_IndexedDataMap()
0206 : NCollection_BaseMap(1, true, Handle(NCollection_BaseAllocator)())
0207 {
0208 }
0209
0210
0211 explicit NCollection_IndexedDataMap(const Standard_Integer theNbBuckets,
0212 const Handle(NCollection_BaseAllocator)& theAllocator = 0L)
0213 : NCollection_BaseMap(theNbBuckets, true, theAllocator)
0214 {
0215 }
0216
0217
0218 NCollection_IndexedDataMap(const NCollection_IndexedDataMap& theOther)
0219 : NCollection_BaseMap(theOther.NbBuckets(), true, theOther.myAllocator)
0220 {
0221 *this = theOther;
0222 }
0223
0224
0225 NCollection_IndexedDataMap(NCollection_IndexedDataMap&& theOther) noexcept
0226 : NCollection_BaseMap(std::forward<NCollection_BaseMap>(theOther))
0227 {
0228 }
0229
0230
0231
0232 void Exchange(NCollection_IndexedDataMap& theOther) { this->exchangeMapsData(theOther); }
0233
0234
0235
0236 NCollection_IndexedDataMap& Assign(const NCollection_IndexedDataMap& theOther)
0237 {
0238 if (this == &theOther)
0239 return *this;
0240
0241 Clear();
0242 Standard_Integer anExt = theOther.Extent();
0243 if (anExt)
0244 {
0245 ReSize(anExt - 1);
0246 for (Standard_Integer anIndexIter = 1; anIndexIter <= anExt; ++anIndexIter)
0247 {
0248 const TheKeyType& aKey1 = theOther.FindKey(anIndexIter);
0249 const TheItemType& anItem = theOther.FindFromIndex(anIndexIter);
0250 const size_t iK1 = HashCode(aKey1, NbBuckets());
0251 IndexedDataMapNode* pNode =
0252 new (this->myAllocator) IndexedDataMapNode(aKey1, anIndexIter, anItem, myData1[iK1]);
0253 myData1[iK1] = pNode;
0254 myData2[anIndexIter - 1] = pNode;
0255 Increment();
0256 }
0257 }
0258 return *this;
0259 }
0260
0261
0262 NCollection_IndexedDataMap& operator=(const NCollection_IndexedDataMap& theOther)
0263 {
0264 return Assign(theOther);
0265 }
0266
0267
0268 NCollection_IndexedDataMap& operator=(NCollection_IndexedDataMap&& theOther) noexcept
0269 {
0270 if (this == &theOther)
0271 return *this;
0272 exchangeMapsData(theOther);
0273 return *this;
0274 }
0275
0276
0277 void ReSize(const Standard_Integer N)
0278 {
0279 NCollection_ListNode** ppNewData1 = NULL;
0280 NCollection_ListNode** ppNewData2 = NULL;
0281 Standard_Integer newBuck;
0282 if (BeginResize(N, newBuck, ppNewData1, ppNewData2))
0283 {
0284 if (myData1)
0285 {
0286 for (Standard_Integer aBucketIter = 0; aBucketIter <= NbBuckets(); ++aBucketIter)
0287 {
0288 if (myData1[aBucketIter])
0289 {
0290 IndexedDataMapNode* p = (IndexedDataMapNode*)myData1[aBucketIter];
0291 while (p)
0292 {
0293 const size_t iK1 = HashCode(p->Key1(), newBuck);
0294 IndexedDataMapNode* q = (IndexedDataMapNode*)p->Next();
0295 p->Next() = ppNewData1[iK1];
0296 ppNewData1[iK1] = p;
0297 p = q;
0298 }
0299 }
0300 }
0301 }
0302 EndResize(N,
0303 newBuck,
0304 ppNewData1,
0305 (NCollection_ListNode**)
0306 Standard::Reallocate(myData2, (newBuck + 1) * sizeof(NCollection_ListNode*)));
0307 }
0308 }
0309
0310
0311
0312
0313
0314 Standard_Integer Add(const TheKeyType& theKey1, const TheItemType& theItem)
0315 {
0316 if (Resizable())
0317 {
0318 ReSize(Extent());
0319 }
0320 IndexedDataMapNode* aNode;
0321 size_t aHash;
0322 if (lookup(theKey1, aNode, aHash))
0323 {
0324 return aNode->Index();
0325 }
0326 const Standard_Integer aNewIndex = Increment();
0327 aNode = new (this->myAllocator) IndexedDataMapNode(theKey1, aNewIndex, theItem, myData1[aHash]);
0328 myData1[aHash] = aNode;
0329 myData2[aNewIndex - 1] = aNode;
0330 return aNewIndex;
0331 }
0332
0333
0334
0335
0336
0337 Standard_Integer Add(TheKeyType&& theKey1, const TheItemType& theItem)
0338 {
0339 if (Resizable())
0340 {
0341 ReSize(Extent());
0342 }
0343 IndexedDataMapNode* aNode;
0344 size_t aHash;
0345 if (lookup(theKey1, aNode, aHash))
0346 {
0347 return aNode->Index();
0348 }
0349 const Standard_Integer aNewIndex = Increment();
0350 aNode = new (this->myAllocator)
0351 IndexedDataMapNode(std::forward<TheKeyType>(theKey1), aNewIndex, theItem, myData1[aHash]);
0352 myData1[aHash] = aNode;
0353 myData2[aNewIndex - 1] = aNode;
0354 return aNewIndex;
0355 }
0356
0357
0358
0359
0360
0361 Standard_Integer Add(const TheKeyType& theKey1, TheItemType&& theItem)
0362 {
0363 if (Resizable())
0364 {
0365 ReSize(Extent());
0366 }
0367 IndexedDataMapNode* aNode;
0368 size_t aHash;
0369 if (lookup(theKey1, aNode, aHash))
0370 {
0371 return aNode->Index();
0372 }
0373 const Standard_Integer aNewIndex = Increment();
0374 aNode = new (this->myAllocator)
0375 IndexedDataMapNode(theKey1, aNewIndex, std::forward<TheItemType>(theItem), myData1[aHash]);
0376 myData1[aHash] = aNode;
0377 myData2[aNewIndex - 1] = aNode;
0378 return aNewIndex;
0379 }
0380
0381
0382
0383
0384
0385 Standard_Integer Add(TheKeyType&& theKey1, TheItemType&& theItem)
0386 {
0387 if (Resizable())
0388 {
0389 ReSize(Extent());
0390 }
0391 IndexedDataMapNode* aNode;
0392 size_t aHash;
0393 if (lookup(theKey1, aNode, aHash))
0394 {
0395 return aNode->Index();
0396 }
0397 const Standard_Integer aNewIndex = Increment();
0398 aNode = new (this->myAllocator) IndexedDataMapNode(std::forward<TheKeyType>(theKey1),
0399 aNewIndex,
0400 std::forward<TheItemType>(theItem),
0401 myData1[aHash]);
0402 myData1[aHash] = aNode;
0403 myData2[aNewIndex - 1] = aNode;
0404 return aNewIndex;
0405 }
0406
0407
0408 Standard_Boolean Contains(const TheKeyType& theKey1) const
0409 {
0410 IndexedDataMapNode* aNode;
0411 if (lookup(theKey1, aNode))
0412 {
0413 return true;
0414 }
0415 return false;
0416 }
0417
0418
0419 void Substitute(const Standard_Integer theIndex,
0420 const TheKeyType& theKey1,
0421 const TheItemType& theItem)
0422 {
0423 Standard_OutOfRange_Raise_if(theIndex < 1 || theIndex > Extent(),
0424 "NCollection_IndexedDataMap::Substitute : "
0425 "Index is out of range");
0426
0427
0428 size_t aHash;
0429 IndexedDataMapNode* aNode;
0430 if (lookup(theKey1, aNode, aHash))
0431 {
0432 if (aNode->Index() != theIndex)
0433 {
0434 throw Standard_DomainError("NCollection_IndexedDataMap::Substitute : "
0435 "Attempt to substitute existing key");
0436 }
0437 aNode->Key1() = theKey1;
0438 aNode->ChangeValue() = theItem;
0439 return;
0440 }
0441
0442
0443 aNode = (IndexedDataMapNode*)myData2[theIndex - 1];
0444
0445
0446 const size_t iK = HashCode(aNode->Key1(), NbBuckets());
0447 IndexedDataMapNode* q = (IndexedDataMapNode*)myData1[iK];
0448 if (q == aNode)
0449 myData1[iK] = (IndexedDataMapNode*)aNode->Next();
0450 else
0451 {
0452 while (q->Next() != aNode)
0453 q = (IndexedDataMapNode*)q->Next();
0454 q->Next() = aNode->Next();
0455 }
0456
0457
0458 aNode->Key1() = theKey1;
0459 aNode->ChangeValue() = theItem;
0460 aNode->Next() = myData1[aHash];
0461 myData1[aHash] = aNode;
0462 }
0463
0464
0465 void Swap(const Standard_Integer theIndex1, const Standard_Integer theIndex2)
0466 {
0467 Standard_OutOfRange_Raise_if(theIndex1 < 1 || theIndex1 > Extent() || theIndex2 < 1
0468 || theIndex2 > Extent(),
0469 "NCollection_IndexedDataMap::Swap");
0470
0471 if (theIndex1 == theIndex2)
0472 {
0473 return;
0474 }
0475
0476 IndexedDataMapNode* aP1 = (IndexedDataMapNode*)myData2[theIndex1 - 1];
0477 IndexedDataMapNode* aP2 = (IndexedDataMapNode*)myData2[theIndex2 - 1];
0478 std::swap(aP1->Index(), aP2->Index());
0479 myData2[theIndex2 - 1] = aP1;
0480 myData2[theIndex1 - 1] = aP2;
0481 }
0482
0483
0484 void RemoveLast(void)
0485 {
0486 const Standard_Integer aLastIndex = Extent();
0487 Standard_OutOfRange_Raise_if(aLastIndex == 0, "NCollection_IndexedDataMap::RemoveLast");
0488
0489
0490 IndexedDataMapNode* p = (IndexedDataMapNode*)myData2[aLastIndex - 1];
0491 myData2[aLastIndex - 1] = NULL;
0492
0493
0494 const size_t iK1 = HashCode(p->Key1(), NbBuckets());
0495 IndexedDataMapNode* q = (IndexedDataMapNode*)myData1[iK1];
0496 if (q == p)
0497 myData1[iK1] = (IndexedDataMapNode*)p->Next();
0498 else
0499 {
0500 while (q->Next() != p)
0501 q = (IndexedDataMapNode*)q->Next();
0502 q->Next() = p->Next();
0503 }
0504 p->~IndexedDataMapNode();
0505 this->myAllocator->Free(p);
0506 Decrement();
0507 }
0508
0509
0510
0511 void RemoveFromIndex(const Standard_Integer theIndex)
0512 {
0513 const Standard_Integer aLastInd = Extent();
0514 Standard_OutOfRange_Raise_if(theIndex < 1 || theIndex > aLastInd,
0515 "NCollection_IndexedDataMap::Remove");
0516 if (theIndex != aLastInd)
0517 {
0518 Swap(theIndex, aLastInd);
0519 }
0520 RemoveLast();
0521 }
0522
0523
0524
0525 void RemoveKey(const TheKeyType& theKey1)
0526 {
0527 Standard_Integer anIndToRemove = FindIndex(theKey1);
0528 if (anIndToRemove > 0)
0529 {
0530 RemoveFromIndex(anIndToRemove);
0531 }
0532 }
0533
0534
0535 const TheKeyType& FindKey(const Standard_Integer theIndex) const
0536 {
0537 Standard_OutOfRange_Raise_if(theIndex < 1 || theIndex > Extent(),
0538 "NCollection_IndexedDataMap::FindKey");
0539 IndexedDataMapNode* aNode = (IndexedDataMapNode*)myData2[theIndex - 1];
0540 return aNode->Key1();
0541 }
0542
0543
0544 const TheItemType& FindFromIndex(const Standard_Integer theIndex) const
0545 {
0546 Standard_OutOfRange_Raise_if(theIndex < 1 || theIndex > Extent(),
0547 "NCollection_IndexedDataMap::FindFromIndex");
0548 IndexedDataMapNode* aNode = (IndexedDataMapNode*)myData2[theIndex - 1];
0549 return aNode->Value();
0550 }
0551
0552
0553 const TheItemType& operator()(const Standard_Integer theIndex) const
0554 {
0555 return FindFromIndex(theIndex);
0556 }
0557
0558
0559 TheItemType& ChangeFromIndex(const Standard_Integer theIndex)
0560 {
0561 Standard_OutOfRange_Raise_if(theIndex < 1 || theIndex > Extent(),
0562 "NCollection_IndexedDataMap::ChangeFromIndex");
0563 IndexedDataMapNode* aNode = (IndexedDataMapNode*)myData2[theIndex - 1];
0564 return aNode->ChangeValue();
0565 }
0566
0567
0568 TheItemType& operator()(const Standard_Integer theIndex) { return ChangeFromIndex(theIndex); }
0569
0570
0571 Standard_Integer FindIndex(const TheKeyType& theKey1) const
0572 {
0573 IndexedDataMapNode* aNode;
0574 if (lookup(theKey1, aNode))
0575 {
0576 return aNode->Index();
0577 }
0578 return 0;
0579 }
0580
0581
0582 const TheItemType& FindFromKey(const TheKeyType& theKey1) const
0583 {
0584 Standard_NoSuchObject_Raise_if(IsEmpty(), "NCollection_IndexedDataMap::FindFromKey");
0585 IndexedDataMapNode* aNode;
0586 if (lookup(theKey1, aNode))
0587 {
0588 return aNode->Value();
0589 }
0590 throw Standard_NoSuchObject("NCollection_IndexedDataMap::FindFromKey");
0591 }
0592
0593
0594 TheItemType& ChangeFromKey(const TheKeyType& theKey1)
0595 {
0596 Standard_NoSuchObject_Raise_if(IsEmpty(), "NCollection_IndexedDataMap::ChangeFromKey");
0597 IndexedDataMapNode* aNode;
0598 if (lookup(theKey1, aNode))
0599 {
0600 return aNode->ChangeValue();
0601 }
0602 throw Standard_NoSuchObject("NCollection_IndexedDataMap::ChangeFromKey");
0603 }
0604
0605
0606
0607 const TheItemType* Seek(const TheKeyType& theKey1) const
0608 {
0609 return const_cast<NCollection_IndexedDataMap*>(this)->ChangeSeek(theKey1);
0610 }
0611
0612
0613
0614 TheItemType* ChangeSeek(const TheKeyType& theKey1)
0615 {
0616 IndexedDataMapNode* aNode;
0617 if (lookup(theKey1, aNode))
0618 {
0619 return &aNode->ChangeValue();
0620 }
0621 return nullptr;
0622 }
0623
0624
0625
0626 Standard_Boolean FindFromKey(const TheKeyType& theKey1, TheItemType& theValue) const
0627 {
0628 IndexedDataMapNode* aNode;
0629 if (lookup(theKey1, aNode))
0630 {
0631 theValue = aNode->Value();
0632 return Standard_True;
0633 }
0634 return Standard_False;
0635 }
0636
0637
0638
0639 void Clear(const Standard_Boolean doReleaseMemory = Standard_False)
0640 {
0641 Destroy(IndexedDataMapNode::delNode, doReleaseMemory);
0642 }
0643
0644
0645 void Clear(const Handle(NCollection_BaseAllocator)& theAllocator)
0646 {
0647 Clear(theAllocator != this->myAllocator);
0648 this->myAllocator =
0649 (!theAllocator.IsNull() ? theAllocator : NCollection_BaseAllocator::CommonBaseAllocator());
0650 }
0651
0652
0653 virtual ~NCollection_IndexedDataMap(void) { Clear(true); }
0654
0655
0656 Standard_Integer Size(void) const { return Extent(); }
0657
0658 protected:
0659
0660
0661
0662
0663
0664 Standard_Boolean lookup(const TheKeyType& theKey,
0665 IndexedDataMapNode*& theNode,
0666 size_t& theHash) const
0667 {
0668 theHash = HashCode(theKey, NbBuckets());
0669 if (IsEmpty())
0670 return Standard_False;
0671 for (theNode = (IndexedDataMapNode*)myData1[theHash]; theNode;
0672 theNode = (IndexedDataMapNode*)theNode->Next())
0673 {
0674 if (IsEqual(theNode->Key1(), theKey))
0675 return Standard_True;
0676 }
0677 return Standard_False;
0678 }
0679
0680
0681
0682
0683
0684 Standard_Boolean lookup(const TheKeyType& theKey, IndexedDataMapNode*& theNode) const
0685 {
0686 if (IsEmpty())
0687 return Standard_False;
0688 for (theNode = (IndexedDataMapNode*)myData1[HashCode(theKey, NbBuckets())]; theNode;
0689 theNode = (IndexedDataMapNode*)theNode->Next())
0690 {
0691 if (IsEqual(theNode->Key1(), theKey))
0692 {
0693 return Standard_True;
0694 }
0695 }
0696 return Standard_False;
0697 }
0698
0699 bool IsEqual(const TheKeyType& theKey1, const TheKeyType& theKey2) const
0700 {
0701 return myHasher(theKey1, theKey2);
0702 }
0703
0704 size_t HashCode(const TheKeyType& theKey, const int theUpperBound) const
0705 {
0706 return myHasher(theKey) % theUpperBound + 1;
0707 }
0708
0709 protected:
0710 Hasher myHasher;
0711 };
0712
0713 #endif