File indexing completed on 2026-09-09 09:16:09
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef NCollection_DoubleMap_HeaderFile
0017 #define NCollection_DoubleMap_HeaderFile
0018
0019 #include <NCollection_BaseMap.hxx>
0020 #include <NCollection_TListNode.hxx>
0021 #include <Standard_MultiplyDefined.hxx>
0022 #include <Standard_NoSuchObject.hxx>
0023
0024 #include <NCollection_DefaultHasher.hxx>
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 template <class TheKey1Type,
0035 class TheKey2Type,
0036 class Hasher1 = NCollection_DefaultHasher<TheKey1Type>,
0037 class Hasher2 = NCollection_DefaultHasher<TheKey2Type>>
0038 class NCollection_DoubleMap : public NCollection_BaseMap
0039 {
0040 public:
0041
0042 typedef TheKey1Type key1_type;
0043
0044 typedef TheKey2Type key2_type;
0045
0046 public:
0047
0048 class DoubleMapNode : public NCollection_TListNode<TheKey2Type>
0049 {
0050 public:
0051
0052 DoubleMapNode(const TheKey1Type& theKey1,
0053 const TheKey2Type& theKey2,
0054 NCollection_ListNode* theNext1,
0055 NCollection_ListNode* theNext2)
0056 : NCollection_TListNode<TheKey2Type>(theKey2, theNext1),
0057 myKey1(theKey1),
0058 myNext2((DoubleMapNode*)theNext2)
0059 {
0060 }
0061
0062
0063 const TheKey1Type& Key1(void) { return myKey1; }
0064
0065
0066 const TheKey2Type& Key2(void) { return this->myValue; }
0067
0068
0069 DoubleMapNode*& Next2(void) { return myNext2; }
0070
0071
0072 static void delNode(NCollection_ListNode* theNode, Handle(NCollection_BaseAllocator)& theAl)
0073 {
0074 ((DoubleMapNode*)theNode)->~DoubleMapNode();
0075 theAl->Free(theNode);
0076 }
0077
0078 private:
0079 TheKey1Type myKey1;
0080 DoubleMapNode* myNext2;
0081 };
0082
0083 public:
0084
0085 class Iterator : public NCollection_BaseMap::Iterator
0086 {
0087 public:
0088
0089 Iterator(void) {}
0090
0091
0092 Iterator(const NCollection_DoubleMap& theMap)
0093 : NCollection_BaseMap::Iterator(theMap)
0094 {
0095 }
0096
0097
0098 Standard_Boolean More(void) const { return PMore(); }
0099
0100
0101 void Next(void) { PNext(); }
0102
0103
0104 const TheKey1Type& Key1(void) const
0105 {
0106 Standard_NoSuchObject_Raise_if(!More(), "NCollection_DoubleMap::Iterator::Key1");
0107 return ((DoubleMapNode*)myNode)->Key1();
0108 }
0109
0110
0111 const TheKey2Type& Key2(void) const
0112 {
0113 Standard_NoSuchObject_Raise_if(!More(), "NCollection_DoubleMap::Iterator::Key2");
0114 return ((DoubleMapNode*)myNode)->Key2();
0115 }
0116
0117
0118 const TheKey2Type& Value(void) const
0119 {
0120 Standard_NoSuchObject_Raise_if(!More(), "NCollection_DoubleMap::Iterator::Value");
0121 return ((DoubleMapNode*)myNode)->Value();
0122 }
0123 };
0124
0125 public:
0126
0127
0128
0129 NCollection_DoubleMap()
0130 : NCollection_BaseMap(1, Standard_False, Handle(NCollection_BaseAllocator)())
0131 {
0132 }
0133
0134
0135 explicit NCollection_DoubleMap(const Standard_Integer theNbBuckets,
0136 const Handle(NCollection_BaseAllocator)& theAllocator = 0L)
0137 : NCollection_BaseMap(theNbBuckets, Standard_False, theAllocator)
0138 {
0139 }
0140
0141
0142 NCollection_DoubleMap(const NCollection_DoubleMap& theOther)
0143 : NCollection_BaseMap(theOther.NbBuckets(), Standard_False, theOther.myAllocator)
0144 {
0145 *this = theOther;
0146 }
0147
0148
0149
0150 void Exchange(NCollection_DoubleMap& theOther) { this->exchangeMapsData(theOther); }
0151
0152
0153
0154 NCollection_DoubleMap& Assign(const NCollection_DoubleMap& theOther)
0155 {
0156 if (this == &theOther)
0157 return *this;
0158
0159 Clear();
0160 Standard_Integer anExt = theOther.Extent();
0161 if (anExt)
0162 {
0163 ReSize(anExt - 1);
0164 Iterator anIter(theOther);
0165 for (; anIter.More(); anIter.Next())
0166 {
0167 TheKey1Type aKey1 = anIter.Key1();
0168 TheKey2Type aKey2 = anIter.Key2();
0169 const size_t iK1 = HashCode1(aKey1, NbBuckets());
0170 const size_t iK2 = HashCode2(aKey2, NbBuckets());
0171 DoubleMapNode* pNode =
0172 new (this->myAllocator) DoubleMapNode(aKey1, aKey2, myData1[iK1], myData2[iK2]);
0173 myData1[iK1] = pNode;
0174 myData2[iK2] = pNode;
0175 Increment();
0176 }
0177 }
0178 return *this;
0179 }
0180
0181
0182 NCollection_DoubleMap& operator=(const NCollection_DoubleMap& theOther)
0183 {
0184 return Assign(theOther);
0185 }
0186
0187
0188 void ReSize(const Standard_Integer N)
0189 {
0190 NCollection_ListNode** ppNewData1 = NULL;
0191 NCollection_ListNode** ppNewData2 = NULL;
0192 Standard_Integer newBuck;
0193 if (BeginResize(N, newBuck, ppNewData1, ppNewData2))
0194 {
0195 if (myData1)
0196 {
0197 DoubleMapNode *p, *q;
0198 for (int i = 0; i <= NbBuckets(); i++)
0199 {
0200 if (myData1[i])
0201 {
0202 p = (DoubleMapNode*)myData1[i];
0203 while (p)
0204 {
0205 const size_t iK1 = HashCode1(p->Key1(), newBuck);
0206 const size_t iK2 = HashCode2(p->Key2(), newBuck);
0207 q = (DoubleMapNode*)p->Next();
0208 p->Next() = ppNewData1[iK1];
0209 p->Next2() = (DoubleMapNode*)ppNewData2[iK2];
0210 ppNewData1[iK1] = p;
0211 ppNewData2[iK2] = p;
0212 p = q;
0213 }
0214 }
0215 }
0216 }
0217 EndResize(N, newBuck, ppNewData1, ppNewData2);
0218 }
0219 }
0220
0221
0222 void Bind(const TheKey1Type& theKey1, const TheKey2Type& theKey2)
0223 {
0224 if (Resizable())
0225 ReSize(Extent());
0226 const size_t iK1 = HashCode1(theKey1, NbBuckets());
0227 const size_t iK2 = HashCode2(theKey2, NbBuckets());
0228 DoubleMapNode* pNode;
0229 pNode = (DoubleMapNode*)myData1[iK1];
0230 while (pNode)
0231 {
0232 if (IsEqual1(pNode->Key1(), theKey1))
0233 throw Standard_MultiplyDefined("NCollection_DoubleMap:Bind");
0234 pNode = (DoubleMapNode*)pNode->Next();
0235 }
0236 pNode = (DoubleMapNode*)myData2[iK2];
0237 while (pNode)
0238 {
0239 if (IsEqual2(pNode->Key2(), theKey2))
0240 throw Standard_MultiplyDefined("NCollection_DoubleMap:Bind");
0241 pNode = (DoubleMapNode*)pNode->Next();
0242 }
0243 pNode = new (this->myAllocator) DoubleMapNode(theKey1, theKey2, myData1[iK1], myData2[iK2]);
0244 myData1[iK1] = pNode;
0245 myData2[iK2] = pNode;
0246 Increment();
0247 }
0248
0249
0250 Standard_Boolean AreBound(const TheKey1Type& theKey1, const TheKey2Type& theKey2) const
0251 {
0252 if (IsEmpty())
0253 return Standard_False;
0254 const size_t iK1 = HashCode1(theKey1, NbBuckets());
0255 const size_t iK2 = HashCode2(theKey2, NbBuckets());
0256 DoubleMapNode *pNode1, *pNode2;
0257 pNode1 = (DoubleMapNode*)myData1[iK1];
0258 while (pNode1)
0259 {
0260 if (IsEqual1(pNode1->Key1(), theKey1))
0261 break;
0262 pNode1 = (DoubleMapNode*)pNode1->Next();
0263 }
0264 if (pNode1 == NULL)
0265 return Standard_False;
0266 pNode2 = (DoubleMapNode*)myData2[iK2];
0267 while (pNode2)
0268 {
0269 if (IsEqual2(pNode2->Key2(), theKey2))
0270 break;
0271 pNode2 = (DoubleMapNode*)pNode2->Next();
0272 }
0273 if (pNode2 == NULL)
0274 return Standard_False;
0275
0276 return (pNode1 == pNode2);
0277 }
0278
0279
0280 Standard_Boolean IsBound1(const TheKey1Type& theKey1) const
0281 {
0282 if (IsEmpty())
0283 return Standard_False;
0284 const size_t iK1 = HashCode1(theKey1, NbBuckets());
0285 DoubleMapNode* pNode1;
0286 pNode1 = (DoubleMapNode*)myData1[iK1];
0287 while (pNode1)
0288 {
0289 if (IsEqual1(pNode1->Key1(), theKey1))
0290 return Standard_True;
0291 pNode1 = (DoubleMapNode*)pNode1->Next();
0292 }
0293 return Standard_False;
0294 }
0295
0296
0297 Standard_Boolean IsBound2(const TheKey2Type& theKey2) const
0298 {
0299 if (IsEmpty())
0300 return Standard_False;
0301 const size_t iK2 = HashCode2(theKey2, NbBuckets());
0302 DoubleMapNode* pNode2;
0303 pNode2 = (DoubleMapNode*)myData2[iK2];
0304 while (pNode2)
0305 {
0306 if (IsEqual2(pNode2->Key2(), theKey2))
0307 return Standard_True;
0308 pNode2 = (DoubleMapNode*)pNode2->Next2();
0309 }
0310 return Standard_False;
0311 }
0312
0313
0314 Standard_Boolean UnBind1(const TheKey1Type& theKey1)
0315 {
0316 if (IsEmpty())
0317 return Standard_False;
0318 const size_t iK1 = HashCode1(theKey1, NbBuckets());
0319 DoubleMapNode *p1, *p2, *q1, *q2;
0320 q1 = q2 = NULL;
0321 p1 = (DoubleMapNode*)myData1[iK1];
0322 while (p1)
0323 {
0324 if (IsEqual1(p1->Key1(), theKey1))
0325 {
0326
0327 if (q1)
0328 q1->Next() = p1->Next();
0329 else
0330 myData1[iK1] = (DoubleMapNode*)p1->Next();
0331 const size_t iK2 = HashCode2(p1->Key2(), NbBuckets());
0332 p2 = (DoubleMapNode*)myData2[iK2];
0333 while (p2)
0334 {
0335 if (p2 == p1)
0336 {
0337
0338 if (q2)
0339 q2->Next2() = p2->Next2();
0340 else
0341 myData2[iK2] = (DoubleMapNode*)p2->Next2();
0342 break;
0343 }
0344 q2 = p2;
0345 p2 = (DoubleMapNode*)p2->Next2();
0346 }
0347 p1->~DoubleMapNode();
0348 this->myAllocator->Free(p1);
0349 Decrement();
0350 return Standard_True;
0351 }
0352 q1 = p1;
0353 p1 = (DoubleMapNode*)p1->Next();
0354 }
0355 return Standard_False;
0356 }
0357
0358
0359 Standard_Boolean UnBind2(const TheKey2Type& theKey2)
0360 {
0361 if (IsEmpty())
0362 return Standard_False;
0363 const size_t iK2 = HashCode2(theKey2, NbBuckets());
0364 DoubleMapNode *p1, *p2, *q1, *q2;
0365 q1 = q2 = NULL;
0366 p2 = (DoubleMapNode*)myData2[iK2];
0367 while (p2)
0368 {
0369 if (IsEqual2(p2->Key2(), theKey2))
0370 {
0371
0372 if (q2)
0373 {
0374 q2->Next2() = p2->Next2();
0375 }
0376 else
0377 myData2[iK2] = (DoubleMapNode*)p2->Next2();
0378 const size_t iK1 = HashCode1(p2->Key1(), NbBuckets());
0379 p1 = (DoubleMapNode*)myData1[iK1];
0380 while (p1)
0381 {
0382 if (p1 == p2)
0383 {
0384
0385 if (q1)
0386 q1->Next() = p1->Next();
0387 else
0388 myData1[iK1] = (DoubleMapNode*)p1->Next();
0389 break;
0390 }
0391 q1 = p1;
0392 p1 = (DoubleMapNode*)p1->Next();
0393 }
0394 p2->~DoubleMapNode();
0395 this->myAllocator->Free(p2);
0396 Decrement();
0397 return Standard_True;
0398 }
0399 q2 = p2;
0400 p2 = (DoubleMapNode*)p2->Next2();
0401 }
0402 return Standard_False;
0403 }
0404
0405
0406
0407 const TheKey2Type& Find1(const TheKey1Type& theKey1) const
0408 {
0409 if (const TheKey2Type* aKey2 = Seek1(theKey1))
0410 {
0411 return *aKey2;
0412 }
0413 throw Standard_NoSuchObject("NCollection_DoubleMap::Find1");
0414 }
0415
0416
0417
0418
0419
0420 Standard_Boolean Find1(const TheKey1Type& theKey1, TheKey2Type& theKey2) const
0421 {
0422 if (const TheKey2Type* aKey2 = Seek1(theKey1))
0423 {
0424 theKey2 = *aKey2;
0425 return true;
0426 }
0427 return false;
0428 }
0429
0430
0431
0432
0433 const TheKey2Type* Seek1(const TheKey1Type& theKey1) const
0434 {
0435 for (DoubleMapNode* aNode1 =
0436 !IsEmpty() ? (DoubleMapNode*)myData1[HashCode1(theKey1, NbBuckets())] : NULL;
0437 aNode1 != NULL;
0438 aNode1 = (DoubleMapNode*)aNode1->Next())
0439 {
0440 if (IsEqual1(aNode1->Key1(), theKey1))
0441 {
0442 return &aNode1->Key2();
0443 }
0444 }
0445 return NULL;
0446 }
0447
0448
0449
0450 const TheKey1Type& Find2(const TheKey2Type& theKey2) const
0451 {
0452 if (const TheKey1Type* aVal1 = Seek2(theKey2))
0453 {
0454 return *aVal1;
0455 }
0456 throw Standard_NoSuchObject("NCollection_DoubleMap::Find2");
0457 }
0458
0459
0460
0461
0462
0463 Standard_Boolean Find2(const TheKey2Type& theKey2, TheKey1Type& theKey1) const
0464 {
0465 if (const TheKey1Type* aVal1 = Seek2(theKey2))
0466 {
0467 theKey1 = *aVal1;
0468 return Standard_True;
0469 }
0470 return Standard_False;
0471 }
0472
0473
0474
0475
0476 const TheKey1Type* Seek2(const TheKey2Type& theKey2) const
0477 {
0478 for (DoubleMapNode* aNode2 =
0479 !IsEmpty() ? (DoubleMapNode*)myData2[HashCode2(theKey2, NbBuckets())] : NULL;
0480 aNode2 != NULL;
0481 aNode2 = (DoubleMapNode*)aNode2->Next2())
0482 {
0483 if (IsEqual2(aNode2->Key2(), theKey2))
0484 {
0485 return &aNode2->Key1();
0486 }
0487 }
0488 return NULL;
0489 }
0490
0491
0492
0493 void Clear(const Standard_Boolean doReleaseMemory = Standard_False)
0494 {
0495 Destroy(DoubleMapNode::delNode, doReleaseMemory);
0496 }
0497
0498
0499 void Clear(const Handle(NCollection_BaseAllocator)& theAllocator)
0500 {
0501 Clear(true);
0502 this->myAllocator =
0503 (!theAllocator.IsNull() ? theAllocator : NCollection_BaseAllocator::CommonBaseAllocator());
0504 }
0505
0506
0507 ~NCollection_DoubleMap(void) { Clear(true); }
0508
0509
0510 Standard_Integer Size(void) const { return Extent(); }
0511
0512 protected:
0513 bool IsEqual1(const TheKey1Type& theKey1, const TheKey1Type& theKey2) const
0514 {
0515 return myHasher1(theKey1, theKey2);
0516 }
0517
0518 size_t HashCode1(const TheKey1Type& theKey, const int theUpperBound) const
0519 {
0520 return myHasher1(theKey) % theUpperBound + 1;
0521 }
0522
0523 bool IsEqual2(const TheKey2Type& theKey1, const TheKey2Type& theKey2) const
0524 {
0525 return myHasher2(theKey1, theKey2);
0526 }
0527
0528 size_t HashCode2(const TheKey2Type& theKey, const int theUpperBound) const
0529 {
0530 return myHasher2(theKey) % theUpperBound + 1;
0531 }
0532
0533 protected:
0534 Hasher1 myHasher1;
0535 Hasher2 myHasher2;
0536 };
0537
0538 #endif