1 // Created on: 2002-04-24
2 // Created by: Alexander KARTOMIN (akm)
3 // Copyright (c) 2002-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #ifndef NCollection_DoubleMap_HeaderFile
17 #define NCollection_DoubleMap_HeaderFile
19 #include <NCollection_TypeDef.hxx>
20 #include <NCollection_BaseMap.hxx>
21 #include <NCollection_TListNode.hxx>
22 #include <Standard_TypeMismatch.hxx>
23 #include <Standard_MultiplyDefined.hxx>
24 #include <Standard_ImmutableObject.hxx>
25 #include <Standard_NoSuchObject.hxx>
27 #include <NCollection_DefaultHasher.hxx>
30 * Purpose: The DoubleMap is used to bind pairs (Key1,Key2)
31 * and retrieve them in linear time.
33 * See Map from NCollection for a discussion about the number
37 template < class TheKey1Type,
39 class Hasher1 = NCollection_DefaultHasher<TheKey1Type>,
40 class Hasher2 = NCollection_DefaultHasher<TheKey2Type> >
41 class NCollection_DoubleMap : public NCollection_BaseMap
44 //! STL-compliant typedef for key1 type
45 typedef TheKey1Type key1_type;
46 //! STL-compliant typedef for key2 type
47 typedef TheKey2Type key2_type;
50 // **************** Adaptation of the TListNode to the DOUBLEmap
51 class DoubleMapNode : public NCollection_TListNode<TheKey2Type>
54 //! Constructor with 'Next'
55 DoubleMapNode (const TheKey1Type& theKey1,
56 const TheKey2Type& theKey2,
57 NCollection_ListNode* theNext1,
58 NCollection_ListNode* theNext2) :
59 NCollection_TListNode<TheKey2Type> (theKey2, theNext1),
61 myNext2((DoubleMapNode*)theNext2)
65 const TheKey1Type& Key1 (void)
68 const TheKey2Type& Key2 (void)
69 { return this->myValue; }
71 DoubleMapNode*& Next2 (void)
74 //! Static deleter to be passed to BaseList
75 static void delNode (NCollection_ListNode * theNode,
76 Handle(NCollection_BaseAllocator)& theAl)
78 ((DoubleMapNode *) theNode)->~DoubleMapNode();
84 DoubleMapNode *myNext2;
88 // **************** Implementation of the Iterator interface.
89 class Iterator : public NCollection_BaseMap::Iterator
95 Iterator (const NCollection_DoubleMap& theMap) :
96 NCollection_BaseMap::Iterator(theMap) {}
97 //! Query if the end of collection is reached by iterator
98 Standard_Boolean More(void) const
100 //! Make a step along the collection
104 const TheKey1Type& Key1(void) const
106 Standard_NoSuchObject_Raise_if (!More(), "NCollection_DoubleMap::Iterator::Key1");
107 return ((DoubleMapNode *) myNode)->Key1();
110 const TheKey2Type& Key2(void) const
112 Standard_NoSuchObject_Raise_if (!More(), "NCollection_DoubleMap::Iterator::Key2");
113 return ((DoubleMapNode *) myNode)->Key2();
116 const TheKey2Type& Value(void) const
118 Standard_NoSuchObject_Raise_if (!More(), "NCollection_DoubleMap::Iterator::Value");
119 return ((DoubleMapNode *) myNode)->Value();
124 // ---------- PUBLIC METHODS ------------
126 //! Empty constructor.
127 NCollection_DoubleMap() : NCollection_BaseMap (1, Standard_False, Handle(NCollection_BaseAllocator)()) {}
130 explicit NCollection_DoubleMap (const Standard_Integer theNbBuckets,
131 const Handle(NCollection_BaseAllocator)& theAllocator = 0L)
132 : NCollection_BaseMap (theNbBuckets, Standard_False, theAllocator) {}
135 NCollection_DoubleMap (const NCollection_DoubleMap& theOther)
136 : NCollection_BaseMap (theOther.NbBuckets(), Standard_False, theOther.myAllocator)
137 { *this = theOther; }
139 //! Exchange the content of two maps without re-allocations.
140 //! Notice that allocators will be swapped as well!
141 void Exchange (NCollection_DoubleMap& theOther)
143 this->exchangeMapsData (theOther);
147 //! This method does not change the internal allocator.
148 NCollection_DoubleMap& Assign (const NCollection_DoubleMap& theOther)
150 if (this == &theOther)
154 ReSize (theOther.Extent()-1);
155 Iterator anIter(theOther);
156 for (; anIter.More(); anIter.Next())
158 TheKey1Type aKey1 = anIter.Key1();
159 TheKey2Type aKey2 = anIter.Key2();
160 Standard_Integer iK1 = Hasher1::HashCode (aKey1, NbBuckets());
161 Standard_Integer iK2 = Hasher2::HashCode (aKey2, NbBuckets());
162 DoubleMapNode * pNode = new (this->myAllocator) DoubleMapNode (aKey1, aKey2,
165 myData1[iK1] = pNode;
166 myData2[iK2] = pNode;
172 //! Assignment operator
173 NCollection_DoubleMap& operator= (const NCollection_DoubleMap& theOther)
175 return Assign (theOther);
179 void ReSize (const Standard_Integer N)
181 NCollection_ListNode** ppNewData1 = NULL;
182 NCollection_ListNode** ppNewData2 = NULL;
183 Standard_Integer newBuck;
184 if (BeginResize (N, newBuck, ppNewData1, ppNewData2))
188 DoubleMapNode *p, *q;
189 Standard_Integer i, iK1, iK2;
190 for (i = 0; i <= NbBuckets(); i++)
194 p = (DoubleMapNode *) myData1[i];
197 iK1 = Hasher1::HashCode (p->Key1(), newBuck);
198 iK2 = Hasher2::HashCode (p->Key2(), newBuck);
199 q = (DoubleMapNode*) p->Next();
200 p->Next() = ppNewData1[iK1];
201 p->Next2() = (DoubleMapNode*)ppNewData2[iK2];
209 EndResize (N, newBuck, ppNewData1, ppNewData2);
214 void Bind (const TheKey1Type& theKey1, const TheKey2Type& theKey2)
218 Standard_Integer iK1 = Hasher1::HashCode (theKey1, NbBuckets());
219 Standard_Integer iK2 = Hasher2::HashCode (theKey2, NbBuckets());
220 DoubleMapNode * pNode;
221 pNode = (DoubleMapNode *) myData1[iK1];
224 if (Hasher1::IsEqual (pNode->Key1(), theKey1))
225 throw Standard_MultiplyDefined("NCollection_DoubleMap:Bind");
226 pNode = (DoubleMapNode *) pNode->Next();
228 pNode = (DoubleMapNode *) myData2[iK2];
231 if (Hasher2::IsEqual (pNode->Key2(), theKey2))
232 throw Standard_MultiplyDefined("NCollection_DoubleMap:Bind");
233 pNode = (DoubleMapNode *) pNode->Next();
235 pNode = new (this->myAllocator) DoubleMapNode (theKey1, theKey2,
236 myData1[iK1], myData2[iK2]);
237 myData1[iK1] = pNode;
238 myData2[iK2] = pNode;
243 Standard_Boolean AreBound (const TheKey1Type& theKey1,
244 const TheKey2Type& theKey2) const
247 return Standard_False;
248 Standard_Integer iK1 = Hasher1::HashCode (theKey1, NbBuckets());
249 Standard_Integer iK2 = Hasher2::HashCode (theKey2, NbBuckets());
250 DoubleMapNode * pNode1, * pNode2;
251 pNode1 = (DoubleMapNode *) myData1[iK1];
254 if (Hasher1::IsEqual(pNode1->Key1(), theKey1))
256 pNode1 = (DoubleMapNode *) pNode1->Next();
259 return Standard_False;
260 pNode2 = (DoubleMapNode *) myData2[iK2];
263 if (Hasher2::IsEqual(pNode2->Key2(), theKey2))
265 pNode2 = (DoubleMapNode *) pNode2->Next();
268 return Standard_False;
270 return (pNode1 == pNode2);
274 Standard_Boolean IsBound1 (const TheKey1Type& theKey1) const
277 return Standard_False;
278 Standard_Integer iK1 = Hasher1::HashCode (theKey1, NbBuckets());
279 DoubleMapNode * pNode1;
280 pNode1 = (DoubleMapNode *) myData1[iK1];
283 if (Hasher1::IsEqual(pNode1->Key1(), theKey1))
284 return Standard_True;
285 pNode1 = (DoubleMapNode *) pNode1->Next();
287 return Standard_False;
291 Standard_Boolean IsBound2 (const TheKey2Type& theKey2) const
294 return Standard_False;
295 Standard_Integer iK2 = Hasher2::HashCode (theKey2, NbBuckets());
296 DoubleMapNode * pNode2;
297 pNode2 = (DoubleMapNode *) myData2[iK2];
300 if (Hasher2::IsEqual(pNode2->Key2(), theKey2))
301 return Standard_True;
302 pNode2 = (DoubleMapNode *) pNode2->Next2();
304 return Standard_False;
308 Standard_Boolean UnBind1 (const TheKey1Type& theKey1)
311 return Standard_False;
312 Standard_Integer iK1 = Hasher1::HashCode (theKey1, NbBuckets());
313 DoubleMapNode * p1, * p2, * q1, *q2;
315 p1 = (DoubleMapNode *) myData1[iK1];
318 if (Hasher1::IsEqual (p1->Key1(), theKey1))
320 // remove from the data1
322 q1->Next() = p1->Next();
324 myData1[iK1] = (DoubleMapNode*) p1->Next();
325 Standard_Integer iK2 = Hasher2::HashCode (p1->Key2(), NbBuckets());
326 p2 = (DoubleMapNode *) myData2[iK2];
331 // remove from the data2
333 q2->Next2() = p2->Next2();
335 myData2[iK2] = (DoubleMapNode*) p2->Next2();
339 p2 = (DoubleMapNode*) p2->Next2();
341 p1->~DoubleMapNode();
342 this->myAllocator->Free(p1);
344 return Standard_True;
347 p1 = (DoubleMapNode*) p1->Next();
349 return Standard_False;
353 Standard_Boolean UnBind2 (const TheKey2Type& theKey2)
356 return Standard_False;
357 Standard_Integer iK2 = Hasher2::HashCode (theKey2, NbBuckets());
358 DoubleMapNode * p1, * p2, * q1, *q2;
360 p2 = (DoubleMapNode *) myData2[iK2];
363 if (Hasher2::IsEqual (p2->Key2(), theKey2))
365 // remove from the data2
367 q2->Next() = p2->Next();
369 myData2[iK2] = (DoubleMapNode*) p2->Next2();
370 Standard_Integer iK1 = Hasher1::HashCode (p2->Key1(), NbBuckets());
371 p1 = (DoubleMapNode *) myData1[iK1];
376 // remove from the data1
378 q1->Next() = p1->Next();
380 myData1[iK1] = (DoubleMapNode*) p1->Next();
384 p1 = (DoubleMapNode*) p1->Next();
386 p2->~DoubleMapNode();
387 this->myAllocator->Free(p2);
389 return Standard_True;
392 p2 = (DoubleMapNode*) p2->Next2();
394 return Standard_False;
398 const TheKey2Type& Find1(const TheKey1Type& theKey1) const
400 Standard_NoSuchObject_Raise_if (IsEmpty(), "NCollection_DoubleMap::Find1");
401 DoubleMapNode * pNode1 =
402 (DoubleMapNode *) myData1[Hasher1::HashCode(theKey1,NbBuckets())];
405 if (Hasher1::IsEqual (pNode1->Key1(), theKey1))
406 return pNode1->Key2();
407 pNode1 = (DoubleMapNode*) pNode1->Next();
409 throw Standard_NoSuchObject("NCollection_DoubleMap::Find1");
413 const TheKey1Type& Find2(const TheKey2Type& theKey2) const
415 Standard_NoSuchObject_Raise_if (IsEmpty(), "NCollection_DoubleMap::Find2");
416 DoubleMapNode * pNode2 =
417 (DoubleMapNode *) myData2[Hasher2::HashCode(theKey2,NbBuckets())];
420 if (Hasher2::IsEqual (pNode2->Key2(), theKey2))
421 return pNode2->Key1();
422 pNode2 = (DoubleMapNode*) pNode2->Next2();
424 throw Standard_NoSuchObject("NCollection_DoubleMap::Find2");
427 //! Clear data. If doReleaseMemory is false then the table of
428 //! buckets is not released and will be reused.
429 void Clear(const Standard_Boolean doReleaseMemory = Standard_True)
430 { Destroy (DoubleMapNode::delNode, doReleaseMemory); }
432 //! Clear data and reset allocator
433 void Clear (const Handle(NCollection_BaseAllocator)& theAllocator)
436 this->myAllocator = ( ! theAllocator.IsNull() ? theAllocator :
437 NCollection_BaseAllocator::CommonBaseAllocator() );
441 ~NCollection_DoubleMap (void)
445 Standard_Integer Size(void) const