File indexing completed on 2026-09-26 09:04:03
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef NCollection_DataMap_HeaderFile
0017 #define NCollection_DataMap_HeaderFile
0018
0019 #include <NCollection_BaseMap.hxx>
0020 #include <NCollection_TListNode.hxx>
0021 #include <NCollection_StlIterator.hxx>
0022 #include <NCollection_DefaultHasher.hxx>
0023 #include <NCollection_ItemsView.hxx>
0024
0025 #include <Standard_TypeMismatch.hxx>
0026 #include <Standard_NoSuchObject.hxx>
0027 #include <Standard_OutOfRange.hxx>
0028 #include <functional>
0029 #include <optional>
0030 #include <type_traits>
0031 #include <utility>
0032
0033 #include <Message.hxx>
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053 template <class TheKeyType, class TheItemType, class Hasher = NCollection_DefaultHasher<TheKeyType>>
0054 class NCollection_DataMap : public NCollection_BaseMap
0055 {
0056 public:
0057
0058 typedef TheKeyType key_type;
0059
0060 typedef TheItemType value_type;
0061
0062 public:
0063
0064 class DataMapNode : public NCollection_TListNode<TheItemType>
0065 {
0066 public:
0067
0068 DataMapNode(const TheKeyType& theKey, const TheItemType& theItem, NCollection_ListNode* theNext)
0069 : NCollection_TListNode<TheItemType>(theItem, theNext),
0070 myKey(theKey)
0071 {
0072 }
0073
0074
0075 DataMapNode(const TheKeyType& theKey, TheItemType&& theItem, NCollection_ListNode* theNext)
0076 : NCollection_TListNode<TheItemType>(std::forward<TheItemType>(theItem), theNext),
0077 myKey(theKey)
0078 {
0079 }
0080
0081
0082 DataMapNode(TheKeyType&& theKey, const TheItemType& theItem, NCollection_ListNode* theNext)
0083 : NCollection_TListNode<TheItemType>(theItem, theNext),
0084 myKey(std::forward<TheKeyType>(theKey))
0085 {
0086 }
0087
0088
0089 DataMapNode(TheKeyType&& theKey, TheItemType&& theItem, NCollection_ListNode* theNext)
0090 : NCollection_TListNode<TheItemType>(std::forward<TheItemType>(theItem), theNext),
0091 myKey(std::forward<TheKeyType>(theKey))
0092 {
0093 }
0094
0095
0096 template <typename K, typename... Args>
0097 DataMapNode(K&& theKey, std::in_place_t, NCollection_ListNode* theNext, Args&&... theArgs)
0098 : NCollection_TListNode<TheItemType>(std::in_place,
0099 theNext,
0100 std::forward<Args>(theArgs)...),
0101 myKey(std::forward<K>(theKey))
0102 {
0103 }
0104
0105
0106 const TheKeyType& Key() const noexcept { return myKey; }
0107
0108
0109 static void delNode(NCollection_ListNode* theNode,
0110 occ::handle<NCollection_BaseAllocator>& theAl) noexcept
0111 {
0112 ((DataMapNode*)theNode)->~DataMapNode();
0113 theAl->Free(theNode);
0114 }
0115
0116 private:
0117 TheKeyType myKey;
0118 };
0119
0120 public:
0121
0122 class Iterator : public NCollection_BaseMap::Iterator
0123 {
0124 public:
0125
0126 Iterator()
0127 : NCollection_BaseMap::Iterator()
0128 {
0129 }
0130
0131
0132 Iterator(const NCollection_DataMap& theMap)
0133 : NCollection_BaseMap::Iterator(theMap)
0134 {
0135 }
0136
0137
0138 bool More() const noexcept { return PMore(); }
0139
0140
0141 void Next() noexcept { PNext(); }
0142
0143
0144 const TheItemType& Value() const
0145 {
0146 Standard_NoSuchObject_Raise_if(!More(), "NCollection_DataMap::Iterator::Value");
0147 return ((DataMapNode*)myNode)->Value();
0148 }
0149
0150
0151 TheItemType& ChangeValue() const
0152 {
0153 Standard_NoSuchObject_Raise_if(!More(), "NCollection_DataMap::Iterator::ChangeValue");
0154 return ((DataMapNode*)myNode)->ChangeValue();
0155 }
0156
0157
0158 const TheKeyType& Key() const
0159 {
0160 Standard_NoSuchObject_Raise_if(!More(), "NCollection_DataMap::Iterator::Key");
0161 return ((DataMapNode*)myNode)->Key();
0162 }
0163 };
0164
0165
0166 typedef NCollection_StlIterator<std::forward_iterator_tag, Iterator, TheItemType, false> iterator;
0167
0168
0169 typedef NCollection_StlIterator<std::forward_iterator_tag, Iterator, TheItemType, true>
0170 const_iterator;
0171
0172
0173 iterator begin() const noexcept { return Iterator(*this); }
0174
0175
0176 iterator end() const noexcept { return Iterator(); }
0177
0178
0179 const_iterator cbegin() const noexcept { return Iterator(*this); }
0180
0181
0182 const_iterator cend() const noexcept { return Iterator(); }
0183
0184 public:
0185
0186
0187
0188
0189 using KeyValueRef = NCollection_ItemsView::KeyValueRef<TheKeyType, TheItemType, false>;
0190
0191
0192 using ConstKeyValueRef = NCollection_ItemsView::KeyValueRef<TheKeyType, TheItemType, true>;
0193
0194 private:
0195
0196 struct ItemsExtractor
0197 {
0198 static KeyValueRef Extract(const Iterator& theIter)
0199 {
0200 return {theIter.Key(), theIter.ChangeValue()};
0201 }
0202 };
0203
0204
0205 struct ConstItemsExtractor
0206 {
0207 static ConstKeyValueRef Extract(const Iterator& theIter)
0208 {
0209 return {theIter.Key(), theIter.Value()};
0210 }
0211 };
0212
0213 public:
0214
0215 using ItemsView =
0216 NCollection_ItemsView::View<NCollection_DataMap, KeyValueRef, ItemsExtractor, false>;
0217
0218
0219 using ConstItemsView =
0220 NCollection_ItemsView::View<NCollection_DataMap, ConstKeyValueRef, ConstItemsExtractor, true>;
0221
0222
0223
0224 ItemsView Items() { return ItemsView(*this); }
0225
0226
0227
0228 ConstItemsView Items() const { return ConstItemsView(*this); }
0229
0230 public:
0231
0232
0233
0234 NCollection_DataMap()
0235 : NCollection_BaseMap(1, true, occ::handle<NCollection_BaseAllocator>())
0236 {
0237 }
0238
0239
0240 explicit NCollection_DataMap(const size_t theNbBuckets,
0241 const occ::handle<NCollection_BaseAllocator>& theAllocator = nullptr)
0242 : NCollection_BaseMap(theNbBuckets, true, theAllocator)
0243 {
0244 }
0245
0246
0247 explicit NCollection_DataMap(const int theNbBuckets,
0248 const occ::handle<NCollection_BaseAllocator>& theAllocator = nullptr)
0249 : NCollection_DataMap(NCollection_BaseMap::NbBucketsFromInt(theNbBuckets), theAllocator)
0250 {
0251 }
0252
0253
0254
0255
0256
0257 explicit NCollection_DataMap(const Hasher& theHasher,
0258 const size_t theNbBuckets = 1,
0259 const occ::handle<NCollection_BaseAllocator>& theAllocator = nullptr)
0260 : NCollection_BaseMap(theNbBuckets, true, theAllocator),
0261 myHasher(theHasher)
0262 {
0263 }
0264
0265
0266 explicit NCollection_DataMap(const Hasher& theHasher,
0267 const int theNbBuckets,
0268 const occ::handle<NCollection_BaseAllocator>& theAllocator = nullptr)
0269 : NCollection_DataMap(theHasher,
0270 NCollection_BaseMap::NbBucketsFromInt(theNbBuckets),
0271 theAllocator)
0272 {
0273 }
0274
0275
0276
0277
0278
0279 explicit NCollection_DataMap(Hasher&& theHasher,
0280 const size_t theNbBuckets = 1,
0281 const occ::handle<NCollection_BaseAllocator>& theAllocator = nullptr)
0282 : NCollection_BaseMap(theNbBuckets, true, theAllocator),
0283 myHasher(std::move(theHasher))
0284 {
0285 }
0286
0287
0288 explicit NCollection_DataMap(Hasher&& theHasher,
0289 const int theNbBuckets,
0290 const occ::handle<NCollection_BaseAllocator>& theAllocator = nullptr)
0291 : NCollection_DataMap(std::move(theHasher),
0292 NCollection_BaseMap::NbBucketsFromInt(theNbBuckets),
0293 theAllocator)
0294 {
0295 }
0296
0297
0298 NCollection_DataMap(const NCollection_DataMap& theOther)
0299 : NCollection_BaseMap(theOther.NbBuckets(), true, theOther.myAllocator),
0300 myHasher(theOther.myHasher)
0301 {
0302 const int anExt = theOther.Extent();
0303 if (anExt <= 0)
0304 return;
0305 ReSize(anExt - 1);
0306 for (Iterator anIter(theOther); anIter.More(); anIter.Next())
0307 Bind(anIter.Key(), anIter.Value());
0308 }
0309
0310
0311 NCollection_DataMap(NCollection_DataMap&& theOther) noexcept
0312 : NCollection_BaseMap(std::forward<NCollection_BaseMap>(theOther)),
0313 myHasher(std::move(theOther.myHasher))
0314 {
0315 }
0316
0317
0318
0319 void Exchange(NCollection_DataMap& theOther) noexcept
0320 {
0321 this->exchangeMapsData(theOther);
0322 std::swap(myHasher, theOther.myHasher);
0323 }
0324
0325
0326 const Hasher& GetHasher() const noexcept { return myHasher; }
0327
0328
0329
0330 NCollection_DataMap& Assign(const NCollection_DataMap& theOther)
0331 {
0332 if (this == &theOther)
0333 return *this;
0334
0335 Clear();
0336 int anExt = theOther.Extent();
0337 if (anExt)
0338 {
0339 ReSize(anExt - 1);
0340 Iterator anIter(theOther);
0341 for (; anIter.More(); anIter.Next())
0342 Bind(anIter.Key(), anIter.Value());
0343 }
0344 return *this;
0345 }
0346
0347
0348 NCollection_DataMap& operator=(const NCollection_DataMap& theOther) { return Assign(theOther); }
0349
0350
0351 NCollection_DataMap& operator=(NCollection_DataMap&& theOther) noexcept
0352 {
0353 if (this == &theOther)
0354 return *this;
0355 exchangeMapsData(theOther);
0356 return *this;
0357 }
0358
0359
0360 void ReSize(const size_t N)
0361 {
0362 NCollection_ListNode** newdata = nullptr;
0363 NCollection_ListNode** dummy = nullptr;
0364 size_t newBuck;
0365 if (BeginResize(N, newBuck, newdata, dummy))
0366 {
0367 if (myData1)
0368 {
0369 DataMapNode** olddata = (DataMapNode**)myData1;
0370 DataMapNode * p, *q;
0371 for (size_t i = 0; i <= NbBuckets(); ++i)
0372 {
0373 if (olddata[i])
0374 {
0375 p = olddata[i];
0376 while (p)
0377 {
0378 const size_t k = HashCode(p->Key(), newBuck);
0379 q = (DataMapNode*)p->Next();
0380 p->Next() = newdata[k];
0381 newdata[k] = p;
0382 p = q;
0383 }
0384 }
0385 }
0386 }
0387 EndResize(N, newBuck, newdata, dummy);
0388 }
0389 }
0390
0391 void ReSize(const int N)
0392 {
0393 Standard_OutOfRange_Raise_if(N < 0, "NCollection_DataMap::ReSize: negative size");
0394 ReSize(static_cast<size_t>(N));
0395 }
0396
0397
0398
0399
0400
0401
0402 bool Bind(const TheKeyType& theKey, const TheItemType& theItem)
0403 {
0404 return emplaceImpl(theKey, std::false_type{}, std::false_type{}, theItem);
0405 }
0406
0407
0408
0409
0410
0411
0412 bool Bind(TheKeyType&& theKey, const TheItemType& theItem)
0413 {
0414 return emplaceImpl(std::move(theKey), std::false_type{}, std::false_type{}, theItem);
0415 }
0416
0417
0418
0419
0420
0421
0422 bool Bind(const TheKeyType& theKey, TheItemType&& theItem)
0423 {
0424 return emplaceImpl(theKey, std::false_type{}, std::false_type{}, std::move(theItem));
0425 }
0426
0427
0428
0429
0430
0431
0432 bool Bind(TheKeyType&& theKey, TheItemType&& theItem)
0433 {
0434 return emplaceImpl(std::move(theKey), std::false_type{}, std::false_type{}, std::move(theItem));
0435 }
0436
0437
0438
0439
0440
0441
0442 TheItemType* Bound(const TheKeyType& theKey, const TheItemType& theItem)
0443 {
0444 return &emplaceImpl(theKey, std::false_type{}, std::true_type{}, theItem);
0445 }
0446
0447
0448
0449
0450
0451
0452 TheItemType* Bound(TheKeyType&& theKey, const TheItemType& theItem)
0453 {
0454 return &emplaceImpl(std::move(theKey), std::false_type{}, std::true_type{}, theItem);
0455 }
0456
0457
0458
0459
0460
0461
0462 TheItemType* Bound(const TheKeyType& theKey, TheItemType&& theItem)
0463 {
0464 return &emplaceImpl(theKey, std::false_type{}, std::true_type{}, std::move(theItem));
0465 }
0466
0467
0468
0469
0470
0471
0472 TheItemType* Bound(TheKeyType&& theKey, TheItemType&& theItem)
0473 {
0474 return &emplaceImpl(std::move(theKey), std::false_type{}, std::true_type{}, std::move(theItem));
0475 }
0476
0477
0478
0479
0480
0481 bool TryBind(const TheKeyType& theKey, const TheItemType& theItem)
0482 {
0483 return emplaceImpl(theKey, std::true_type{}, std::false_type{}, theItem);
0484 }
0485
0486
0487
0488
0489
0490 bool TryBind(TheKeyType&& theKey, const TheItemType& theItem)
0491 {
0492 return emplaceImpl(std::move(theKey), std::true_type{}, std::false_type{}, theItem);
0493 }
0494
0495
0496
0497
0498
0499 bool TryBind(const TheKeyType& theKey, TheItemType&& theItem)
0500 {
0501 return emplaceImpl(theKey, std::true_type{}, std::false_type{}, std::move(theItem));
0502 }
0503
0504
0505
0506
0507
0508 bool TryBind(TheKeyType&& theKey, TheItemType&& theItem)
0509 {
0510 return emplaceImpl(std::move(theKey), std::true_type{}, std::false_type{}, std::move(theItem));
0511 }
0512
0513
0514
0515
0516
0517 TheItemType& TryBound(const TheKeyType& theKey, const TheItemType& theItem)
0518 {
0519 return emplaceImpl(theKey, std::true_type{}, std::true_type{}, theItem);
0520 }
0521
0522
0523
0524
0525
0526 TheItemType& TryBound(TheKeyType&& theKey, const TheItemType& theItem)
0527 {
0528 return emplaceImpl(std::move(theKey), std::true_type{}, std::true_type{}, theItem);
0529 }
0530
0531
0532
0533
0534
0535 TheItemType& TryBound(const TheKeyType& theKey, TheItemType&& theItem)
0536 {
0537 return emplaceImpl(theKey, std::true_type{}, std::true_type{}, std::move(theItem));
0538 }
0539
0540
0541
0542
0543
0544 TheItemType& TryBound(TheKeyType&& theKey, TheItemType&& theItem)
0545 {
0546 return emplaceImpl(std::move(theKey), std::true_type{}, std::true_type{}, std::move(theItem));
0547 }
0548
0549
0550
0551
0552
0553
0554 template <typename K, typename... Args>
0555 bool Emplace(K&& theKey, Args&&... theArgs)
0556 {
0557 return emplaceImpl(std::forward<K>(theKey),
0558 std::false_type{},
0559 std::false_type{},
0560 std::forward<Args>(theArgs)...);
0561 }
0562
0563
0564
0565
0566
0567 template <typename K, typename... Args>
0568 TheItemType& Emplaced(K&& theKey, Args&&... theArgs)
0569 {
0570 return emplaceImpl(std::forward<K>(theKey),
0571 std::false_type{},
0572 std::true_type{},
0573 std::forward<Args>(theArgs)...);
0574 }
0575
0576
0577
0578
0579
0580 template <typename K, typename... Args>
0581 bool TryEmplace(K&& theKey, Args&&... theArgs)
0582 {
0583 return emplaceImpl(std::forward<K>(theKey),
0584 std::true_type{},
0585 std::false_type{},
0586 std::forward<Args>(theArgs)...);
0587 }
0588
0589
0590
0591
0592
0593 template <typename K, typename... Args>
0594 TheItemType& TryEmplaced(K&& theKey, Args&&... theArgs)
0595 {
0596 return emplaceImpl(std::forward<K>(theKey),
0597 std::true_type{},
0598 std::true_type{},
0599 std::forward<Args>(theArgs)...);
0600 }
0601
0602
0603 bool IsBound(const TheKeyType& theKey) const
0604 {
0605 DataMapNode* p;
0606 return lookup(theKey, p);
0607 }
0608
0609
0610
0611 std::optional<
0612 std::pair<std::reference_wrapper<const TheKeyType>, std::reference_wrapper<const TheItemType>>>
0613 Contained(const TheKeyType& theKey) const
0614 {
0615 DataMapNode* p = nullptr;
0616 if (!lookup(theKey, p))
0617 return std::nullopt;
0618 return std::make_pair(std::cref(p->Key()), std::cref(p->Value()));
0619 }
0620
0621
0622
0623 std::optional<
0624 std::pair<std::reference_wrapper<const TheKeyType>, std::reference_wrapper<TheItemType>>>
0625 Contained(const TheKeyType& theKey)
0626 {
0627 DataMapNode* p = nullptr;
0628 if (!lookup(theKey, p))
0629 return std::nullopt;
0630 return std::make_pair(std::cref(p->Key()), std::ref(p->ChangeValue()));
0631 }
0632
0633
0634 bool UnBind(const TheKeyType& theKey)
0635 {
0636 if (IsEmpty())
0637 return false;
0638 DataMapNode** data = (DataMapNode**)myData1;
0639 const size_t k = HashCode(theKey, NbBuckets());
0640 DataMapNode* p = data[k];
0641 DataMapNode* q = nullptr;
0642 while (p)
0643 {
0644 if (IsEqual(p->Key(), theKey))
0645 {
0646 Decrement();
0647 if (q)
0648 q->Next() = p->Next();
0649 else
0650 data[k] = (DataMapNode*)p->Next();
0651 p->~DataMapNode();
0652 this->myAllocator->Free(p);
0653 return true;
0654 }
0655 q = p;
0656 p = (DataMapNode*)p->Next();
0657 }
0658 return false;
0659 }
0660
0661
0662
0663 const TheItemType* Seek(const TheKeyType& theKey) const
0664 {
0665 DataMapNode* p = nullptr;
0666 if (!lookup(theKey, p))
0667 return nullptr;
0668 return &p->Value();
0669 }
0670
0671
0672 const TheItemType& Find(const TheKeyType& theKey) const
0673 {
0674 DataMapNode* p = nullptr;
0675 if (!lookup(theKey, p))
0676 throw Standard_NoSuchObject("NCollection_DataMap::Find");
0677 return p->Value();
0678 }
0679
0680
0681
0682 bool Find(const TheKeyType& theKey, TheItemType& theValue) const
0683 {
0684 DataMapNode* p = nullptr;
0685 if (!lookup(theKey, p))
0686 return false;
0687
0688 theValue = p->Value();
0689 return true;
0690 }
0691
0692
0693 const TheItemType& operator()(const TheKeyType& theKey) const { return Find(theKey); }
0694
0695
0696
0697 TheItemType* ChangeSeek(const TheKeyType& theKey)
0698 {
0699 DataMapNode* p = nullptr;
0700 if (!lookup(theKey, p))
0701 return nullptr;
0702 return &p->ChangeValue();
0703 }
0704
0705
0706 TheItemType& ChangeFind(const TheKeyType& theKey)
0707 {
0708 DataMapNode* p = nullptr;
0709 if (!lookup(theKey, p))
0710 throw Standard_NoSuchObject("NCollection_DataMap::Find");
0711 return p->ChangeValue();
0712 }
0713
0714
0715 TheItemType& operator()(const TheKeyType& theKey) { return ChangeFind(theKey); }
0716
0717
0718
0719 void Clear(const bool doReleaseMemory = false) { Destroy(DataMapNode::delNode, doReleaseMemory); }
0720
0721
0722 void Clear(const occ::handle<NCollection_BaseAllocator>& theAllocator)
0723 {
0724 Clear(theAllocator != this->myAllocator);
0725 this->myAllocator =
0726 (!theAllocator.IsNull() ? theAllocator : NCollection_BaseAllocator::CommonBaseAllocator());
0727 }
0728
0729
0730 ~NCollection_DataMap() override { Clear(true); }
0731
0732 protected:
0733
0734
0735
0736
0737 bool lookup(const TheKeyType& theKey, DataMapNode*& theNode) const
0738 {
0739 if (IsEmpty())
0740 return false;
0741 for (theNode = (DataMapNode*)myData1[HashCode(theKey, NbBuckets())]; theNode;
0742 theNode = (DataMapNode*)theNode->Next())
0743 {
0744 if (IsEqual(theNode->Key(), theKey))
0745 return true;
0746 }
0747 return false;
0748 }
0749
0750
0751
0752
0753
0754
0755 bool lookup(const TheKeyType& theKey, DataMapNode*& theNode, size_t& theHash) const
0756 {
0757 theHash = HashCode(theKey, NbBuckets());
0758 if (IsEmpty())
0759 return false;
0760 for (theNode = (DataMapNode*)myData1[theHash]; theNode; theNode = (DataMapNode*)theNode->Next())
0761 {
0762 if (IsEqual(theNode->Key(), theKey))
0763 {
0764 return true;
0765 }
0766 }
0767 return false;
0768 }
0769
0770 bool IsEqual(const TheKeyType& theKey1, const TheKeyType& theKey2) const
0771 {
0772 return myHasher(theKey1, theKey2);
0773 }
0774
0775 size_t HashCode(const TheKeyType& theKey, const size_t theUpperBound) const
0776 {
0777 return myHasher(theKey) % theUpperBound + 1;
0778 }
0779
0780
0781
0782
0783
0784
0785
0786
0787
0788 template <typename K, bool IsTry, bool ReturnRef, typename... Args>
0789 auto emplaceImpl(K&& theKey,
0790 std::bool_constant<IsTry>,
0791 std::bool_constant<ReturnRef>,
0792 Args&&... theArgs) -> std::conditional_t<ReturnRef, TheItemType&, bool>
0793 {
0794 if (Resizable())
0795 ReSize(Extent());
0796 size_t aHash;
0797 DataMapNode* aNode;
0798 if (lookup(theKey, aNode, aHash))
0799 {
0800 if constexpr (!IsTry)
0801 {
0802 aNode->ChangeValue() = TheItemType(std::forward<Args>(theArgs)...);
0803 }
0804 if constexpr (ReturnRef)
0805 return aNode->ChangeValue();
0806 else
0807 return false;
0808 }
0809 DataMapNode** data = (DataMapNode**)myData1;
0810 data[aHash] = new (this->myAllocator) DataMapNode(std::forward<K>(theKey),
0811 std::in_place,
0812 data[aHash],
0813 std::forward<Args>(theArgs)...);
0814 Increment();
0815 if constexpr (ReturnRef)
0816 return data[aHash]->ChangeValue();
0817 else
0818 return true;
0819 }
0820
0821 private:
0822 Hasher myHasher;
0823 };
0824
0825 #endif