Files
cdev-1.7.2n/include/cdevDirectoryTable.h
2022-12-13 12:44:04 +01:00

723 lines
23 KiB
C++

#ifndef _CDEV_DIRECTORY_TABLE_H_
#define _CDEV_DIRECTORY_TABLE_H_
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <cdevSystem.h>
#include <cdevErrCode.h>
#include <cdevError.h>
#include <StringHash.h>
#ifdef __VMS
typedef unsigned long u_long;
typedef unsigned short u_short;
#endif
class cdevElementDefinition;
class cdevClassDefinition;
class cdevServiceDefinition;
class cdevAliasDefinition;
class cdevDeviceDefinition;
class cdevCollectionDefinition;
int CDEV_CLASS_SPEC cdevReportError(int severity, char *name, void *, char *formatString, ...);
// *****************************************************************************
// * class cdevDirectoryTable :
// * This is the master class that is used to collect and maintain
// * information associated with the CDEV Device Definition Language file.
// *
// * This class maintains a number of tables and lists for the following
// * purposes...
// *
// * collectionClass - This is the single instance of the cdevClassDefinition
// * for the collection class.
// *
// * serviceHead - This is a list of all of the services that have been
// * serviceTail read from the DDL file in the order in which they
// * were loaded.
// *
// * classHead - This is a list of all of the classes that have been
// * classTail read from the DDL file in the order in which they
// * were loaded.
// *
// * aliasHead - This is a list of aliases that are defined within
// * aliasTail the DDL file.
// *
// * collectionHead - This is a list of collection devices that are
// * collectionTail defined within the DDL file.
// *
// * serviceHash - This is a hash table that allows for fast lookup of
// * each of the services that were loaded into the
// * service list.
// *
// * classHash - This is a hash table that allows fast lookup by name
// * of any of the classes that were loaded into the
// * class list.
// *
// * classInstanceHash - This is a hash table that contains only the names
// * and addresses of classes that have been used to
// * instanciate a device.
// *
// * deviceHash - This is a hash table that allows the caller to
// * quickly locate any device that has been defined in
// * the DDL file.
// *
// * collectionHash - This is a hash table that allows the caller to
// * quickly locate a collection device definition.
// *****************************************************************************
class CDEV_CLASS_SPEC cdevDirectoryTable
{
public:
static long BinaryMagic_1_4;
static long BinaryMagic_1_5;
static long BinaryMagic;
typedef enum {VERB=0, ATTRIBUTE, MESSAGE} ElementType;
private:
cdevClassDefinition * collectionClass;
cdevServiceDefinition * serviceHead;
cdevServiceDefinition * serviceTail;
cdevClassDefinition * classHead;
cdevClassDefinition * classTail;
cdevAliasDefinition * aliasHead;
cdevAliasDefinition * aliasTail;
cdevCollectionDefinition * collectionHead;
cdevCollectionDefinition * collectionTail;
StringHash serviceHash;
StringHash classHash;
StringHash classInstanceHash;
StringHash deviceHash;
StringHash collectionHash;
public:
inline cdevDirectoryTable ( void );
inline ~cdevDirectoryTable ( void );
inline int addService ( cdevServiceDefinition *def );
inline int addService ( char *name,
char **tags=NULL,
int nTags=0);
inline int addClass ( cdevClassDefinition *def );
inline int addClass ( char *name,
cdevClassDefinition *parent = NULL,
cdevElementDefinition *verbs = NULL,
cdevElementDefinition *attributes = NULL,
cdevElementDefinition *messages = NULL);
inline int addClassInstance ( cdevClassDefinition * def );
inline int addDevice ( cdevDeviceDefinition * def );
inline int addAlias ( cdevAliasDefinition * def );
inline int addAlias ( char * name, cdevDeviceDefinition & def );
inline int addCollection ( cdevCollectionDefinition * def );
inline int addCollection ( char * name, char ** devices, int nDevices );
inline void asciiDump ( FILE * fp = stdout );
inline void asciiDumpRedirector ( FILE * fp = stdout );
inline cdevServiceDefinition * findService ( char * name );
inline cdevClassDefinition * findClass ( char * name );
// *********************************************************************
// * Member access methods.
// *********************************************************************
inline cdevServiceDefinition * getServices ( void );
inline cdevClassDefinition * getClasses ( void );
inline cdevAliasDefinition * getAliases ( void );
inline StringHash & getServiceHash ( void );
inline StringHash & getClassHash ( void );
inline StringHash & getInstanceHash ( void );
inline StringHash & getDeviceHash ( void );
inline StringHash & getCollectionHash (void );
// *********************************************************************
// * External data load/dump methods.
// *********************************************************************
int load ( char * inputFile );
int asciiLoad ( char * inputFile );
int asciiBufferLoad ( char * buffer );
void binaryDump ( char * outputFile );
int binaryLoad ( char * inputFile );
int loadText ( char * includePath, char * filename, char * &buf, int &buflen, int &cursor);
void readServices ( char * buf );
void readClasses ( char * buf );
void readElements ( cdevClassDefinition &def, ElementType type, char *start, char *end );
void readDevices ( char * buf );
void readAliases ( char * buf );
void readCollections ( char * buf );
void compressComments ( char * filename, char * buf );
void compressSpaces ( char * filename, char * buf );
};
#include <cdevDeviceDefinition.h>
#include <cdevAliasDefinition.h>
#include <cdevServiceDefinition.h>
#include <cdevElementDefinition.h>
#include <cdevRedirectorDefinition.h>
#include <cdevClassDefinition.h>
#include <cdevCollectionDefinition.h>
// *****************************************************************************
// * cdevDirectoryTable::cdevDirectoryTable :
// * Constructor for the cdevDirectoryTable class.
// *****************************************************************************
inline cdevDirectoryTable::cdevDirectoryTable ( void )
: serviceHead(NULL), serviceTail(NULL), classHead(NULL), classTail(NULL),
aliasHead(NULL), aliasTail(NULL), collectionHead(NULL),
collectionTail(NULL), serviceHash(0), classHash(0),
deviceHash(0, 9973), classInstanceHash(0), collectionHash(0)
{
// *********************************************************************
// * Note, by creating a collection class to hold all collection devices
// * I am preventing the developer from creating his own collection
// * class.
// *********************************************************************
collectionClass = new cdevClassDefinition(*this, strdup("collection"));
addClass(collectionClass);
}
// *****************************************************************************
// * cdevDirectoryTable::~cdevDirectoryTable :
// * This is the destructor for the cdevDirectoryTable class.
// *****************************************************************************
inline cdevDirectoryTable::~cdevDirectoryTable ( void )
{
while(serviceHead!=NULL)
{
cdevServiceDefinition *ptr = serviceHead;
serviceHead = ptr->getNext();
serviceHash.remove(ptr->getName());
delete ptr;
}
while(classHead!=NULL)
{
cdevClassDefinition *ptr = classHead;
classHead = ptr->getNext();
classHash.remove(ptr->getName());
classInstanceHash.remove(ptr->getName());
delete ptr;
}
while(aliasHead!=NULL)
{
cdevAliasDefinition *ptr = aliasHead;
aliasHead = ptr->getNext();
deviceHash.remove(ptr->getName());
delete ptr;
}
while(collectionHead!=NULL)
{
cdevCollectionDefinition *ptr = collectionHead;
collectionHead = ptr->getNext();
collectionHash.remove(ptr->getName());
delete ptr;
}
}
// *****************************************************************************
// * cdevDirectoryTable::addService :
// * Adds a new service to the directory table.
// *****************************************************************************
inline int cdevDirectoryTable::addService ( cdevServiceDefinition * def )
{
int result = CDEV_SUCCESS;
if(def!=NULL && def->getName() && *def->getName())
{
if(serviceHash.find(def->getName())!=NULL)
{
cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL,
"Service \"%s\" is already defined", def->getName());
result = CDEV_ERROR;
}
else
{
serviceHash.insert(def->getName(), def);
if(serviceTail==NULL)
{
serviceTail = def;
serviceHead = def;
}
else {
serviceTail->setNext(def);
serviceTail = def;
}
}
}
else result = CDEV_ERROR;
return result;
}
// *****************************************************************************
// * cdevDirectoryTable::addService :
// * Adds a new service to the directory table.
// *****************************************************************************
inline int cdevDirectoryTable::addService ( char * name, char ** tags, int nTags )
{
int result = CDEV_SUCCESS;
if(name!=NULL && *name)
{
if(serviceHash.find(name)!=NULL)
{
cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL,
"Service \"%s\" is already defined", name);
result = CDEV_ERROR;
}
else
{
cdevServiceDefinition *def = new cdevServiceDefinition
(name, tags, nTags);
serviceHash.insert(name, def);
if(serviceTail==NULL)
{
serviceTail = def;
serviceHead = def;
}
else {
serviceTail->setNext(def);
serviceTail = def;
}
}
}
else result = CDEV_ERROR;
return result;
}
// *****************************************************************************
// * cdevDirectoryTable::addClass :
// * Adds a new class to the directory table.
// *****************************************************************************
inline int cdevDirectoryTable::addClass ( cdevClassDefinition * def )
{
int result = CDEV_SUCCESS;
if(def!=NULL && def->getName() && *def->getName())
{
if(classHash.find(def->getName())!=NULL)
{
cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL,
"Class \"%s\" is already defined", def->getName());
result = CDEV_ERROR;
}
else
{
classHash.insert(def->getName(), def);
if(classTail==NULL)
{
classTail = def;
classHead = def;
}
else {
classTail->setNext(def);
classTail = def;
}
}
}
else result = CDEV_ERROR;
return result;
}
// *****************************************************************************
// * cdevDirectoryTable::addClass :
// * Adds a new class to the directory table.
// *****************************************************************************
inline int cdevDirectoryTable::addClass
( char *name,
cdevClassDefinition *parent,
cdevElementDefinition *verbs,
cdevElementDefinition *attributes,
cdevElementDefinition *messages)
{
int result = CDEV_SUCCESS;
if(name!=NULL && *name)
{
if(classHash.find(name)!=NULL)
{
cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL,
"Class \"%s\" is already defined", name);
result = CDEV_ERROR;
}
else
{
cdevClassDefinition *def = new cdevClassDefinition
(*this, name, parent, verbs, attributes, messages);
classHash.insert(name, def);
if(classTail==NULL)
{
classTail = def;
classHead = def;
}
else {
classTail->setNext(def);
classTail = def;
}
}
}
else result = CDEV_ERROR;
return result;
}
// *****************************************************************************
// * cdevDirectoryTable::addClassInstance :
// * Adds a new class instance to the directory table.
// *****************************************************************************
inline int cdevDirectoryTable::addClassInstance ( cdevClassDefinition * def )
{
int result = CDEV_SUCCESS;
if(def!=NULL && def->getName() && *def->getName())
{
if(classHash.find(def->getName())==NULL)
{
cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL,
"Class \"%s\" has not been defined", def->getName());
result = CDEV_ERROR;
}
else if(classInstanceHash.find(def->getName())==NULL)
{
classInstanceHash.insert(def->getName(), def);
}
}
else result = CDEV_ERROR;
return result;
}
// *****************************************************************************
// * cdevDirectoryTable::addDevice :
// * Adds a new device to the directory table.
// *****************************************************************************
inline int cdevDirectoryTable::addDevice ( cdevDeviceDefinition * def )
{
int result = CDEV_SUCCESS;
if(def!=NULL && def->getName()!=NULL && *def->getName())
{
if(deviceHash.find(def->getName())!=NULL)
{
cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL,
"Device \"%s\" has already been defined", def->getName());
result = CDEV_ERROR;
}
else deviceHash.insert(def->getName(), def);
}
else result = CDEV_ERROR;
return result;
}
// *****************************************************************************
// * cdevDirectoryTable::addAlias :
// * Adds a new alias to the directory table.
// *****************************************************************************
inline int cdevDirectoryTable::addAlias ( cdevAliasDefinition * def )
{
int result = CDEV_SUCCESS;
if(def!=NULL && def->getName() && *def->getName())
{
if(deviceHash.find(def->getName())!=NULL)
{
cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL,
"Alias \"%s\" has already been defined", def->getName());
result = CDEV_ERROR;
}
else {
if(aliasTail==NULL)
{
aliasHead = def;
aliasTail = def;
}
else {
aliasTail->setNext(def);
aliasTail = def;
}
deviceHash.insert(def->getName(), &def->getDevice());
}
}
else result = CDEV_ERROR;
return result;
}
// *****************************************************************************
// * cdevDirectoryTable::addAlias :
// * Adds a new alias to the directory table.
// *****************************************************************************
inline int cdevDirectoryTable::addAlias
( char * name, cdevDeviceDefinition & device )
{
cdevAliasDefinition *def = new cdevAliasDefinition(name, device);
int result = addAlias(def);
if(result!=CDEV_SUCCESS) delete def;
return result;
}
// *****************************************************************************
// * cdevDirectoryTable::addCollection :
// * Adds a new collection to the directory table.
// *****************************************************************************
inline int cdevDirectoryTable::addCollection ( cdevCollectionDefinition * def )
{
int result = CDEV_SUCCESS;
if(def!=NULL && def->getName()!=NULL && *def->getName())
{
if(deviceHash.find(def->getName())!=NULL ||
collectionHash.find(def->getName())!=NULL)
{
cdevReportError(CDEV_SEVERITY_ERROR, "CDEV Directory", NULL,
"Collection device \"%s\" has already been defined", def->getName());
result = CDEV_ERROR;
}
else {
if(collectionTail==NULL)
{
collectionTail = def;
collectionHead = def;
}
else {
collectionTail->setNext(def);
collectionTail = def;
}
collectionHash.insert(def->getName(), def);
collectionClass->addDevice (strdup(def->getName()));
}
}
else result = CDEV_ERROR;
return result;
}
// *****************************************************************************
// * cdevDirectoryTable::addCollection :
// * Adds a new collection to the directory table.
// *****************************************************************************
inline int cdevDirectoryTable::addCollection ( char * name, char ** devices, int nDevices )
{
int result;
cdevCollectionDefinition * def =
new cdevCollectionDefinition(name, devices, nDevices);
if((result = addCollection(def))!=CDEV_SUCCESS) delete def;
return result;
}
// *****************************************************************************
// * cdevDirectoryTable::findService :
// * Allows the caller to locate a service by name.
// *****************************************************************************
inline cdevServiceDefinition * cdevDirectoryTable::findService ( char * name )
{
return (cdevServiceDefinition *)serviceHash.find(name);
}
// *****************************************************************************
// * cdevDirectoryTable::findClass :
// * Allows the caller to locate a class by name.
// *****************************************************************************
inline cdevClassDefinition * cdevDirectoryTable::findClass ( char * name )
{
return (cdevClassDefinition *)classHash.find(name);
}
// *****************************************************************************
// * cdevDirectoryTable::asciiDump :
// * This method will write the contents of the cdevDirectory object to
// * the user provided file pointer.
// *****************************************************************************
inline void cdevDirectoryTable::asciiDump ( FILE * fp )
{
cdevServiceDefinition *sPtr = serviceHead;
if(sPtr)
{
fprintf(fp, "\n// ******************************************\n");
fprintf(fp, "// * Table of service definitions... *\n");
fprintf(fp, "// ******************************************\n");
}
while(sPtr!=NULL)
{
sPtr->asciiDump(fp);
sPtr = sPtr->getNext();
}
cdevClassDefinition *cPtr = classHead;
if(cPtr)
{
fprintf(fp, "\n// ******************************************\n");
fprintf(fp, "// * Table of class definitions... *\n");
fprintf(fp, "// ******************************************\n");
}
while(cPtr!=NULL)
{
if(cPtr!=collectionClass) cPtr->asciiDump(fp);
cPtr = cPtr->getNext();
}
cPtr = classHead;
if(cPtr)
{
fprintf(fp, "\n// ******************************************\n");
fprintf(fp, "// * Table of class instance definitions... *\n");
fprintf(fp, "// ******************************************\n");
}
while(cPtr!=NULL)
{
if(cPtr!=collectionClass) cPtr->asciiDumpInstances(fp);
cPtr = cPtr->getNext();
}
cdevAliasDefinition *aPtr = aliasHead;
if(aPtr)
{
fprintf(fp, "\n\n// ******************************************\n");
fprintf(fp, "// * Table of alias definitions... *\n");
fprintf(fp, "// ******************************************\n");
}
while(aPtr!=NULL)
{
aPtr->asciiDump(fp);
aPtr = aPtr->getNext();
}
cdevCollectionDefinition * clPtr = collectionHead;
if(clPtr)
{
fprintf(fp, "\n\n// ******************************************\n");
fprintf(fp, "// * Table of collection definitions... *\n");
fprintf(fp, "// ******************************************\n");
}
while(clPtr!=NULL)
{
clPtr->asciiDump(fp);
clPtr = clPtr->getNext();
}
}
// *****************************************************************************
// * cdevDirectoryTable::asciiDumpRedirector :
// * This is a diagnostic method that allows the caller to dump the contents
// * of the redirection table for each class that has been instanciated.
// *****************************************************************************
inline void cdevDirectoryTable::asciiDumpRedirector ( FILE * fp )
{
int cnt = 0;
cdevClassDefinition *def;
for(def = classHead; def!=NULL; def = def->getNext())
{
if(classInstanceHash.find(def->getName())!=NULL)
{
def->asciiDumpRedirector(fp);
cnt++;
}
}
if(!cnt) cdevReportError(CDEV_SEVERITY_WARN, "CDEV Directory", NULL,
"No devices have been instanciated");
}
// *****************************************************************************
// * cdevDirectoryTable::getServices :
// * Returns the list of services that are defined within the directory.
// *****************************************************************************
inline cdevServiceDefinition * cdevDirectoryTable::getServices ( void )
{
return serviceHead;
}
// *****************************************************************************
// * cdevDirectoryTable::getClasses :
// * Returns the list of classes that are defined within the directory.
// *****************************************************************************
inline cdevClassDefinition * cdevDirectoryTable::getClasses ( void )
{
return classHead;
}
// *****************************************************************************
// * cdevDirectoryTable::getAliases :
// * Returns the list of aliases that are defined within the directory.
// *****************************************************************************
inline cdevAliasDefinition * cdevDirectoryTable::getAliases ( void )
{
return aliasHead;
}
// *****************************************************************************
// * cdevDirectoryTable::getServiceHash :
// * Return a hash table of services that are defined within the directory.
// *****************************************************************************
inline StringHash & cdevDirectoryTable::getServiceHash ( void )
{
return serviceHash;
}
// *****************************************************************************
// * cdevDirectoryTable::getClassHash :
// * Return a hash table of classes that are defined within the directory.
// *****************************************************************************
inline StringHash & cdevDirectoryTable::getClassHash ( void )
{
return classHash;
}
// *****************************************************************************
// * cdevDirectoryTable::getInstanceHash :
// * Return a hash table of classes that have been instanciated within the
// * directory.
// *****************************************************************************
inline StringHash & cdevDirectoryTable::getInstanceHash ( void )
{
return classInstanceHash;
}
// *****************************************************************************
// * cdevDirectoryTable::getDeviceHash :
// * Return a hash table of device names that have been instanciated in all
// * classes within the directory. This hash-table includes aliases that
// * have been instanciated.
// *****************************************************************************
inline StringHash & cdevDirectoryTable::getDeviceHash ( void )
{
return deviceHash;
}
// *****************************************************************************
// * cdevDirectoryTable::getCollectionHash :
// * Return a hash table of collection names that have been instanciated in
// * the DDL file. Each collection definition contains the list of devices
// * that it contains.
// *****************************************************************************
inline StringHash & cdevDirectoryTable::getCollectionHash ( void )
{
return collectionHash;
}
#endif /* _CDEV_DIRECTORY_TABLE_H_ */