// Created on: 1993-01-08 // Created by: Remi LEQUETTE // Copyright (c) 1993-1999 Matra Datavision // Copyright (c) 1999-2014 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // // This library is free software; you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License version 2.1 as published // by the Free Software Foundation, with special exception defined in the file // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT // distribution for complete text of the license and disclaimer of any warranty. // // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. #include #include #include #include #include //======================================================================= //function : TCollection_IndexedMap //purpose : //======================================================================= TCollection_IndexedMap::TCollection_IndexedMap (const Standard_Integer NbBuckets): TCollection_BasicMap(NbBuckets,Standard_False) { } //======================================================================= //function : TCollection_IndexedMap //purpose : //======================================================================= TCollection_IndexedMap::TCollection_IndexedMap (const TCollection_IndexedMap& Other) : TCollection_BasicMap(Other.NbBuckets(),Standard_False) { if (!Other.IsEmpty()) { ReSize(Other.Extent()); for (Standard_Integer i = 1; i <= Other.Extent(); i++) { Add(Other(i)); } } } //======================================================================= //function : Assign //purpose : //======================================================================= TCollection_IndexedMap& TCollection_IndexedMap::Assign (const TCollection_IndexedMap& Other) { // very simple implementation // not optimal (recompute the hashcode values) if (this == &Other) return *this; Clear(); // ReSize(Other.NbBuckets()); if (!Other.IsEmpty()) { ReSize(Other.Extent()); for (Standard_Integer i = 1; i <= Other.Extent(); i++) { Add(Other(i)); } } return *this; } //======================================================================= //function : ReSize //purpose : //======================================================================= void TCollection_IndexedMap::ReSize(const Standard_Integer N) { Standard_Integer newBuck; Standard_Address newData1, newData2; if (BeginResize(N,newBuck,newData1,newData2)) { if (myData1) { TCollection_IndexedMapNode** newdata1 = (TCollection_IndexedMapNode**)newData1; TCollection_IndexedMapNode** newdata2 = (TCollection_IndexedMapNode**)newData2; TCollection_IndexedMapNode** olddata1 = (TCollection_IndexedMapNode**) myData1; TCollection_IndexedMapNode *p, *q; Standard_Integer i,k1,k2; for (i = 0; i <= NbBuckets(); i++) { if (olddata1[i]) { p = olddata1[i]; while (p) { k1 = Hasher::HashCode(p->Key1(),newBuck); q = (TCollection_IndexedMapNode*) p->Next(); p->Next() = newdata1[k1]; newdata1[k1] = p; if (p->Key2() > 0) { k2 = ::HashCode(p->Key2(),newBuck); p->Next2() = newdata2[k2]; newdata2[k2] = p; } p = q; } } } } EndResize(N,newBuck,newData1,newData2); } } //======================================================================= //function : Clear //purpose : //======================================================================= void TCollection_IndexedMap::Clear() { if (!IsEmpty()) { Standard_Integer i; TCollection_IndexedMapNode** data1 = (TCollection_IndexedMapNode**) myData1; // TCollection_IndexedMapNode** data2 = (TCollection_IndexedMapNode**) myData2; TCollection_IndexedMapNode *p,*q; for (i = 0; i <= NbBuckets(); i++) { p = data1[i]; while (p) { q = (TCollection_IndexedMapNode*) p->Next(); delete p; p = q; } } } TCollection_BasicMap::Destroy(); } //======================================================================= //function : Add //purpose : //======================================================================= Standard_Integer TCollection_IndexedMap::Add(const TheKey& K1) { if (Resizable()) ReSize(Extent()); TCollection_IndexedMapNode** data1 = (TCollection_IndexedMapNode**)myData1; Standard_Integer k1 = Hasher::HashCode(K1,NbBuckets()); TCollection_IndexedMapNode* p; p = data1[k1]; while (p) { if (Hasher::IsEqual(p->Key1(),K1)) return p->Key2(); p = (TCollection_IndexedMapNode*) p->Next(); } Increment(); TCollection_IndexedMapNode** data2 = (TCollection_IndexedMapNode**)myData2; Standard_Integer k2 = ::HashCode(Extent(),NbBuckets()); p = new TCollection_IndexedMapNode(K1,Extent(),data1[k1],data2[k2]); data1[k1] = p; data2[k2] = p; return Extent(); } //======================================================================= //function : Substitute //purpose : //======================================================================= void TCollection_IndexedMap::Substitute(const Standard_Integer I, const TheKey& K1) { Standard_OutOfRange_Raise_if(I < 1 || I > Extent(), "IndexedMap::Substitute : " "Index is out of range"); TCollection_IndexedMapNode** data1 = (TCollection_IndexedMapNode**)myData1; TCollection_IndexedMapNode* p; // check if K1 is not already in the map Standard_Integer k1 = Hasher::HashCode(K1,NbBuckets()); p = data1[k1]; while (p) { if (Hasher::IsEqual(p->Key1(),K1)) { if (p->Key2() != I) throw Standard_DomainError("IndexedMap::Substitute : " "Attempt to substitute existing key"); p->Key1() = K1; return; } p = (TCollection_IndexedMapNode*) p->Next(); } // Find the node for the index I TCollection_IndexedMapNode** data2 = (TCollection_IndexedMapNode**)myData2; Standard_Integer k2 = ::HashCode(I,NbBuckets()); p = data2[k2]; while (p) { if (p->Key2() == I) break; p = (TCollection_IndexedMapNode*) p->Next2(); } // remove the old key Standard_Integer k = Hasher::HashCode(p->Key1(),NbBuckets()); TCollection_IndexedMapNode* q = data1[k]; if (q == p) data1[k] = (TCollection_IndexedMapNode*) p->Next(); else { while(q->Next() != p) q = (TCollection_IndexedMapNode*) q->Next(); q->Next() = p->Next(); } // update the node p->Key1() = K1; p->Next() = data1[k1]; data1[k1] = p; } //======================================================================= //function : RemoveLast //purpose : //======================================================================= void TCollection_IndexedMap::RemoveLast() { Standard_OutOfRange_Raise_if(Extent() == 0, "IndexedMap::RemoveLast"); TCollection_IndexedMapNode** data1 = (TCollection_IndexedMapNode**)myData1; TCollection_IndexedMapNode* p; TCollection_IndexedMapNode* q; // Find the node for the last index and remove it TCollection_IndexedMapNode** data2 = (TCollection_IndexedMapNode**)myData2; Standard_Integer k2 = ::HashCode(Extent(),NbBuckets()); p = data2[k2]; q = NULL; while (p) { if (p->Key2() == Extent()) break; q = p; p = (TCollection_IndexedMapNode*) p->Next2(); } if (q == NULL) data2[k2] = (TCollection_IndexedMapNode*)p->Next2(); else q->Next2() = p->Next2(); // remove the key Standard_Integer k = Hasher::HashCode(p->Key1(),NbBuckets()); q = data1[k]; if (q == p) data1[k] = (TCollection_IndexedMapNode*) p->Next(); else { while(q->Next() != p) q = (TCollection_IndexedMapNode*) q->Next(); q->Next() = p->Next(); } Decrement(); delete p; } //======================================================================= //function : Contains //purpose : //======================================================================= Standard_Boolean TCollection_IndexedMap::Contains(const TheKey& K1) const { if (IsEmpty()) return Standard_False; TCollection_IndexedMapNode** data1 = (TCollection_IndexedMapNode**)myData1; Standard_Integer k1 = Hasher::HashCode(K1,NbBuckets()); TCollection_IndexedMapNode *p1; p1 = data1[k1]; while (p1) { if (Hasher::IsEqual(p1->Key1(),K1)) return Standard_True; p1 = (TCollection_IndexedMapNode*) p1->Next(); } return Standard_False; } //======================================================================= //function : FindKey //purpose : //======================================================================= const TheKey& TCollection_IndexedMap::FindKey(const Standard_Integer K2) const { Standard_OutOfRange_Raise_if(K2 < 1 || K2 > Extent(), "IndexedMap"); TCollection_IndexedMapNode** data2 = (TCollection_IndexedMapNode**)myData2; Standard_Integer k2 = ::HashCode(K2,NbBuckets()); TCollection_IndexedMapNode *p2; p2 = data2[k2]; while (p2) { if (p2->Key2() == K2) return p2->Key1(); p2 = (TCollection_IndexedMapNode*)p2->Next2(); } throw Standard_OutOfRange("IndexedMap : missing index !!!"); return p2->Key1(); } //======================================================================= //function : FindIndex //purpose : //======================================================================= Standard_Integer TCollection_IndexedMap::FindIndex(const TheKey& K1) const { if (IsEmpty()) return 0; TCollection_IndexedMapNode** data1 = (TCollection_IndexedMapNode**)myData1; Standard_Integer k1 = Hasher::HashCode(K1,NbBuckets()); TCollection_IndexedMapNode *p1; p1 = data1[k1]; while (p1) { if (Hasher::IsEqual(p1->Key1(),K1)) return p1->Key2(); p1 = (TCollection_IndexedMapNode*) p1->Next(); } return 0; }