File indexing completed on 2026-10-29 09:19:57
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 #include <NCollection_ItemsView.hxx>
0026
0027 #include <Standard_OutOfRange.hxx>
0028 #include <functional>
0029 #include <optional>
0030 #include <type_traits>
0031 #include <utility>
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052 template <class TheKeyType, class TheItemType, class Hasher = NCollection_DefaultHasher<TheKeyType>>
0053 class NCollection_IndexedDataMap : public NCollection_BaseMap
0054 {
0055 public:
0056
0057 typedef TheKeyType key_type;
0058
0059 typedef TheItemType value_type;
0060 typedef Hasher hasher;
0061
0062 private:
0063
0064 class IndexedDataMapNode : public NCollection_TListNode<TheItemType>
0065 {
0066 public:
0067
0068 IndexedDataMapNode(const TheKeyType& theKey1,
0069 const int theIndex,
0070 const TheItemType& theItem,
0071 NCollection_ListNode* theNext1)
0072 : NCollection_TListNode<TheItemType>(theItem, theNext1),
0073 myKey1(theKey1),
0074 myIndex(theIndex)
0075 {
0076 }
0077
0078
0079 IndexedDataMapNode(TheKeyType&& theKey1,
0080 const int theIndex,
0081 const TheItemType& theItem,
0082 NCollection_ListNode* theNext1)
0083 : NCollection_TListNode<TheItemType>(theItem, theNext1),
0084 myKey1(std::forward<TheKeyType>(theKey1)),
0085 myIndex(theIndex)
0086 {
0087 }
0088
0089
0090 IndexedDataMapNode(const TheKeyType& theKey1,
0091 const int theIndex,
0092 TheItemType&& theItem,
0093 NCollection_ListNode* theNext1)
0094 : NCollection_TListNode<TheItemType>(std::forward<TheItemType>(theItem), theNext1),
0095 myKey1(theKey1),
0096 myIndex(theIndex)
0097 {
0098 }
0099
0100
0101 IndexedDataMapNode(TheKeyType&& theKey1,
0102 const int theIndex,
0103 TheItemType&& theItem,
0104 NCollection_ListNode* theNext1)
0105 : NCollection_TListNode<TheItemType>(std::forward<TheItemType>(theItem), theNext1),
0106 myKey1(std::forward<TheKeyType>(theKey1)),
0107 myIndex(theIndex)
0108 {
0109 }
0110
0111
0112 template <typename K, typename... Args>
0113 IndexedDataMapNode(K&& theKey1,
0114 const int theIndex,
0115 std::in_place_t,
0116 NCollection_ListNode* theNext1,
0117 Args&&... theArgs)
0118 : NCollection_TListNode<TheItemType>(std::in_place,
0119 theNext1,
0120 std::forward<Args>(theArgs)...),
0121 myKey1(std::forward<K>(theKey1)),
0122 myIndex(theIndex)
0123 {
0124 }
0125
0126
0127 TheKeyType& Key1() noexcept { return myKey1; }
0128
0129
0130 int& Index() noexcept { return myIndex; }
0131
0132
0133 static void delNode(NCollection_ListNode* theNode,
0134 occ::handle<NCollection_BaseAllocator>& theAl) noexcept
0135 {
0136 ((IndexedDataMapNode*)theNode)->~IndexedDataMapNode();
0137 theAl->Free(theNode);
0138 }
0139
0140 private:
0141 TheKeyType myKey1;
0142 int myIndex;
0143 };
0144
0145 public:
0146
0147 class Iterator
0148 {
0149 public:
0150
0151 Iterator()
0152 : myMap(nullptr),
0153 myIndex(0)
0154 {
0155 }
0156
0157
0158 Iterator(const NCollection_IndexedDataMap& theMap)
0159 : myMap((NCollection_IndexedDataMap*)&theMap),
0160 myIndex(1)
0161 {
0162 }
0163
0164
0165 bool More() const noexcept { return (myMap != nullptr) && (myIndex <= myMap->Extent()); }
0166
0167
0168 void Next() noexcept { ++myIndex; }
0169
0170
0171 const TheItemType& Value() const
0172 {
0173 Standard_NoSuchObject_Raise_if(!More(), "NCollection_IndexedDataMap::Iterator::Value");
0174 return myMap->FindFromIndex(myIndex);
0175 }
0176
0177
0178 TheItemType& ChangeValue() const
0179 {
0180 Standard_NoSuchObject_Raise_if(!More(), "NCollection_IndexedDataMap::Iterator::ChangeValue");
0181 return myMap->ChangeFromIndex(myIndex);
0182 }
0183
0184
0185 const TheKeyType& Key() const
0186 {
0187 Standard_NoSuchObject_Raise_if(!More(), "NCollection_IndexedDataMap::Iterator::Key");
0188 return myMap->FindKey(myIndex);
0189 }
0190
0191
0192 bool IsEqual(const Iterator& theOther) const noexcept
0193 {
0194 return myMap == theOther.myMap && myIndex == theOther.myIndex;
0195 }
0196
0197
0198 int Index() const noexcept { return myIndex; }
0199
0200 private:
0201 NCollection_IndexedDataMap* myMap;
0202 int myIndex;
0203 };
0204
0205
0206 typedef NCollection_StlIterator<std::forward_iterator_tag, Iterator, TheItemType, false> iterator;
0207
0208
0209 typedef NCollection_StlIterator<std::forward_iterator_tag, Iterator, TheItemType, true>
0210 const_iterator;
0211
0212
0213 iterator begin() const noexcept { return Iterator(*this); }
0214
0215
0216 iterator end() const noexcept { return Iterator(); }
0217
0218
0219 const_iterator cbegin() const noexcept { return Iterator(*this); }
0220
0221
0222 const_iterator cend() const noexcept { return Iterator(); }
0223
0224 public:
0225
0226
0227
0228
0229 using KeyValueRef = NCollection_ItemsView::KeyValueRef<TheKeyType, TheItemType, false>;
0230
0231
0232 using ConstKeyValueRef = NCollection_ItemsView::KeyValueRef<TheKeyType, TheItemType, true>;
0233
0234
0235
0236 using KeyValueIndexRef = NCollection_ItemsView::KeyValueIndexRef<TheKeyType, TheItemType, false>;
0237
0238
0239 using ConstKeyValueIndexRef =
0240 NCollection_ItemsView::KeyValueIndexRef<TheKeyType, TheItemType, true>;
0241
0242 private:
0243
0244 struct ItemsExtractor
0245 {
0246 static KeyValueRef Extract(const Iterator& theIter)
0247 {
0248 return {theIter.Key(), theIter.ChangeValue()};
0249 }
0250 };
0251
0252
0253 struct ConstItemsExtractor
0254 {
0255 static ConstKeyValueRef Extract(const Iterator& theIter)
0256 {
0257 return {theIter.Key(), theIter.Value()};
0258 }
0259 };
0260
0261
0262 struct IndexedItemsExtractor
0263 {
0264 static KeyValueIndexRef Extract(const Iterator& theIter)
0265 {
0266 return {theIter.Key(), theIter.ChangeValue(), theIter.Index()};
0267 }
0268 };
0269
0270
0271 struct ConstIndexedItemsExtractor
0272 {
0273 static ConstKeyValueIndexRef Extract(const Iterator& theIter)
0274 {
0275 return {theIter.Key(), theIter.Value(), theIter.Index()};
0276 }
0277 };
0278
0279 public:
0280
0281 using ItemsView =
0282 NCollection_ItemsView::View<NCollection_IndexedDataMap, KeyValueRef, ItemsExtractor, false>;
0283
0284
0285 using ConstItemsView = NCollection_ItemsView::
0286 View<NCollection_IndexedDataMap, ConstKeyValueRef, ConstItemsExtractor, true>;
0287
0288
0289 using IndexedItemsView = NCollection_ItemsView::
0290 View<NCollection_IndexedDataMap, KeyValueIndexRef, IndexedItemsExtractor, false>;
0291
0292
0293 using ConstIndexedItemsView = NCollection_ItemsView::
0294 View<NCollection_IndexedDataMap, ConstKeyValueIndexRef, ConstIndexedItemsExtractor, true>;
0295
0296
0297
0298 ItemsView Items() { return ItemsView(*this); }
0299
0300
0301
0302 ConstItemsView Items() const { return ConstItemsView(*this); }
0303
0304
0305
0306 IndexedItemsView IndexedItems() { return IndexedItemsView(*this); }
0307
0308
0309
0310 ConstIndexedItemsView IndexedItems() const { return ConstIndexedItemsView(*this); }
0311
0312 public:
0313
0314
0315
0316 NCollection_IndexedDataMap()
0317 : NCollection_BaseMap(1, true, occ::handle<NCollection_BaseAllocator>())
0318 {
0319 }
0320
0321
0322 explicit NCollection_IndexedDataMap(
0323 const size_t theNbBuckets,
0324 const occ::handle<NCollection_BaseAllocator>& theAllocator = nullptr)
0325 : NCollection_BaseMap(theNbBuckets, true, theAllocator)
0326 {
0327 }
0328
0329
0330 explicit NCollection_IndexedDataMap(
0331 const int theNbBuckets,
0332 const occ::handle<NCollection_BaseAllocator>& theAllocator = nullptr)
0333 : NCollection_IndexedDataMap(NCollection_BaseMap::NbBucketsFromInt(theNbBuckets),
0334 theAllocator)
0335 {
0336 }
0337
0338
0339
0340
0341
0342 explicit NCollection_IndexedDataMap(
0343 const Hasher& theHasher,
0344 const size_t theNbBuckets = 1,
0345 const occ::handle<NCollection_BaseAllocator>& theAllocator = nullptr)
0346 : NCollection_BaseMap(theNbBuckets, true, theAllocator),
0347 myHasher(theHasher)
0348 {
0349 }
0350
0351
0352 explicit NCollection_IndexedDataMap(
0353 const Hasher& theHasher,
0354 const int theNbBuckets,
0355 const occ::handle<NCollection_BaseAllocator>& theAllocator = nullptr)
0356 : NCollection_IndexedDataMap(theHasher,
0357 NCollection_BaseMap::NbBucketsFromInt(theNbBuckets),
0358 theAllocator)
0359 {
0360 }
0361
0362
0363
0364
0365
0366 explicit NCollection_IndexedDataMap(
0367 Hasher&& theHasher,
0368 const size_t theNbBuckets = 1,
0369 const occ::handle<NCollection_BaseAllocator>& theAllocator = nullptr)
0370 : NCollection_BaseMap(theNbBuckets, true, theAllocator),
0371 myHasher(std::move(theHasher))
0372 {
0373 }
0374
0375
0376 explicit NCollection_IndexedDataMap(
0377 Hasher&& theHasher,
0378 const int theNbBuckets,
0379 const occ::handle<NCollection_BaseAllocator>& theAllocator = nullptr)
0380 : NCollection_IndexedDataMap(std::move(theHasher),
0381 NCollection_BaseMap::NbBucketsFromInt(theNbBuckets),
0382 theAllocator)
0383 {
0384 }
0385
0386
0387 NCollection_IndexedDataMap(const NCollection_IndexedDataMap& theOther)
0388 : NCollection_BaseMap(theOther.NbBuckets(), true, theOther.myAllocator),
0389 myHasher(theOther.myHasher)
0390 {
0391 *this = theOther;
0392 }
0393
0394
0395 NCollection_IndexedDataMap(NCollection_IndexedDataMap&& theOther) noexcept
0396 : NCollection_BaseMap(std::forward<NCollection_BaseMap>(theOther)),
0397 myHasher(std::move(theOther.myHasher))
0398 {
0399 }
0400
0401
0402
0403 void Exchange(NCollection_IndexedDataMap& theOther) noexcept
0404 {
0405 this->exchangeMapsData(theOther);
0406 std::swap(myHasher, theOther.myHasher);
0407 }
0408
0409
0410 const Hasher& GetHasher() const noexcept { return myHasher; }
0411
0412
0413
0414 NCollection_IndexedDataMap& Assign(const NCollection_IndexedDataMap& theOther)
0415 {
0416 if (this == &theOther)
0417 return *this;
0418
0419 Clear();
0420 int anExt = theOther.Extent();
0421 if (anExt)
0422 {
0423 ReSize(anExt - 1);
0424 for (int anIndexIter = 1; anIndexIter <= anExt; ++anIndexIter)
0425 {
0426 const TheKeyType& aKey1 = theOther.FindKey(anIndexIter);
0427 const TheItemType& anItem = theOther.FindFromIndex(anIndexIter);
0428 const size_t iK1 = HashCode(aKey1, NbBuckets());
0429 IndexedDataMapNode* pNode =
0430 new (this->myAllocator) IndexedDataMapNode(aKey1, anIndexIter, anItem, myData1[iK1]);
0431 myData1[iK1] = pNode;
0432 myData2[anIndexIter - 1] = pNode;
0433 Increment();
0434 }
0435 }
0436 return *this;
0437 }
0438
0439
0440 NCollection_IndexedDataMap& operator=(const NCollection_IndexedDataMap& theOther)
0441 {
0442 return Assign(theOther);
0443 }
0444
0445
0446 NCollection_IndexedDataMap& operator=(NCollection_IndexedDataMap&& theOther) noexcept
0447 {
0448 if (this == &theOther)
0449 return *this;
0450 exchangeMapsData(theOther);
0451 return *this;
0452 }
0453
0454
0455 void ReSize(const size_t N)
0456 {
0457 NCollection_ListNode** ppNewData1 = nullptr;
0458 NCollection_ListNode** ppNewData2 = nullptr;
0459 size_t newBuck;
0460 if (BeginResize(N, newBuck, ppNewData1, ppNewData2))
0461 {
0462 if (myData1)
0463 {
0464 for (size_t aBucketIter = 0; aBucketIter <= NbBuckets(); ++aBucketIter)
0465 {
0466 if (myData1[aBucketIter])
0467 {
0468 IndexedDataMapNode* p = (IndexedDataMapNode*)myData1[aBucketIter];
0469 while (p)
0470 {
0471 const size_t iK1 = HashCode(p->Key1(), newBuck);
0472 IndexedDataMapNode* q = (IndexedDataMapNode*)p->Next();
0473 p->Next() = ppNewData1[iK1];
0474 ppNewData1[iK1] = p;
0475 p = q;
0476 }
0477 }
0478 }
0479 }
0480 EndResize(N,
0481 newBuck,
0482 ppNewData1,
0483 (NCollection_ListNode**)
0484 Standard::Reallocate(myData2, (newBuck + 1) * sizeof(NCollection_ListNode*)));
0485 }
0486 }
0487
0488 void ReSize(const int N)
0489 {
0490 Standard_OutOfRange_Raise_if(N < 0, "NCollection_IndexedDataMap::ReSize: negative size");
0491 ReSize(static_cast<size_t>(N));
0492 }
0493
0494
0495
0496
0497
0498 int Add(const TheKeyType& theKey1, const TheItemType& theItem)
0499 {
0500 return addImpl(theKey1, theItem);
0501 }
0502
0503
0504
0505
0506
0507 int Add(TheKeyType&& theKey1, const TheItemType& theItem)
0508 {
0509 return addImpl(std::move(theKey1), theItem);
0510 }
0511
0512
0513
0514
0515
0516 int Add(const TheKeyType& theKey1, TheItemType&& theItem)
0517 {
0518 return addImpl(theKey1, std::move(theItem));
0519 }
0520
0521
0522
0523
0524
0525 int Add(TheKeyType&& theKey1, TheItemType&& theItem)
0526 {
0527 return addImpl(std::move(theKey1), std::move(theItem));
0528 }
0529
0530
0531
0532
0533
0534 TheItemType& TryBound(const TheKeyType& theKey1, const TheItemType& theItem)
0535 {
0536 return bindImpl(theKey1, theItem, std::true_type{}, std::true_type{});
0537 }
0538
0539
0540 TheItemType& TryBound(TheKeyType&& theKey1, const TheItemType& theItem)
0541 {
0542 return bindImpl(std::move(theKey1), theItem, std::true_type{}, std::true_type{});
0543 }
0544
0545
0546 TheItemType& TryBound(const TheKeyType& theKey1, TheItemType&& theItem)
0547 {
0548 return bindImpl(theKey1, std::move(theItem), std::true_type{}, std::true_type{});
0549 }
0550
0551
0552 TheItemType& TryBound(TheKeyType&& theKey1, TheItemType&& theItem)
0553 {
0554 return bindImpl(std::move(theKey1), std::move(theItem), std::true_type{}, std::true_type{});
0555 }
0556
0557
0558
0559
0560
0561 bool TryBind(const TheKeyType& theKey1, const TheItemType& theItem)
0562 {
0563 return bindImpl(theKey1, theItem, std::true_type{}, std::false_type{});
0564 }
0565
0566
0567 bool TryBind(TheKeyType&& theKey1, const TheItemType& theItem)
0568 {
0569 return bindImpl(std::move(theKey1), theItem, std::true_type{}, std::false_type{});
0570 }
0571
0572
0573 bool TryBind(const TheKeyType& theKey1, TheItemType&& theItem)
0574 {
0575 return bindImpl(theKey1, std::move(theItem), std::true_type{}, std::false_type{});
0576 }
0577
0578
0579 bool TryBind(TheKeyType&& theKey1, TheItemType&& theItem)
0580 {
0581 return bindImpl(std::move(theKey1), std::move(theItem), std::true_type{}, std::false_type{});
0582 }
0583
0584
0585
0586
0587
0588 bool Bind(const TheKeyType& theKey1, const TheItemType& theItem)
0589 {
0590 return bindImpl(theKey1, theItem, std::false_type{}, std::false_type{});
0591 }
0592
0593
0594 bool Bind(TheKeyType&& theKey1, const TheItemType& theItem)
0595 {
0596 return bindImpl(std::move(theKey1), theItem, std::false_type{}, std::false_type{});
0597 }
0598
0599
0600 bool Bind(const TheKeyType& theKey1, TheItemType&& theItem)
0601 {
0602 return bindImpl(theKey1, std::move(theItem), std::false_type{}, std::false_type{});
0603 }
0604
0605
0606 bool Bind(TheKeyType&& theKey1, TheItemType&& theItem)
0607 {
0608 return bindImpl(std::move(theKey1), std::move(theItem), std::false_type{}, std::false_type{});
0609 }
0610
0611
0612
0613
0614
0615 TheItemType* Bound(const TheKeyType& theKey1, const TheItemType& theItem)
0616 {
0617 return &bindImpl(theKey1, theItem, std::false_type{}, std::true_type{});
0618 }
0619
0620
0621 TheItemType* Bound(TheKeyType&& theKey1, const TheItemType& theItem)
0622 {
0623 return &bindImpl(std::move(theKey1), theItem, std::false_type{}, std::true_type{});
0624 }
0625
0626
0627 TheItemType* Bound(const TheKeyType& theKey1, TheItemType&& theItem)
0628 {
0629 return &bindImpl(theKey1, std::move(theItem), std::false_type{}, std::true_type{});
0630 }
0631
0632
0633 TheItemType* Bound(TheKeyType&& theKey1, TheItemType&& theItem)
0634 {
0635 return &bindImpl(std::move(theKey1), std::move(theItem), std::false_type{}, std::true_type{});
0636 }
0637
0638
0639
0640
0641
0642 template <typename K, typename... Args>
0643 int Emplace(K&& theKey1, Args&&... theArgs)
0644 {
0645 return emplaceImpl(std::forward<K>(theKey1),
0646 std::false_type{},
0647 std::false_type{},
0648 std::forward<Args>(theArgs)...);
0649 }
0650
0651
0652
0653
0654
0655 template <typename K, typename... Args>
0656 TheItemType& Emplaced(K&& theKey1, Args&&... theArgs)
0657 {
0658 return emplaceImpl(std::forward<K>(theKey1),
0659 std::false_type{},
0660 std::true_type{},
0661 std::forward<Args>(theArgs)...);
0662 }
0663
0664
0665
0666
0667
0668 template <typename K, typename... Args>
0669 int TryEmplace(K&& theKey1, Args&&... theArgs)
0670 {
0671 return emplaceImpl(std::forward<K>(theKey1),
0672 std::true_type{},
0673 std::false_type{},
0674 std::forward<Args>(theArgs)...);
0675 }
0676
0677
0678
0679
0680
0681 template <typename K, typename... Args>
0682 TheItemType& TryEmplaced(K&& theKey1, Args&&... theArgs)
0683 {
0684 return emplaceImpl(std::forward<K>(theKey1),
0685 std::true_type{},
0686 std::true_type{},
0687 std::forward<Args>(theArgs)...);
0688 }
0689
0690
0691 bool Contains(const TheKeyType& theKey1) const
0692 {
0693 IndexedDataMapNode* aNode;
0694 return static_cast<bool>(lookup(theKey1, aNode));
0695 }
0696
0697
0698
0699 std::optional<
0700 std::pair<std::reference_wrapper<const TheKeyType>, std::reference_wrapper<const TheItemType>>>
0701 Contained(const TheKeyType& theKey1) const
0702 {
0703 IndexedDataMapNode* aNode;
0704 if (!lookup(theKey1, aNode))
0705 return std::nullopt;
0706 return std::make_pair(std::cref(aNode->Key()), std::cref(aNode->Value()));
0707 }
0708
0709
0710
0711 std::optional<
0712 std::pair<std::reference_wrapper<const TheKeyType>, std::reference_wrapper<TheItemType>>>
0713 Contained(const TheKeyType& theKey1)
0714 {
0715 IndexedDataMapNode* aNode;
0716 if (!lookup(theKey1, aNode))
0717 return std::nullopt;
0718 return std::make_pair(std::cref(aNode->Key()), std::ref(aNode->ChangeValue()));
0719 }
0720
0721
0722 void Substitute(const size_t theIndex, const TheKeyType& theKey1, const TheItemType& theItem)
0723 {
0724 Standard_OutOfRange_Raise_if(theIndex == 0 || theIndex > Size(),
0725 "NCollection_IndexedDataMap::Substitute : "
0726 "Index is out of range");
0727
0728
0729 size_t aHash;
0730 IndexedDataMapNode* aNode;
0731 if (lookup(theKey1, aNode, aHash))
0732 {
0733 if (static_cast<size_t>(aNode->Index()) != theIndex)
0734 {
0735 throw Standard_DomainError("NCollection_IndexedDataMap::Substitute : "
0736 "Attempt to substitute existing key");
0737 }
0738 aNode->Key1() = theKey1;
0739 aNode->ChangeValue() = theItem;
0740 return;
0741 }
0742
0743
0744 aNode = (IndexedDataMapNode*)myData2[theIndex - 1];
0745
0746
0747 const size_t iK = HashCode(aNode->Key1(), NbBuckets());
0748 IndexedDataMapNode* q = (IndexedDataMapNode*)myData1[iK];
0749 if (q == aNode)
0750 myData1[iK] = (IndexedDataMapNode*)aNode->Next();
0751 else
0752 {
0753 while (q->Next() != aNode)
0754 q = (IndexedDataMapNode*)q->Next();
0755 q->Next() = aNode->Next();
0756 }
0757
0758
0759 aNode->Key1() = theKey1;
0760 aNode->ChangeValue() = theItem;
0761 aNode->Next() = myData1[aHash];
0762 myData1[aHash] = aNode;
0763 }
0764
0765 void Substitute(const int theIndex, const TheKeyType& theKey1, const TheItemType& theItem)
0766 {
0767 Standard_OutOfRange_Raise_if(theIndex < 0,
0768 "NCollection_IndexedDataMap::Substitute: negative index");
0769 Substitute(static_cast<size_t>(theIndex), theKey1, theItem);
0770 }
0771
0772
0773 void Swap(const size_t theIndex1, const size_t theIndex2)
0774 {
0775 Standard_OutOfRange_Raise_if(theIndex1 == 0 || theIndex1 > Size() || theIndex2 == 0
0776 || theIndex2 > Size(),
0777 "NCollection_IndexedDataMap::Swap");
0778
0779 if (theIndex1 == theIndex2)
0780 {
0781 return;
0782 }
0783
0784 IndexedDataMapNode* aP1 = (IndexedDataMapNode*)myData2[theIndex1 - 1];
0785 IndexedDataMapNode* aP2 = (IndexedDataMapNode*)myData2[theIndex2 - 1];
0786 std::swap(aP1->Index(), aP2->Index());
0787 myData2[theIndex2 - 1] = aP1;
0788 myData2[theIndex1 - 1] = aP2;
0789 }
0790
0791 void Swap(const int theIndex1, const int theIndex2)
0792 {
0793 Standard_OutOfRange_Raise_if(theIndex1 < 0 || theIndex2 < 0,
0794 "NCollection_IndexedDataMap::Swap: negative index");
0795 Swap(static_cast<size_t>(theIndex1), static_cast<size_t>(theIndex2));
0796 }
0797
0798
0799 void RemoveLast()
0800 {
0801 const size_t aLastIndex = Size();
0802 Standard_OutOfRange_Raise_if(aLastIndex == 0, "NCollection_IndexedDataMap::RemoveLast");
0803
0804
0805 IndexedDataMapNode* p = (IndexedDataMapNode*)myData2[aLastIndex - 1];
0806 myData2[aLastIndex - 1] = nullptr;
0807
0808
0809 const size_t iK1 = HashCode(p->Key1(), NbBuckets());
0810 IndexedDataMapNode* q = (IndexedDataMapNode*)myData1[iK1];
0811 if (q == p)
0812 myData1[iK1] = (IndexedDataMapNode*)p->Next();
0813 else
0814 {
0815 while (q->Next() != p)
0816 q = (IndexedDataMapNode*)q->Next();
0817 q->Next() = p->Next();
0818 }
0819 p->~IndexedDataMapNode();
0820 this->myAllocator->Free(p);
0821 Decrement();
0822 }
0823
0824
0825
0826 void RemoveFromIndex(const size_t theIndex)
0827 {
0828 const size_t aLastInd = Size();
0829 Standard_OutOfRange_Raise_if(theIndex == 0 || theIndex > aLastInd,
0830 "NCollection_IndexedDataMap::Remove");
0831 if (theIndex != aLastInd)
0832 {
0833 Swap(theIndex, aLastInd);
0834 }
0835 RemoveLast();
0836 }
0837
0838 void RemoveFromIndex(const int theIndex)
0839 {
0840 Standard_OutOfRange_Raise_if(theIndex < 0,
0841 "NCollection_IndexedDataMap::RemoveFromIndex: negative index");
0842 RemoveFromIndex(static_cast<size_t>(theIndex));
0843 }
0844
0845
0846
0847 void RemoveKey(const TheKeyType& theKey1)
0848 {
0849 int anIndToRemove = FindIndex(theKey1);
0850 if (anIndToRemove > 0)
0851 {
0852 RemoveFromIndex(static_cast<size_t>(anIndToRemove));
0853 }
0854 }
0855
0856
0857 const TheKeyType& FindKey(const size_t theIndex) const
0858 {
0859 Standard_OutOfRange_Raise_if(theIndex == 0 || theIndex > Size(),
0860 "NCollection_IndexedDataMap::FindKey");
0861 IndexedDataMapNode* aNode = (IndexedDataMapNode*)myData2[theIndex - 1];
0862 return aNode->Key1();
0863 }
0864
0865 const TheKeyType& FindKey(const int theIndex) const
0866 {
0867 Standard_OutOfRange_Raise_if(theIndex < 0,
0868 "NCollection_IndexedDataMap::FindKey: negative index");
0869 return FindKey(static_cast<size_t>(theIndex));
0870 }
0871
0872
0873 const TheItemType& FindFromIndex(const size_t theIndex) const
0874 {
0875 Standard_OutOfRange_Raise_if(theIndex == 0 || theIndex > Size(),
0876 "NCollection_IndexedDataMap::FindFromIndex");
0877 IndexedDataMapNode* aNode = (IndexedDataMapNode*)myData2[theIndex - 1];
0878 return aNode->Value();
0879 }
0880
0881 const TheItemType& FindFromIndex(const int theIndex) const
0882 {
0883 Standard_OutOfRange_Raise_if(theIndex < 0,
0884 "NCollection_IndexedDataMap::FindFromIndex: negative index");
0885 return FindFromIndex(static_cast<size_t>(theIndex));
0886 }
0887
0888
0889 const TheItemType& operator()(const size_t theIndex) const { return FindFromIndex(theIndex); }
0890
0891 const TheItemType& operator()(const int theIndex) const { return FindFromIndex(theIndex); }
0892
0893
0894 TheItemType& ChangeFromIndex(const size_t theIndex)
0895 {
0896 Standard_OutOfRange_Raise_if(theIndex == 0 || theIndex > Size(),
0897 "NCollection_IndexedDataMap::ChangeFromIndex");
0898 IndexedDataMapNode* aNode = (IndexedDataMapNode*)myData2[theIndex - 1];
0899 return aNode->ChangeValue();
0900 }
0901
0902 TheItemType& ChangeFromIndex(const int theIndex)
0903 {
0904 Standard_OutOfRange_Raise_if(theIndex < 0,
0905 "NCollection_IndexedDataMap::ChangeFromIndex: negative index");
0906 return ChangeFromIndex(static_cast<size_t>(theIndex));
0907 }
0908
0909
0910 TheItemType& operator()(const size_t theIndex) { return ChangeFromIndex(theIndex); }
0911
0912 TheItemType& operator()(const int theIndex) { return ChangeFromIndex(theIndex); }
0913
0914
0915 int FindIndex(const TheKeyType& theKey1) const
0916 {
0917 IndexedDataMapNode* aNode;
0918 if (lookup(theKey1, aNode))
0919 {
0920 return aNode->Index();
0921 }
0922 return 0;
0923 }
0924
0925
0926 const TheItemType& FindFromKey(const TheKeyType& theKey1) const
0927 {
0928 Standard_NoSuchObject_Raise_if(IsEmpty(), "NCollection_IndexedDataMap::FindFromKey");
0929 IndexedDataMapNode* aNode;
0930 if (lookup(theKey1, aNode))
0931 {
0932 return aNode->Value();
0933 }
0934 throw Standard_NoSuchObject("NCollection_IndexedDataMap::FindFromKey");
0935 }
0936
0937
0938 TheItemType& ChangeFromKey(const TheKeyType& theKey1)
0939 {
0940 Standard_NoSuchObject_Raise_if(IsEmpty(), "NCollection_IndexedDataMap::ChangeFromKey");
0941 IndexedDataMapNode* aNode;
0942 if (lookup(theKey1, aNode))
0943 {
0944 return aNode->ChangeValue();
0945 }
0946 throw Standard_NoSuchObject("NCollection_IndexedDataMap::ChangeFromKey");
0947 }
0948
0949
0950
0951 const TheItemType* Seek(const TheKeyType& theKey1) const
0952 {
0953 return const_cast<NCollection_IndexedDataMap*>(this)->ChangeSeek(theKey1);
0954 }
0955
0956
0957
0958 TheItemType* ChangeSeek(const TheKeyType& theKey1)
0959 {
0960 IndexedDataMapNode* aNode;
0961 if (lookup(theKey1, aNode))
0962 {
0963 return &aNode->ChangeValue();
0964 }
0965 return nullptr;
0966 }
0967
0968
0969
0970 bool FindFromKey(const TheKeyType& theKey1, TheItemType& theValue) const
0971 {
0972 IndexedDataMapNode* aNode;
0973 if (lookup(theKey1, aNode))
0974 {
0975 theValue = aNode->Value();
0976 return true;
0977 }
0978 return false;
0979 }
0980
0981
0982
0983 void Clear(const bool doReleaseMemory = false)
0984 {
0985 Destroy(IndexedDataMapNode::delNode, doReleaseMemory);
0986 }
0987
0988
0989 void Clear(const occ::handle<NCollection_BaseAllocator>& theAllocator)
0990 {
0991 Clear(theAllocator != this->myAllocator);
0992 this->myAllocator =
0993 (!theAllocator.IsNull() ? theAllocator : NCollection_BaseAllocator::CommonBaseAllocator());
0994 }
0995
0996
0997 ~NCollection_IndexedDataMap() override { Clear(true); }
0998
0999 protected:
1000
1001
1002
1003
1004
1005 bool lookup(const TheKeyType& theKey, IndexedDataMapNode*& theNode, size_t& theHash) const
1006 {
1007 theHash = HashCode(theKey, NbBuckets());
1008 if (IsEmpty())
1009 return false;
1010 for (theNode = (IndexedDataMapNode*)myData1[theHash]; theNode;
1011 theNode = (IndexedDataMapNode*)theNode->Next())
1012 {
1013 if (IsEqual(theNode->Key1(), theKey))
1014 return true;
1015 }
1016 return false;
1017 }
1018
1019
1020
1021
1022
1023 bool lookup(const TheKeyType& theKey, IndexedDataMapNode*& theNode) const
1024 {
1025 if (IsEmpty())
1026 return false;
1027 for (theNode = (IndexedDataMapNode*)myData1[HashCode(theKey, NbBuckets())]; theNode;
1028 theNode = (IndexedDataMapNode*)theNode->Next())
1029 {
1030 if (IsEqual(theNode->Key1(), theKey))
1031 {
1032 return true;
1033 }
1034 }
1035 return false;
1036 }
1037
1038 bool IsEqual(const TheKeyType& theKey1, const TheKeyType& theKey2) const
1039 {
1040 return myHasher(theKey1, theKey2);
1041 }
1042
1043 size_t HashCode(const TheKeyType& theKey, const size_t theUpperBound) const
1044 {
1045 return myHasher(theKey) % theUpperBound + 1;
1046 }
1047
1048
1049
1050
1051
1052
1053
1054 template <typename K, typename V>
1055 int addImpl(K&& theKey1, V&& theItem)
1056 {
1057 if (Resizable())
1058 {
1059 ReSize(Extent());
1060 }
1061 IndexedDataMapNode* aNode;
1062 size_t aHash;
1063 if (lookup(theKey1, aNode, aHash))
1064 {
1065 return aNode->Index();
1066 }
1067 const int aNewIndex = Extent() + 1;
1068 aNode = new (this->myAllocator) IndexedDataMapNode(std::forward<K>(theKey1),
1069 aNewIndex,
1070 std::forward<V>(theItem),
1071 myData1[aHash]);
1072 myData1[aHash] = aNode;
1073 myData2[aNewIndex - 1] = aNode;
1074 Increment();
1075 return aNewIndex;
1076 }
1077
1078
1079
1080
1081
1082
1083
1084
1085 template <typename K, bool IsTry, bool ReturnRef, typename... Args>
1086 auto emplaceImpl(K&& theKey1,
1087 std::bool_constant<IsTry>,
1088 std::bool_constant<ReturnRef>,
1089 Args&&... theArgs) -> std::conditional_t<ReturnRef, TheItemType&, int>
1090 {
1091 if (Resizable())
1092 ReSize(Extent());
1093 IndexedDataMapNode* aNode;
1094 size_t aHash;
1095 if (lookup(theKey1, aNode, aHash))
1096 {
1097 if constexpr (!IsTry)
1098 aNode->ChangeValue() = TheItemType(std::forward<Args>(theArgs)...);
1099 if constexpr (ReturnRef)
1100 return aNode->ChangeValue();
1101 else
1102 return aNode->Index();
1103 }
1104 const int aNewIndex = Extent() + 1;
1105 aNode = new (this->myAllocator) IndexedDataMapNode(std::forward<K>(theKey1),
1106 aNewIndex,
1107 std::in_place,
1108 myData1[aHash],
1109 std::forward<Args>(theArgs)...);
1110 myData1[aHash] = aNode;
1111 myData2[aNewIndex - 1] = aNode;
1112 Increment();
1113 if constexpr (ReturnRef)
1114 return aNode->ChangeValue();
1115 else
1116 return aNewIndex;
1117 }
1118
1119
1120
1121
1122
1123
1124
1125 template <typename K, typename V, bool IsTry, bool ReturnRef>
1126 auto bindImpl(K&& theKey1, V&& theItem, std::bool_constant<IsTry>, std::bool_constant<ReturnRef>)
1127 -> std::conditional_t<ReturnRef, TheItemType&, bool>
1128 {
1129 if (Resizable())
1130 ReSize(Extent());
1131 IndexedDataMapNode* aNode;
1132 size_t aHash;
1133 if (lookup(theKey1, aNode, aHash))
1134 {
1135 if constexpr (!IsTry)
1136 aNode->ChangeValue() = std::forward<V>(theItem);
1137 if constexpr (ReturnRef)
1138 return aNode->ChangeValue();
1139 else
1140 return false;
1141 }
1142 const int aNewIndex = Extent() + 1;
1143 aNode = new (this->myAllocator) IndexedDataMapNode(std::forward<K>(theKey1),
1144 aNewIndex,
1145 std::forward<V>(theItem),
1146 myData1[aHash]);
1147 myData1[aHash] = aNode;
1148 myData2[aNewIndex - 1] = aNode;
1149 Increment();
1150 if constexpr (ReturnRef)
1151 return aNode->ChangeValue();
1152 else
1153 return true;
1154 }
1155
1156 protected:
1157 Hasher myHasher;
1158 };
1159
1160 #endif