|
楼主 |
发表于 2007-7-22 21:21:45
|
显示全部楼层
回复: node sample
7.STypeMap.cpp
// STypeMap.cpp: implementation of the CSClassTypeMap class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "CSTypedef.h"
#include "CSBaseMapIterator.h"
#include "CSMapHasher.h"
#include "CSClassTypeMap.h"
class Node : public CSMapNode
{
public :
Node(const PCSClassTypeNode& K1, const CS_Integer K2, Node* n1, Node* n2) :
CSMapNode(n1),key1(K1),key2(K2),next2(n2) {}
void* operator new(size_t aSize)
{return calloc(1,aSize);}
void operator delete(void* aNode )
{
free(aNode);
}
PCSClassTypeNode key1;
CS_Integer key2;
Node* next2;
};
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//=======================================================================
//function : CSClassTypeMap
//purpose :
//=======================================================================
CSClassTypeMap::CSClassTypeMap(const CS_Integer NbBuckets )
{
//:CSBaseMap(NbBuckets,CS_False)
CSBaseMap(NbBuckets,CS_False,1);
}
//=======================================================================
//function : CSClassTypeMap
//purpose :
//=======================================================================
CSClassTypeMap::CSClassTypeMap(const CS_Integer NbBuckets ,const CS_Integer maxsize ) :
CSBaseMap(NbBuckets,CS_False,maxsize)
{
}
//=======================================================================
//function : CSClassTypeMap
//purpose :
//=======================================================================
CSClassTypeMap::CSClassTypeMap(const CSClassTypeMap& Other) :
CSBaseMap(Other.GetBucketsNum(),CS_False)
{
if (!Other.IsEmpty())
Standard_DomainError::Raise("Standard:Copy of IndexedMap");
}
//=======================================================================
//function : Assign
//purpose :
//=======================================================================
CSClassTypeMap& CSClassTypeMap::Assign(const CSClassTypeMap& Other)
{
// very simple implementation
// not optimal (recompute the hashcode values)
if (this == &Other) return *this;
Clear();
ReSize(Other.GetBucketsNum());
for (CS_Integer i = 1; i <= Other.Extent(); i++)
{
Add(Other(i));
}
return *this;
}
//=======================================================================
//function : ReSize
//purpose :
//=======================================================================
void CSClassTypeMap::ReSize(const CS_Integer N)
{
Node** pData1;
Node** pData2;
CS_Integer nBuck ;
if (BeginResize(N,nBuck,
*(CS_Address*)&pData1,
*(CS_Address*)&pData2))
{
Node *p, *q;
CS_Integer i,k1,k2;
if (m_pData1)
{
Node** olddata1 = (Node**) m_pData1;
for (i = 0; i <= GetBucketsNum(); i++)
{
if (olddata1)
{
p = olddata1;
while (p)
{
k1 = Hasher::HashCode(p->key1,nBuck);
q = (Node*) p->next;
p->next = pData1[k1];
pData1[k1] = p;
if (p->key2 > 0) {
k2 = ::HashCode(p->key2,nBuck);
p->next2 = pData2[k2];
pData2[k2] = p;
}
p = q;
}
}
}
}
EndResize(N,nBuck,pData1,pData2);
}
}
//=======================================================================
//function : Clear
//purpose :
//=======================================================================
void CSClassTypeMap::Clear()
{
if (!IsEmpty())
{
CS_Integer i;
Node** data1 = (Node**) m_pData1;
Node *p,*q;
for (i = 0; i <= GetBucketsNum(); i++)
{
p = data1;
while (p)
{
q = (Node*) p->next;
delete p;
p = q;
}
}
}
CSBaseMap:estroy();
}
//=======================================================================
//function : Add
//purpose :
//=======================================================================
CS_Integer CSClassTypeMap::Add(const PCSClassTypeNode& K1)
{
if (Resizable()) ReSize(Extent());
Node** data1 = (Node**)m_pData1;
CS_Integer k1 = Hasher::HashCode(K1,GetBucketsNum());
Node* p;
p = data1[k1];
while (p) {
if (Hasher::IsEqual(p->key1,K1))
return p->key2;
p = (Node*) p->next;
}
Increment();
Node** data2 = (Node**)m_pData2;
CS_Integer k2 = ::HashCode(Extent(),GetBucketsNum());
p = new Node(K1,Extent(),data1[k1],data2[k2]);
data1[k1] = p;
data2[k2] = p;
return Extent();
}
//=======================================================================
//function : Substitute
//purpose :
//=======================================================================
void CSClassTypeMap::Substitute(const CS_Integer I,const PCSClassTypeNode& K1)
{
Standard_OutOfRange_Raise_if(I < 1 || I > Extent(),
"IndexedMap::Substitute");
Node** data1 = (Node**)m_pData1;
Node* p;
// check if K1 is not already in the map
CS_Integer k1 = Hasher::HashCode(K1,GetBucketsNum());
p = data1[k1];
while (p) {
if (Hasher::IsEqual(p->key1,K1))
Standard_DomainError::Raise("IndexedMap::Substitute");
p = (Node*) p->next;
}
// Find the node for the index I
Node** data2 = (Node**)m_pData2;
CS_Integer k2 = ::HashCode(I,GetBucketsNum());
p = data2[k2];
while (p) {
if (p->key2 == I)
break;
p = (Node*) p->next2;
}
// remove the old key
CS_Integer k = Hasher::HashCode(p->key1,GetBucketsNum());
Node* q = data1[k];
if (q == p) data1[k] = (Node*) p->next;
else {
while(q->next != p) q = (Node*) q->next;
q->next = p->next;
}
// update the node
p->key1 = K1;
p->next = data1[k1];
data1[k1] = p;
}
//=======================================================================
//function : RemoveLast
//purpose :
//=======================================================================
void CSClassTypeMap::RemoveLast()
{
Standard_OutOfRange_Raise_if(Extent() == 0,
"IndexedMap::RemoveLast");
Node** data1 = (Node**)m_pData1;
Node* p;
Node* q;
// Find the node for the last index and remove it
Node** data2 = (Node**)m_pData2;
CS_Integer k2 = ::HashCode(Extent(),GetBucketsNum());
p = data2[k2];
q = NULL;
while (p) {
if (p->key2 == Extent())
break;
q = p;
p = (Node*) p->next2;
}
if (q == NULL)
data2[k2] = p->next2;
else
q->next2 = p->next2;
// remove the key
CS_Integer k = Hasher::HashCode(p->key1,GetBucketsNum());
q = data1[k];
if (q == p) data1[k] = (Node*) p->next;
else {
while(q->next != p) q = (Node*) q->next;
q->next = p->next;
}
Decrement();
delete p;
}
//=======================================================================
//function : Contains
//purpose :
//=======================================================================
CS_Boolean CSClassTypeMap::Contains(const PCSClassTypeNode& K1) const
{
if (IsEmpty()) return CS_False;
Node** data1 = (Node**)m_pData1;
CS_Integer k1 = Hasher::HashCode(K1,GetBucketsNum());
Node *p1;
p1 = data1[k1];
while (p1) {
if (Hasher::IsEqual(p1->key1,K1)) return CS_True;
p1 = (Node*) p1->next;
}
return CS_False;
}
//=======================================================================
//function : FindKey
//purpose :
//=======================================================================
static void *theNULL = NULL ;
const PCSClassTypeNode& CSClassTypeMap::FindKey(const CS_Integer K2) const
{
if (K2 < 1 || K2 > Extent())
return (const PCSClassTypeNode& ) theNULL ;
Node** data2 = (Node**)m_pData2;
CS_Integer k2 = ::HashCode(K2,GetBucketsNum());
Node *p2;
p2 = data2[k2];
while (p2) {
if (p2->key2 == K2) return p2->key1;
p2 = p2->next2;
}
return (const PCSClassTypeNode& ) theNULL ;
}
//=======================================================================
//function : FindIndex
//purpose :
//=======================================================================
CS_Integer CSClassTypeMap::FindIndex(const PCSClassTypeNode& K1) const
{
if (IsEmpty()) return 0;
Node** data1 = (Node**)m_pData1;
CS_Integer k1 = Hasher::HashCode(K1,GetBucketsNum());
Node *p1;
p1 = data1[k1];
while (p1) {
if (Hasher::IsEqual(p1->key1,K1)) return p1->key2;
p1 = (Node*) p1->next;
}
return 0;
}
inline PCSClassTypeNode CSClassTypeMap::FindFromType(const CSClassTypeHandle& aType ) const
{
return CSClassTypeMap::FindFromString( aType->Name() , aType->Size() ) ;
}
inline CS_Boolean CSClassTypeMap::IsUpdated()
{
CS_Boolean ret = m_bUpdate ;
m_bUpdate =CS_False ;
return ret ;
}
void CSClassTypeMap::ChangeSize(const CS_Integer N)
{
Node** pData1 = NULL ;
Node** pData2 = NULL ;
CS_Integer nBuck ;
if (BeginResize(N,nBuck,
*(CS_Address*)&pData1,
*(CS_Address*)&pData2)) {
Node *p, *q;
CS_Integer i,k1,k2;
if (m_pData1) {
Node** olddata1 = (Node**) m_pData1;
for (i = 0; i <= GetBucketsNum(); i++) {
if (olddata1) {
p = olddata1;
while (p) {
k1 = HashCode(p->key1->HashCode(),nBuck);
q = (Node*) p->next;
p->next = pData1[k1];
pData1[k1] = p;
if (p->key2 > 0) {
k2 = ::HashCode(p->key2,nBuck);
p->next2 = pData2[k2];
pData2[k2] = p;
}
p = q;
}
}
}
}
EndResize(N,nBuck,pData1,pData2);
}
}
CS_Integer CSClassTypeMap::AddFromForMapOfTypes(const PCSClassTypeNode & K)
{
CS_Integer aHashCode ;
if (Resizable()) ReSize(Extent());
Node** data1 = (Node**) m_pData1;
CS_Integer k1 = Hasher::HashCode(K->Name(),K->Length(),GetBucketsNum(),aHashCode);
Node* p = data1[ k1 ];
while (p) {
if (Hasher::IsEqual( p->key1 , K )) {
return 0 ;
}
p = (Node*)p->next;
}
Increment();
Node** data2 = (Node**)m_pData2;
CS_Integer k2 = ::HashCode(Extent(),GetBucketsNum());
p = new Node(K,Extent(),data1[k1],data2[k2]);
data1[k1] = p;
data2[k2] = p;
K->AddHashCode( aHashCode ) ;
if ( 2*Extent() > GetBucketsNum() )
ChangeSize( int( NextPrime( 3*GetBucketsNum() ) ) ) ;
K->Sort() ;
m_bUpdate = CS_True ;
return Extent();
}
CS_Integer CSClassTypeMap::AddFromType(const CSClassTypeHandle& K)
{
CS_Integer aHashCode ;
if (Resizable()) ReSize(Extent());
Node** data1 = (Node**) m_pData1;
CS_Integer k1 = Hasher::HashCode( K->Name() ,
K->Size() ,
GetBucketsNum() ,
aHashCode ) ;
Node* p = data1[ k1 ];
while (p) {
if (Hasher::IsEqual( p->key1 , K )) {
if ( p->key1->IsNotLoaded() ) {
PCSClassTypeNode pNode = new CSClassTypeNode( K ) ;
p->key1->Copy( pNode );
}
return 0 ;
}
p = (Node*)p->next;
}
PCSClassTypeNode pNode = new CSClassTypeNode( K ) ;
Increment();
data1 = (Node**) m_pData1; // May have changed !
Node** data2 = (Node**)m_pData2;
CS_Integer k2 = ::HashCode(Extent(),GetBucketsNum());
p = new Node(pNode,Extent(),data1[k1],data2[k2]);
data1[k1] = p;
data2[k2] = p;
pNode->AddHashCode( aHashCode ) ;
if ( 2*Extent() > GetBucketsNum() )
ChangeSize( int( NextPrime( 3*GetBucketsNum() ) ) ) ;
pNode->Sort() ;
m_bUpdate = CS_True ;
return Extent();
}
PCSClassTypeNode CSClassTypeMap::FindFromString(const CS_CString K ,
const CS_Integer Len ) const
{
if (IsEmpty()) return NULL;
Node** data = (Node**) m_pData1;
CS_Integer i = Hasher::HashCode( K , Len ,GetBucketsNum()) ;
Node* p = data[ i ] ;
while (p)
{
if (Hasher::IsEqual( p->key1 , K , Len ))
{
return p->key1 ;
}
p = (Node*)p->next;
}
return NULL ;
} |
|