1 // Created on: 1993-01-08
2 // Created by: Remi LEQUETTE
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 #include <Standard_DomainError.hxx>
18 #include <Standard_MultiplyDefined.hxx>
19 #include <Standard_NoSuchObject.hxx>
20 #include <Standard_OutOfRange.hxx>
21 #include <TCollection_BasicMapIterator.hxx>
23 //=======================================================================
24 //function : TCollection_IndexedDataMap
26 //=======================================================================
28 TCollection_IndexedDataMap::TCollection_IndexedDataMap
29 (const Standard_Integer NbBuckets):
30 TCollection_BasicMap(NbBuckets,Standard_False)
34 //=======================================================================
35 //function : TCollection_IndexedDataMap
37 //=======================================================================
39 TCollection_IndexedDataMap::TCollection_IndexedDataMap
40 (const TCollection_IndexedDataMap& Other) :
41 TCollection_BasicMap(Other.NbBuckets(),Standard_False)
43 if (Other.Extent() != 0)
44 throw Standard_DomainError("TCollection:Copy of non empty IndexedDataMap");
47 //=======================================================================
50 //=======================================================================
52 TCollection_IndexedDataMap& TCollection_IndexedDataMap::Assign
53 (const TCollection_IndexedDataMap& Other)
55 // very simple implementation
56 // not optimal (recompute the hashcode values)
58 if (this == &Other) return *this;
60 // ReSize(Other.NbBuckets());
61 if (!Other.IsEmpty()) {
62 ReSize(Other.Extent());
63 for (Standard_Integer i = 1; i <= Other.Extent(); i++) {
64 Add(Other.FindKey(i),Other(i));
72 //=======================================================================
75 //=======================================================================
77 void TCollection_IndexedDataMap::ReSize(const Standard_Integer N)
79 Standard_Integer newBuck;
80 Standard_Address newData1=NULL, newData2=NULL;
81 if (BeginResize(N,newBuck,newData1,newData2)) {
83 TCollection_IndexedDataMapNode** newdata1 = (TCollection_IndexedDataMapNode**)newData1;
84 TCollection_IndexedDataMapNode** newdata2 = (TCollection_IndexedDataMapNode**)newData2;
85 TCollection_IndexedDataMapNode** olddata1 = (TCollection_IndexedDataMapNode**) myData1;
86 TCollection_IndexedDataMapNode *p, *q;
87 Standard_Integer i,k1,k2;
88 for (i = 0; i <= NbBuckets(); i++) {
92 k1 = Hasher::HashCode(p->Key1(),newBuck);
93 k2 = ::HashCode(p->Key2(),newBuck);
94 q = (TCollection_IndexedDataMapNode*)p->Next();
95 p->Next() = newdata1[k1];
96 p->Next2() = newdata2[k2];
104 EndResize(N,newBuck,newData1,newData2);
108 //=======================================================================
111 //=======================================================================
113 void TCollection_IndexedDataMap::Clear()
117 TCollection_IndexedDataMapNode** data1 = (TCollection_IndexedDataMapNode**) myData1;
118 TCollection_IndexedDataMapNode** data2 = (TCollection_IndexedDataMapNode**) myData2;
119 TCollection_IndexedDataMapNode *p,*q;
120 for (i = 0; i <= NbBuckets(); i++) {
123 q = (TCollection_IndexedDataMapNode*) p->Next();
127 data1[i] = data2[i] = NULL;
130 TCollection_BasicMap::Destroy();
133 //=======================================================================
136 //=======================================================================
138 Standard_Integer TCollection_IndexedDataMap::Add(const TheKey& K1, const TheItem& I)
140 if (Resizable()) ReSize(Extent());
141 TCollection_IndexedDataMapNode** data1 = (TCollection_IndexedDataMapNode**)myData1;
142 Standard_Integer k1 = Hasher::HashCode(K1,NbBuckets());
143 TCollection_IndexedDataMapNode* p;
146 if (Hasher::IsEqual(p->Key1(),K1))
148 p = (TCollection_IndexedDataMapNode*) p->Next();
151 TCollection_IndexedDataMapNode** data2 = (TCollection_IndexedDataMapNode**)myData2;
152 Standard_Integer k2 = ::HashCode(Extent(),NbBuckets());
153 p = new TCollection_IndexedDataMapNode(K1,Extent(),I,data1[k1],data2[k2]);
160 //=======================================================================
161 //function : Substitute
163 //=======================================================================
165 void TCollection_IndexedDataMap::Substitute(const Standard_Integer I,
169 Standard_OutOfRange_Raise_if(I < 1 || I > Extent(), "IndexedDataMap::Substitute : "
170 "Index is out of range");
171 TCollection_IndexedDataMapNode** data1 = (TCollection_IndexedDataMapNode**)myData1;
172 TCollection_IndexedDataMapNode* p;
174 // check if K1 is not already in the map
175 Standard_Integer k1 = Hasher::HashCode(K1,NbBuckets());
178 if (Hasher::IsEqual(p->Key1(),K1)) {
180 throw Standard_DomainError("IndexedDataMap::Substitute : "
181 "Attempt to substitute existing key");
186 p = (TCollection_IndexedDataMapNode*) p->Next();
189 // Find the node for the index I
190 TCollection_IndexedDataMapNode** data2 = (TCollection_IndexedDataMapNode**)myData2;
191 Standard_Integer k2 = ::HashCode(I,NbBuckets());
196 p = (TCollection_IndexedDataMapNode*) p->Next2();
199 // remove the old key
200 Standard_Integer k = Hasher::HashCode(p->Key1(),NbBuckets());
201 TCollection_IndexedDataMapNode* q = data1[k];
202 if (q == p) data1[k] = (TCollection_IndexedDataMapNode*) p->Next();
204 while(q->Next() != p) q = (TCollection_IndexedDataMapNode*) q->Next();
205 q->Next() = p->Next();
211 p->Next() = data1[k1];
215 //=======================================================================
216 //function : RemoveLast
218 //=======================================================================
220 void TCollection_IndexedDataMap::RemoveLast()
222 Standard_OutOfRange_Raise_if(Extent() == 0,
223 "IndexedMap::RemoveLast");
224 TCollection_IndexedDataMapNode** data1 = (TCollection_IndexedDataMapNode**)myData1;
225 TCollection_IndexedDataMapNode* p;
226 TCollection_IndexedDataMapNode* q;
228 // Find the node for the last index and remove it
229 TCollection_IndexedDataMapNode** data2 = (TCollection_IndexedDataMapNode**)myData2;
230 Standard_Integer k2 = ::HashCode(Extent(),NbBuckets());
234 if (p->Key2() == Extent())
237 p = (TCollection_IndexedDataMapNode*) p->Next2();
240 data2[k2] = (TCollection_IndexedDataMapNode*)p->Next2();
242 q->Next2() = p->Next2();
245 Standard_Integer k = Hasher::HashCode(p->Key1(),NbBuckets());
247 if (q == p) data1[k] = (TCollection_IndexedDataMapNode*) p->Next();
249 while(q->Next() != p) q = (TCollection_IndexedDataMapNode*) q->Next();
250 q->Next() = p->Next();
258 //=======================================================================
261 //=======================================================================
263 const TheKey& TCollection_IndexedDataMap::FindKey(const Standard_Integer K2) const
265 Standard_OutOfRange_Raise_if(K2 < 1 || K2 > Extent(), "IndexedDataMap");
266 TCollection_IndexedDataMapNode** data2 = (TCollection_IndexedDataMapNode**)myData2;
267 Standard_Integer k2 = ::HashCode(K2,NbBuckets());
268 TCollection_IndexedDataMapNode *p2;
271 if (p2->Key2() == K2) return p2->Key1();
272 p2 = (TCollection_IndexedDataMapNode*)p2->Next2();
274 throw Standard_OutOfRange("IndexedDataMap : missing index !!!");
278 //=======================================================================
279 //function : FindFromIndex
281 //=======================================================================
283 const TheItem& TCollection_IndexedDataMap::FindFromIndex
284 (const Standard_Integer K2) const
286 Standard_OutOfRange_Raise_if(K2 < 1 || K2 > Extent(), "IndexedDataMap");
287 TCollection_IndexedDataMapNode** data2 = (TCollection_IndexedDataMapNode**)myData2;
288 Standard_Integer k2 = ::HashCode(K2,NbBuckets());
289 TCollection_IndexedDataMapNode *p2;
292 if (p2->Key2() == K2) return p2->Value();
293 p2 = (TCollection_IndexedDataMapNode*)p2->Next2();
295 throw Standard_OutOfRange("IndexedDataMap : missing index !!!");
299 //=======================================================================
300 //function : ChangeFromIndex
302 //=======================================================================
304 TheItem& TCollection_IndexedDataMap::ChangeFromIndex(const Standard_Integer K2)
306 Standard_OutOfRange_Raise_if(K2 < 1 || K2 > Extent(), "IndexedDataMap");
307 TCollection_IndexedDataMapNode** data2 = (TCollection_IndexedDataMapNode**)myData2;
308 Standard_Integer k2 = ::HashCode(K2,NbBuckets());
309 TCollection_IndexedDataMapNode *p2;
312 if (p2->Key2() == K2) return p2->Value();
313 p2 = (TCollection_IndexedDataMapNode*)p2->Next2();
315 throw Standard_OutOfRange("IndexedDataMap : missing index !!!");
319 //=======================================================================
320 //function : FindIndex
322 //=======================================================================
324 Standard_Integer TCollection_IndexedDataMap::FindIndex(const TheKey& K1) const
326 if (IsEmpty()) return 0;
327 TCollection_IndexedDataMapNode** data1 = (TCollection_IndexedDataMapNode**)myData1;
328 Standard_Integer k1 = Hasher::HashCode(K1,NbBuckets());
329 TCollection_IndexedDataMapNode *p1;
332 if (Hasher::IsEqual(p1->Key1(),K1)) return p1->Key2();
333 p1 = (TCollection_IndexedDataMapNode*)p1->Next();
337 //=======================================================================
338 //function : Contains
340 //=======================================================================
341 Standard_Boolean TCollection_IndexedDataMap::Contains(const TheKey& K1) const
343 if (IsEmpty()) return Standard_False;
344 TCollection_IndexedDataMapNode** data1 = (TCollection_IndexedDataMapNode**)myData1;
345 Standard_Integer k1 = Hasher::HashCode(K1,NbBuckets());
346 TCollection_IndexedDataMapNode *p1;
349 if (Hasher::IsEqual(p1->Key1(),K1)) return Standard_True;
350 p1 = (TCollection_IndexedDataMapNode*) p1->Next();
352 return Standard_False;
354 //=======================================================================
355 //function : FindFromKey
357 //=======================================================================
358 const TheItem& TCollection_IndexedDataMap::FindFromKey(const TheKey& K1) const
360 Standard_OutOfRange_Raise_if(IsEmpty(),"TCollection_IndexedDataMap::FindFromKey");
361 TCollection_IndexedDataMapNode** data1 = (TCollection_IndexedDataMapNode**)myData1;
362 Standard_Integer k1 = Hasher::HashCode(K1,NbBuckets());
363 TCollection_IndexedDataMapNode *p1;
366 if (Hasher::IsEqual(p1->Key1(),K1)) return p1->Value();
367 p1 = (TCollection_IndexedDataMapNode*) p1->Next();
369 throw Standard_OutOfRange("TCollection_IndexedDataMap::FindFromKey");
372 //=======================================================================
373 //function : ChangeFromKey
375 //=======================================================================
376 TheItem& TCollection_IndexedDataMap::ChangeFromKey(const TheKey& K1)
378 Standard_OutOfRange_Raise_if(IsEmpty(),"TCollection_IndexedDataMap::ChangeFromKey");
379 TCollection_IndexedDataMapNode** data1 = (TCollection_IndexedDataMapNode**)myData1;
380 Standard_Integer k1 = Hasher::HashCode(K1,NbBuckets());
381 TCollection_IndexedDataMapNode *p1;
384 if (Hasher::IsEqual(p1->Key1(),K1)) return p1->Value();
385 p1 = (TCollection_IndexedDataMapNode*)p1->Next();
387 throw Standard_OutOfRange("TCollection_IndexedDataMap::ChangeFromKey");
390 //modified by NIZNHY-PKV Tue Jul 05 08:37:03 2011f
391 //=======================================================================
392 //function : FindFromKey1
394 //=======================================================================
395 Standard_Address TCollection_IndexedDataMap::FindFromKey1(const TheKey& K1) const
397 TCollection_IndexedDataMap *pMap=(TCollection_IndexedDataMap *)this;
398 return pMap->ChangeFromKey1(K1);
400 //=======================================================================
401 //function : ChangeFromKey1
403 //=======================================================================
404 Standard_Address TCollection_IndexedDataMap::ChangeFromKey1(const TheKey& K1)
409 TCollection_IndexedDataMapNode** data1 = (TCollection_IndexedDataMapNode**)myData1;
410 Standard_Integer k1 = Hasher::HashCode(K1,NbBuckets());
411 TCollection_IndexedDataMapNode *p1;
414 if (Hasher::IsEqual(p1->Key1(),K1)) {
415 return (Standard_Address)&p1->Value();
417 p1 = (TCollection_IndexedDataMapNode*) p1->Next();