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