Cloned library of VTK-5.0.0 with extra build files for internal package management.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

314 lines
10 KiB

/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkInstantiator.cxx,v $
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkInstantiator.h"
#include "vtkObjectFactory.h"
vtkCxxRevisionMacro(vtkInstantiator, "$Revision: 1.6 $");
vtkStandardNewMacro(vtkInstantiator);
// Node in hash table.
class vtkInstantiatorHashNode
{
public:
typedef vtkInstantiator::CreateFunction CreateFunction;
vtkInstantiatorHashNode() { this->ClassName = 0; this->Function = 0; }
void SetClassName(const char* className) { this->ClassName = className; }
const char* GetClassName() { return this->ClassName; }
void SetFunction(CreateFunction function) { this->Function = function; }
CreateFunction GetFunction() { return this->Function; }
private:
const char* ClassName;
CreateFunction Function;
};
// Hash table used by vtkInstantiator. Must not be a vtkObject.
class vtkInstantiatorHashTable
{
public:
vtkInstantiatorHashTable();
~vtkInstantiatorHashTable();
void PrintSelf(ostream& os, vtkIndent indent);
typedef vtkInstantiator::CreateFunction CreateFunction;
void Insert(const char* className, CreateFunction function);
void Erase(const char* className, CreateFunction function);
CreateFunction Find(const char* className);
protected:
unsigned long Hash(const char* s);
void ExtendBucket(unsigned long bucket);
const char* AddClassName(const char* className);
vtkInstantiatorHashNode** Buckets;
unsigned int* BucketCounts;
unsigned int* BucketSizes;
unsigned long NumberOfBuckets;
char** ClassNames;
unsigned long NumberOfClassNames;
unsigned long ClassNamesSize;
private:
vtkInstantiatorHashTable(const vtkInstantiatorHashTable&); // Not implemented.
void operator=(const vtkInstantiatorHashTable&); // Not implemented.
};
//----------------------------------------------------------------------------
vtkInstantiatorHashTable::vtkInstantiatorHashTable()
{
this->NumberOfBuckets = 101;
this->Buckets = new vtkInstantiatorHashNode*[this->NumberOfBuckets];
this->BucketCounts = new unsigned int[this->NumberOfBuckets];
this->BucketSizes = new unsigned int[this->NumberOfBuckets];
unsigned int i;
for(i=0;i < this->NumberOfBuckets;++i)
{
this->BucketCounts[i] = 0;
this->BucketSizes[i] = 16;
this->Buckets[i] = new vtkInstantiatorHashNode[this->BucketSizes[i]];
}
this->NumberOfClassNames = 0;
this->ClassNamesSize = 256;
this->ClassNames = new char*[this->ClassNamesSize];
}
//----------------------------------------------------------------------------
vtkInstantiatorHashTable::~vtkInstantiatorHashTable()
{
unsigned long i;
for(i=0; i < this->NumberOfBuckets;++i)
{
delete [] this->Buckets[i];
}
delete [] this->BucketSizes;
delete [] this->BucketCounts;
delete [] this->Buckets;
for(i=0;i < this->NumberOfClassNames;++i)
{
delete [] this->ClassNames[i];
}
delete [] this->ClassNames;
}
//----------------------------------------------------------------------------
void vtkInstantiatorHashTable::PrintSelf(ostream& os, vtkIndent indent)
{
os << indent << "NumberOfBuckets: " << this->NumberOfBuckets << "\n";
unsigned int i;
float avgBucketSize = 0;
unsigned int maxBucketSize = 0;
unsigned int minBucketSize = this->NumberOfClassNames;
for(i=0;i < this->NumberOfBuckets;++i)
{
avgBucketSize += this->BucketCounts[i];
if(this->BucketCounts[i] > maxBucketSize)
{ maxBucketSize = this->BucketCounts[i]; }
if(this->BucketCounts[i] < minBucketSize)
{ minBucketSize = this->BucketCounts[i]; }
}
avgBucketSize /= float(this->NumberOfBuckets);
os << indent << "Average Bucket Size: " << avgBucketSize << "\n";
os << indent << "Minimum Bucket Size: " << minBucketSize << "\n";
os << indent << "Maximum Bucket Size: " << maxBucketSize << "\n";
}
//----------------------------------------------------------------------------
void vtkInstantiatorHashTable::Insert(const char* className,
CreateFunction function)
{
unsigned long bucket = this->Hash(className);
if(this->BucketCounts[bucket] == this->BucketSizes[bucket])
{ this->ExtendBucket(bucket); }
// Do not check if the class is already registered. It is possible
// that more than one create function will be registered for the
// same class, and even that the same function is registered more
// than once. Each register should have a corresponding unregister.
// As long as any register has not had its corresponding unregister,
// we want to allow the class to be created.
unsigned int pos = this->BucketCounts[bucket]++;
this->Buckets[bucket][pos].SetClassName(this->AddClassName(className));
this->Buckets[bucket][pos].SetFunction(function);
}
//----------------------------------------------------------------------------
void vtkInstantiatorHashTable::Erase(const char* className,
CreateFunction function)
{
unsigned long bucket = this->Hash(className);
// Find the exact registration function we have been given, and
// remove it only once. If more than one funcion has been
// registered for this class, or the same function more than once,
// each register should have its corresponding unregister.
unsigned int i;
for(i=0; i < this->BucketCounts[bucket];++i)
{
if(((this->Buckets[bucket][i].GetFunction() == function)
&& (strcmp(this->Buckets[bucket][i].GetClassName(), className) == 0)))
{
unsigned int j;
--this->BucketCounts[bucket];
for(j=i;j < this->BucketCounts[bucket];++j)
{
this->Buckets[bucket][j] = this->Buckets[bucket][j+1];
}
return;
}
}
}
//----------------------------------------------------------------------------
vtkInstantiatorHashTable::CreateFunction
vtkInstantiatorHashTable::Find(const char* className)
{
unsigned long bucket = this->Hash(className);
unsigned int i;
for(i=0; i < this->BucketCounts[bucket];++i)
{
if(strcmp(this->Buckets[bucket][i].GetClassName(), className) == 0)
{ return this->Buckets[bucket][i].GetFunction(); }
}
return 0;
}
//----------------------------------------------------------------------------
unsigned long vtkInstantiatorHashTable::Hash(const char* s)
{
unsigned long h = 0;
for(;*s;++s) { h = 5*h + *s; }
return h % this->NumberOfBuckets;
}
//----------------------------------------------------------------------------
void vtkInstantiatorHashTable::ExtendBucket(unsigned long bucket)
{
unsigned int newSize = this->BucketSizes[bucket] * 2;
vtkInstantiatorHashNode* newBucket =
new vtkInstantiatorHashNode[newSize];
unsigned int i;
for(i=0; i < this->BucketCounts[bucket];++i)
{ newBucket[i] = this->Buckets[bucket][i]; }
delete [] this->Buckets[bucket];
this->Buckets[bucket] = newBucket;
this->BucketSizes[bucket] = newSize;
}
//----------------------------------------------------------------------------
const char* vtkInstantiatorHashTable::AddClassName(const char* className)
{
if(this->NumberOfClassNames == this->ClassNamesSize)
{
unsigned long newSize = this->ClassNamesSize * 2;
char** newNames = new char*[newSize];
unsigned long i;
for(i=0;i < this->NumberOfClassNames;++i)
{ newNames[i] = this->ClassNames[i]; }
delete [] this->ClassNames;
this->ClassNames = newNames;
this->ClassNamesSize = newSize;
}
char* newName = new char[strlen(className)+1];
strcpy(newName, className);
this->ClassNames[this->NumberOfClassNames++] = newName;
return newName;
}
//----------------------------------------------------------------------------
// Implementation of actual vtkInstantiator class.
//----------------------------------------------------------------------------
vtkInstantiator::vtkInstantiator()
{
}
//----------------------------------------------------------------------------
vtkInstantiator::~vtkInstantiator()
{
}
//----------------------------------------------------------------------------
void vtkInstantiator::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
vtkInstantiator::CreatorTable->PrintSelf(os, indent);
}
//----------------------------------------------------------------------------
vtkObject* vtkInstantiator::CreateInstance(const char* className)
{
CreateFunction function = vtkInstantiator::CreatorTable->Find(className);
if(function) { return function(); }
return 0;
}
//----------------------------------------------------------------------------
void vtkInstantiator::RegisterInstantiator(const char* className,
CreateFunction createFunction)
{
vtkInstantiator::CreatorTable->Insert(className, createFunction);
}
//----------------------------------------------------------------------------
void vtkInstantiator::UnRegisterInstantiator(const char* className,
CreateFunction createFunction)
{
vtkInstantiator::CreatorTable->Erase(className, createFunction);
}
//----------------------------------------------------------------------------
void vtkInstantiator::ClassInitialize()
{
vtkInstantiator::CreatorTable = new vtkInstantiatorHashTable;
}
//----------------------------------------------------------------------------
void vtkInstantiator::ClassFinalize()
{
delete vtkInstantiator::CreatorTable;
}
//----------------------------------------------------------------------------
vtkInstantiatorInitialize::vtkInstantiatorInitialize()
{
if(++vtkInstantiatorInitialize::Count == 1)
{ vtkInstantiator::ClassInitialize(); }
}
//----------------------------------------------------------------------------
vtkInstantiatorInitialize::~vtkInstantiatorInitialize()
{
if(--vtkInstantiatorInitialize::Count == 0)
{ vtkInstantiator::ClassFinalize(); }
}
//----------------------------------------------------------------------------
unsigned int vtkInstantiatorInitialize::Count;
vtkInstantiatorHashTable* vtkInstantiator::CreatorTable;