#ifndef _CDEV_DIRECTORY_TABLE_H_ #define _CDEV_DIRECTORY_TABLE_H_ #include #include #include #include #include #include #include #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 #include #include #include #include #include #include // ***************************************************************************** // * 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_ */