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