//---------------------------------------------------------------
#ifndef UIOObjH
#define UIOObjH
#pragma hdrstop
#include <stlcomp.h>
#include <typeinfo.h>
#include <map.h>
#include <cstring.h>
#include <strstrea.h>
#include <fstream.h>
// problem with Borland C++ and SGI templates?
// compiler error if not less<string> specialized!
// C++ BUILDER HAS NO SUCH PROBLEM
struct less<string> {
bool operator()(const string& x, const string& y) const
{ return (x < y); }
};
//---------------------------------------------------------------
class TIOObjectBase {
enum {MAX_NAME_SIZE = 70};
public:
// exception types
struct exception {
string mess;
exception(const char * _mess): mess(_mess) {}
virtual ~exception() {}
};
struct EUnknownClass : public exception {
EUnknownClass(const char * _className):
exception(_className) {}
};
struct EEof : public exception {
EEof(const char * which=NULL):
exception(which) {}
};
protected:
void write(ostrstream & mem);
static string readClassName(strstream & str)
throw (exception*) ;
static string readClassName(fstream& fstr)
throw (exception*, EEof*) ;
virtual void* dataStart(void) const = 0;
virtual size_t dataSize(void) const = 0;
typedef TIOObjectBase* (*pfCreate)(fstream&);
// for the input "virtual constructor" Create
typedef map<string, pfCreate, less<string> > CreateMap;
static CreateMap* pCreateMap;
public:
virtual ~TIOObjectBase() {}
// use to UN-Register() ALL and CLEANUP AFTER USE
static void reset();
virtual string name(void) const = 0;
void write(fstream& fstr);
static TIOObjectBase* Create( fstream& )
throw (exception*, EUnknownClass*) ;
};
//---------------------------------------------------------------
template <class T>
class TIOObject : public virtual TIOObjectBase {
private:
T Data;
static TIOObjectBase* create(fstream& )
throw (exception*);
protected:
void* dataStart(void) const {return (void*)&Data;}
size_t dataSize(void) const {return sizeof Data;}
static string Name(void){return typeid(TIOObject).name();}
string name(void) const {return Name();}
public:
TIOObject(const T& _data = T()): Data(_data) {}
// RECOGNIZE the type AND access the data :
// IF pIOObjectBase IS a TIOObject<T>* returns a T*
// ELSE returns 0
static T* PtrData(TIOObjectBase* pIOObjectBase);
static void Register(void);
};
//---------------- TEMPLATE FUNCTION DEFINITIONS ----------------
//
//---------------------------------------------------------------
template <class T>
TIOObjectBase* TIOObject<T>::create(fstream& fstr)
throw (exception*)
{
TIOObject* ptr = new TIOObject;
fstr.read((char*)ptr->dataStart(), ptr->dataSize());
if (fstr.eof())
throw new exception("unexpected end of file");
return ptr;
}
//---------------------------------------------------------------
// NB: although TIOObject<T> only has one data member, T Data
// a TIOObject* DOES NOT HAVE SAME ADDRESS AS ITS Data MEMBER!!!
// &(pIOObject->Data) < pIOObject->Data !!!
template <class T>
T* TIOObject<T>::PtrData(TIOObjectBase* pIOObjectBase)
{
TIOObject * pIOObject;
if ((pIOObject = dynamic_cast<TIOObject<T>* >(pIOObjectBase))
!= NULL )
return &(pIOObject->Data);
else
return NULL;
}
//---------------------------------------------------------------
template <class T>
void TIOObject<T>::Register(void) {
if (!TIOObjectBase::pCreateMap)
pCreateMap = new CreateMap();
(*pCreateMap)[Name()] = create;
}
#endif
//End of File