File indexing completed on 2025-07-01 08:43:56
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
0024 #include <Standard_TypeMismatch.hxx>
0025 #include <Standard_NoSuchObject.hxx>
0026 #include <utility>
0027
0028 #include <Message.hxx>
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_DataMap : public NCollection_BaseMap
0052 {
0053 public:
0054
0055 typedef TheKeyType key_type;
0056
0057 typedef TheItemType value_type;
0058
0059 public:
0060
0061 class DataMapNode : public NCollection_TListNode<TheItemType>
0062 {
0063 public:
0064
0065 DataMapNode (const TheKeyType& theKey,
0066 const TheItemType& theItem,
0067 NCollection_ListNode* theNext) :
0068 NCollection_TListNode<TheItemType> (theItem, theNext),
0069 myKey(theKey)
0070 {}
0071
0072 DataMapNode (const TheKeyType& theKey,
0073 TheItemType&& theItem,
0074 NCollection_ListNode* theNext) :
0075 NCollection_TListNode<TheItemType> (std::forward<TheItemType>(theItem), theNext),
0076 myKey(theKey)
0077 {}
0078
0079 DataMapNode (TheKeyType&& theKey,
0080 const TheItemType& theItem,
0081 NCollection_ListNode* theNext) :
0082 NCollection_TListNode<TheItemType> (theItem, theNext),
0083 myKey(std::forward<TheKeyType>(theKey))
0084 {}
0085
0086 DataMapNode (TheKeyType&& theKey,
0087 TheItemType&& theItem,
0088 NCollection_ListNode* theNext) :
0089 NCollection_TListNode<TheItemType> (std::forward<TheItemType>(theItem), theNext),
0090 myKey(std::forward<TheKeyType>(theKey))
0091 {}
0092
0093
0094 const TheKeyType& Key (void) const
0095 { return myKey; }
0096
0097
0098 static void delNode (NCollection_ListNode * theNode,
0099 Handle(NCollection_BaseAllocator)& theAl)
0100 {
0101 ((DataMapNode *) theNode)->~DataMapNode();
0102 theAl->Free(theNode);
0103 }
0104
0105 private:
0106 TheKeyType myKey;
0107 };
0108
0109 public:
0110
0111 class Iterator : public NCollection_BaseMap::Iterator
0112 {
0113 public:
0114
0115 Iterator (void) :
0116 NCollection_BaseMap::Iterator() {}
0117
0118 Iterator (const NCollection_DataMap& theMap) :
0119 NCollection_BaseMap::Iterator(theMap) {}
0120
0121 Standard_Boolean More(void) const
0122 { return PMore(); }
0123
0124 void Next(void)
0125 { PNext(); }
0126
0127 const TheItemType& Value(void) const
0128 {
0129 Standard_NoSuchObject_Raise_if(!More(), "NCollection_DataMap::Iterator::Value");
0130 return ((DataMapNode *) myNode)->Value();
0131 }
0132
0133 TheItemType& ChangeValue(void) const
0134 {
0135 Standard_NoSuchObject_Raise_if(!More(), "NCollection_DataMap::Iterator::ChangeValue");
0136 return ((DataMapNode *) myNode)->ChangeValue();
0137 }
0138
0139 const TheKeyType& Key (void) const
0140 {
0141 Standard_NoSuchObject_Raise_if(!More(), "NCollection_DataMap::Iterator::Key");
0142 return ((DataMapNode *) myNode)->Key();
0143 }
0144 };
0145
0146
0147 typedef NCollection_StlIterator<std::forward_iterator_tag, Iterator, TheItemType, false> iterator;
0148
0149
0150 typedef NCollection_StlIterator<std::forward_iterator_tag, Iterator, TheItemType, true> const_iterator;
0151
0152
0153 iterator begin() const { return Iterator (*this); }
0154
0155
0156 iterator end() const { return Iterator(); }
0157
0158
0159 const_iterator cbegin() const { return Iterator (*this); }
0160
0161
0162 const_iterator cend() const { return Iterator(); }
0163
0164 public:
0165
0166
0167
0168 NCollection_DataMap() : NCollection_BaseMap (1, Standard_True, Handle(NCollection_BaseAllocator)()) {}
0169
0170
0171 explicit NCollection_DataMap (const Standard_Integer theNbBuckets,
0172 const Handle(NCollection_BaseAllocator)& theAllocator = 0L)
0173 : NCollection_BaseMap (theNbBuckets, Standard_True, theAllocator) {}
0174
0175
0176 NCollection_DataMap (const NCollection_DataMap& theOther)
0177 : NCollection_BaseMap (theOther.NbBuckets(), Standard_True, theOther.myAllocator)
0178 {
0179 const int anExt = theOther.Extent();
0180 if (anExt <= 0)
0181 return;
0182 ReSize(anExt - 1);
0183 for (Iterator anIter(theOther); anIter.More(); anIter.Next())
0184 Bind(anIter.Key(), anIter.Value());
0185 }
0186
0187
0188 NCollection_DataMap(NCollection_DataMap&& theOther) noexcept :
0189 NCollection_BaseMap(std::forward<NCollection_BaseMap>(theOther))
0190 {}
0191
0192
0193
0194 void Exchange (NCollection_DataMap& theOther)
0195 {
0196 this->exchangeMapsData (theOther);
0197 }
0198
0199
0200
0201 NCollection_DataMap& Assign (const NCollection_DataMap& theOther)
0202 {
0203 if (this == &theOther)
0204 return *this;
0205
0206 Clear();
0207 Standard_Integer anExt = theOther.Extent();
0208 if (anExt)
0209 {
0210 ReSize (anExt-1);
0211 Iterator anIter(theOther);
0212 for (; anIter.More(); anIter.Next())
0213 Bind (anIter.Key(), anIter.Value());
0214 }
0215 return *this;
0216 }
0217
0218
0219 NCollection_DataMap& operator= (const NCollection_DataMap& theOther)
0220 {
0221 return Assign (theOther);
0222 }
0223
0224
0225 NCollection_DataMap& operator= (NCollection_DataMap&& theOther) noexcept
0226 {
0227 if (this == &theOther)
0228 return *this;
0229 exchangeMapsData(theOther);
0230 return *this;
0231 }
0232
0233
0234 void ReSize (const Standard_Integer N)
0235 {
0236 NCollection_ListNode** newdata = NULL;
0237 NCollection_ListNode** dummy = NULL;
0238 Standard_Integer newBuck;
0239 if (BeginResize (N, newBuck, newdata, dummy))
0240 {
0241 if (myData1)
0242 {
0243 DataMapNode** olddata = (DataMapNode**) myData1;
0244 DataMapNode *p, *q;
0245 for (int i = 0; i <= NbBuckets(); i++)
0246 {
0247 if (olddata[i])
0248 {
0249 p = olddata[i];
0250 while (p)
0251 {
0252 const size_t k = HashCode(p->Key(),newBuck);
0253 q = (DataMapNode*) p->Next();
0254 p->Next() = newdata[k];
0255 newdata[k] = p;
0256 p = q;
0257 }
0258 }
0259 }
0260 }
0261 EndResize (N, newBuck, newdata, dummy);
0262 }
0263 }
0264
0265
0266
0267
0268
0269 Standard_Boolean Bind (const TheKeyType& theKey, const TheItemType& theItem)
0270 {
0271 if (Resizable())
0272 ReSize(Extent());
0273 size_t aHash;
0274 DataMapNode* aNode;
0275 if (lookup(theKey, aNode, aHash))
0276 {
0277 aNode->ChangeValue() = theItem;
0278 return Standard_False;
0279 }
0280 DataMapNode** data = (DataMapNode**)myData1;
0281 data[aHash] = new (this->myAllocator) DataMapNode (theKey, theItem, data[aHash]);
0282 Increment();
0283 return Standard_True;
0284 }
0285
0286
0287
0288
0289
0290 Standard_Boolean Bind (TheKeyType&& theKey, const TheItemType& theItem)
0291 {
0292 if (Resizable())
0293 ReSize(Extent());
0294 size_t aHash;
0295 DataMapNode* aNode;
0296 if (lookup(theKey, aNode, aHash))
0297 {
0298 aNode->ChangeValue() = theItem;
0299 return Standard_False;
0300 }
0301 DataMapNode** data = (DataMapNode**)myData1;
0302 data[aHash] = new (this->myAllocator) DataMapNode (std::forward<TheKeyType>(theKey), theItem, data[aHash]);
0303 Increment();
0304 return Standard_True;
0305 }
0306
0307
0308
0309
0310
0311 Standard_Boolean Bind (const TheKeyType& theKey, TheItemType&& theItem)
0312 {
0313 if (Resizable())
0314 ReSize(Extent());
0315 size_t aHash;
0316 DataMapNode* aNode;
0317 if (lookup(theKey, aNode, aHash))
0318 {
0319 aNode->ChangeValue() = std::forward<TheItemType>(theItem);
0320 return Standard_False;
0321 }
0322 DataMapNode** data = (DataMapNode**)myData1;
0323 data[aHash] = new (this->myAllocator) DataMapNode (theKey, std::forward<TheItemType>(theItem), data[aHash]);
0324 Increment();
0325 return Standard_True;
0326 }
0327
0328
0329
0330
0331
0332 Standard_Boolean Bind (TheKeyType&& theKey, TheItemType&& theItem)
0333 {
0334 if (Resizable())
0335 ReSize(Extent());
0336 size_t aHash;
0337 DataMapNode* aNode;
0338 if (lookup(theKey, aNode, aHash))
0339 {
0340 aNode->ChangeValue() = theItem;
0341 return Standard_False;
0342 }
0343 DataMapNode** data = (DataMapNode**)myData1;
0344 data[aHash] = new (this->myAllocator) DataMapNode (std::forward<TheKeyType>(theKey),
0345 std::forward<TheItemType>(theItem), data[aHash]);
0346 Increment();
0347 return Standard_True;
0348 }
0349
0350
0351
0352
0353
0354 TheItemType* Bound (const TheKeyType& theKey, const TheItemType& theItem)
0355 {
0356 if (Resizable())
0357 ReSize(Extent());
0358 size_t aHash;
0359 DataMapNode* aNode;
0360 if (lookup(theKey, aNode, aHash))
0361 {
0362 aNode->ChangeValue() = theItem;
0363 return &aNode->ChangeValue();
0364 }
0365 DataMapNode** data = (DataMapNode**)myData1;
0366 data[aHash] = new (this->myAllocator) DataMapNode (theKey, theItem, data[aHash]);
0367 Increment();
0368 return &data[aHash]->ChangeValue();
0369 }
0370
0371
0372
0373
0374
0375 TheItemType* Bound (TheKeyType&& theKey, const TheItemType& theItem)
0376 {
0377 if (Resizable())
0378 ReSize(Extent());
0379 size_t aHash;
0380 DataMapNode* aNode;
0381 if (lookup(theKey, aNode, aHash))
0382 {
0383 aNode->ChangeValue() = theItem;
0384 return &aNode->ChangeValue();
0385 }
0386 DataMapNode** data = (DataMapNode**)myData1;
0387 data[aHash] = new (this->myAllocator) DataMapNode (std::forward<TheKeyType>(theKey), theItem, data[aHash]);
0388 Increment();
0389 return &data[aHash]->ChangeValue();
0390 }
0391
0392
0393
0394
0395
0396 TheItemType* Bound (const TheKeyType& theKey, TheItemType&& theItem)
0397 {
0398 if (Resizable())
0399 ReSize(Extent());
0400 size_t aHash;
0401 DataMapNode* aNode;
0402 if (lookup(theKey, aNode, aHash))
0403 {
0404 aNode->ChangeValue() = std::forward<TheItemType>(theItem);
0405 return &aNode->ChangeValue();
0406 }
0407 DataMapNode** data = (DataMapNode**)myData1;
0408 data[aHash] = new (this->myAllocator) DataMapNode (theKey, std::forward<TheItemType>(theItem), data[aHash]);
0409 Increment();
0410 return &data[aHash]->ChangeValue();
0411 }
0412
0413
0414
0415
0416
0417 TheItemType* Bound (TheKeyType&& theKey, TheItemType&& theItem)
0418 {
0419 if (Resizable())
0420 ReSize(Extent());
0421 size_t aHash;
0422 DataMapNode* aNode;
0423 if (lookup(theKey, aNode, aHash))
0424 {
0425 aNode->ChangeValue() = std::forward<TheItemType>(theItem);
0426 return &aNode->ChangeValue();
0427 }
0428 DataMapNode** data = (DataMapNode**)myData1;
0429 data[aHash] = new (this->myAllocator) DataMapNode (std::forward<TheKeyType>(theKey),
0430 std::forward<TheItemType>(theItem), data[aHash]);
0431 Increment();
0432 return &data[aHash]->ChangeValue();
0433 }
0434
0435
0436 Standard_Boolean IsBound(const TheKeyType& theKey) const
0437 {
0438 DataMapNode* p;
0439 return lookup(theKey, p);
0440 }
0441
0442
0443 Standard_Boolean UnBind(const TheKeyType& theKey)
0444 {
0445 if (IsEmpty())
0446 return Standard_False;
0447 DataMapNode** data = (DataMapNode**) myData1;
0448 const size_t k = HashCode(theKey,NbBuckets());
0449 DataMapNode* p = data[k];
0450 DataMapNode* q = NULL;
0451 while (p)
0452 {
0453 if (IsEqual(p->Key(), theKey))
0454 {
0455 Decrement();
0456 if (q)
0457 q->Next() = p->Next();
0458 else
0459 data[k] = (DataMapNode*) p->Next();
0460 p->~DataMapNode();
0461 this->myAllocator->Free(p);
0462 return Standard_True;
0463 }
0464 q = p;
0465 p = (DataMapNode*) p->Next();
0466 }
0467 return Standard_False;
0468 }
0469
0470
0471
0472 const TheItemType* Seek(const TheKeyType& theKey) const
0473 {
0474 DataMapNode* p = 0;
0475 if (!lookup(theKey, p))
0476 return 0L;
0477 return &p->Value();
0478 }
0479
0480
0481 const TheItemType& Find(const TheKeyType& theKey) const
0482 {
0483 DataMapNode* p = 0;
0484 if (!lookup(theKey, p))
0485 throw Standard_NoSuchObject("NCollection_DataMap::Find");
0486 return p->Value();
0487 }
0488
0489
0490
0491 Standard_Boolean Find (const TheKeyType& theKey,
0492 TheItemType& theValue) const
0493 {
0494 DataMapNode* p = 0;
0495 if (!lookup(theKey, p))
0496 return Standard_False;
0497
0498 theValue = p->Value();
0499 return Standard_True;
0500 }
0501
0502
0503 const TheItemType& operator() (const TheKeyType& theKey) const
0504 { return Find(theKey); }
0505
0506
0507
0508 TheItemType* ChangeSeek(const TheKeyType& theKey)
0509 {
0510 DataMapNode* p = 0;
0511 if (!lookup(theKey, p))
0512 return 0L;
0513 return &p->ChangeValue();
0514 }
0515
0516
0517 TheItemType& ChangeFind (const TheKeyType& theKey)
0518 {
0519 DataMapNode* p = 0;
0520 if (!lookup(theKey, p))
0521 throw Standard_NoSuchObject("NCollection_DataMap::Find");
0522 return p->ChangeValue();
0523 }
0524
0525
0526 TheItemType& operator() (const TheKeyType& theKey)
0527 { return ChangeFind(theKey); }
0528
0529
0530
0531 void Clear(const Standard_Boolean doReleaseMemory = Standard_False)
0532 { Destroy (DataMapNode::delNode, doReleaseMemory); }
0533
0534
0535 void Clear (const Handle(NCollection_BaseAllocator)& theAllocator)
0536 {
0537 Clear(theAllocator != this->myAllocator);
0538 this->myAllocator = ( ! theAllocator.IsNull() ? theAllocator :
0539 NCollection_BaseAllocator::CommonBaseAllocator() );
0540 }
0541
0542
0543 virtual ~NCollection_DataMap (void)
0544 { Clear(true); }
0545
0546
0547 Standard_Integer Size(void) const
0548 { return Extent(); }
0549
0550
0551 protected:
0552
0553
0554
0555
0556
0557 Standard_Boolean lookup(const TheKeyType& theKey,DataMapNode*& theNode) const
0558 {
0559 if (IsEmpty())
0560 return Standard_False;
0561 for (theNode = (DataMapNode*)myData1[HashCode(theKey, NbBuckets())];
0562 theNode; theNode = (DataMapNode*)theNode->Next())
0563 {
0564 if (IsEqual(theNode->Key(), theKey))
0565 return Standard_True;
0566 }
0567 return Standard_False;
0568 }
0569
0570
0571
0572
0573
0574
0575 Standard_Boolean lookup(const TheKeyType& theKey, DataMapNode*& theNode, size_t& theHash) const
0576 {
0577 theHash = HashCode(theKey, NbBuckets());
0578 if (IsEmpty())
0579 return Standard_False;
0580 for (theNode = (DataMapNode*)myData1[theHash];
0581 theNode; theNode = (DataMapNode*)theNode->Next())
0582 {
0583 if (IsEqual(theNode->Key(), theKey))
0584 {
0585 return Standard_True;
0586 }
0587 }
0588 return Standard_False;
0589 }
0590
0591 bool IsEqual(const TheKeyType& theKey1,
0592 const TheKeyType& theKey2) const
0593 {
0594 return myHasher(theKey1, theKey2);
0595 }
0596
0597 size_t HashCode(const TheKeyType& theKey,
0598 const int theUpperBound) const
0599 {
0600 return myHasher(theKey) % theUpperBound + 1;
0601 }
0602
0603 private:
0604
0605 Hasher myHasher;
0606 };
0607
0608 #endif
0609