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