class.h
//
// class.h
//
// Copyright (C) 1996 Limit Point Systems, Inc.
//
// Author: Curtis Janssen <cljanss@limitpt.com>
// Maintainer: LPS
//
// This file is part of the SC Toolkit.
//
// The SC Toolkit is free software; you can redistribute it and/or modify
// it under the terms of the GNU Library General Public License as published by
// the Free Software Foundation; either version 2, or (at your option)
// any later version.
//
// The SC Toolkit is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public License
// along with the SC Toolkit; see the file COPYING.LIB. If not, write to
// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
//
// The U.S. Government is granted a limited license as per AL 91-7.
//
#ifdef __GNUG__
#pragma interface
#endif
#ifndef _util_class_class_h
#define _util_class_class_h
#include <map>
#include <set>
#include <string>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <iostream>
#include <iomanip>
#include <typeinfo>
#include <util/ref/ref.h>
#include <util/misc/exenv.h>
namespace sc {
template <class T, class C>
class DescribedMemberDatum {
private:
T C::*member_;
public:
DescribedMemberDatum(T C::*member): member_(member) {}
//T &member(C *c) { return c->*member_; }
};
class DescribedClass;
class ClassDesc;
typedef ClassDesc* ClassDescP;
typedef const ClassDesc* CClassDescP;
class ClassDesc;
class ParentClass
{
public:
enum Access { Private, Protected, Public };
private:
Access _access;
int _is_virtual;
ClassDesc* _classdesc;
public:
ParentClass(ClassDesc*,Access access = Private,int is_virtual = 0);
ParentClass(const ParentClass&);
~ParentClass();
int is_virtual() const;
Access access() const { return _access; }
const ClassDesc* classdesc() const;
void change_classdesc(ClassDesc*n);
};
class ParentClasses
{
private:
int _n;
ParentClass** _classes;
void add(ParentClass*);
// do not allow copy constructor or assignment
ParentClasses(const ParentClasses&);
void operator=(const ParentClasses&);
public:
ParentClasses();
void init(const char*);
~ParentClasses();
ParentClass& parent(int i) { return *_classes[i]; }
const ParentClass& parent(int i) const { return *_classes[i]; }
ParentClass& operator[](int i) { return *_classes[i]; }
const ParentClass& operator[](int i) const { return *_classes[i]; }
int n() const { return _n; }
void change_parent(ClassDesc*oldcd,ClassDesc*newcd);
};
class KeyVal;
class StateIn;
template <class T>
DescribedClass* create()
{
return new T;
}
template <class T>
DescribedClass* create(const Ref<KeyVal>& keyval)
{
return new T(keyval);
}
template <class T>
DescribedClass* create(StateIn& statein)
{
return new T(statein);
}
class type_info_key {
private:
const std::type_info *ti_;
public:
type_info_key(): ti_(0) {}
type_info_key(const std::type_info *ti): ti_(ti) {}
type_info_key& operator=(const type_info_key&);
int operator==(const type_info_key&) const;
int operator<(const type_info_key&) const;
int cmp(const type_info_key&) const;
};
class ClassDesc: public Identity {
friend class ParentClasses;
private:
static std::map<std::string,ClassDescP> *all_;
static std::map<type_info_key,ClassDescP> *type_info_all_;
static char * classlib_search_path_;
static std::set<std::string> *unresolved_parents_;
char* classname_;
int version_;
ParentClasses parents_;
std::set<std::string> *children_;
DescribedClass* (*ctor_)();
DescribedClass* (*keyvalctor_)(const Ref<KeyVal>&);
DescribedClass* (*stateinctor_)(StateIn&);
const std::type_info *ti_;
void change_parent(ClassDesc*oldcd,ClassDesc*newcd);
// do not allow copy constructor or assignment
ClassDesc(const ClassDesc&);
void operator=(const ClassDesc&);
// this is used for temporary parent class descriptors
ClassDesc(const char*);
void init(const char*,int=1,const char* p=0,
const std::type_info *ti=0,
DescribedClass* (*ctor)()=0,
DescribedClass* (*keyvalctor)(const Ref<KeyVal>&)=0,
DescribedClass* (*stateinctor)(StateIn&)=0);
public:
ClassDesc(const std::type_info&, const char*,int=1,const char* p=0,
DescribedClass* (*ctor)()=0,
DescribedClass* (*keyvalctor)(const Ref<KeyVal>&)=0,
DescribedClass* (*stateinctor)(StateIn&)=0);
~ClassDesc();
static std::map<std::string,ClassDescP>& all();
const ParentClasses& parents() const { return parents_; }
static void list_all_classes();
static ClassDesc* name_to_class_desc(const char*);
static ClassDesc *class_desc(const std::type_info &);
const char* name() const { return classname_; }
int version() const { return version_; }
DescribedClass* create_described_class() const;
virtual DescribedClass* create() const;
virtual DescribedClass* create(const Ref<KeyVal>&) const;
virtual DescribedClass* create(StateIn&) const;
static int load_class(const char* classname);
};
class DescribedClass : public RefCount {
public:
DescribedClass();
DescribedClass(const DescribedClass&);
DescribedClass& operator=(const DescribedClass&);
virtual ~DescribedClass();
ClassDesc* class_desc() const throw();
const char* class_name() const;
int class_version() const;
virtual void print(std::ostream& = ExEnv::out0()) const;
};
template <class T>
inline ClassDesc *
class_desc()
{
return ClassDesc::class_desc(typeid(T));
}
inline ClassDesc *
class_desc(DescribedClass *d)
{
return ClassDesc::class_desc(typeid(*d));
}
template<class T>
inline T
require_dynamic_cast(DescribedClass*p,const char * errmsg,...)
{
T t = dynamic_cast<T>(p);
if (p && !t) {
va_list args;
va_start(args,errmsg);
fprintf(stderr,"A required dynamic_cast failed in: ");
vfprintf(stderr,errmsg,args);
fprintf(stderr,"\nwanted type \"%s\" but got \"%s\"\n",
typeid(T).name(),p->class_desc()->name());
fflush(stderr);
va_end(args);
abort();
}
return t;
}
template<class T>
inline T
require_dynamic_cast(const DescribedClass*p,const char * errmsg,...)
{
T t = dynamic_cast<T>(p);
if (p && !t) {
va_list args;
va_start(args,errmsg);
fprintf(stderr,"A required dynamic_cast failed in: ");
vfprintf(stderr,errmsg,args);
fprintf(stderr,"\nwanted type \"%s\" but got \"%s\"\n",
typeid(T).name(),p->class_desc()->name());
fflush(stderr);
va_end(args);
abort();
}
return t;
}
template <class A>
class ForceLinkBase {
public:
ForceLinkBase() {};
virtual ~ForceLinkBase() {};
virtual DescribedClass *create(A) = 0;
};
template <class T, class A = const Ref<KeyVal> &>
class ForceLink: public ForceLinkBase<A> {
public:
ForceLink() {};
virtual ~ForceLink() {};
DescribedClass *create(A a) { return new T(a); }
};
}
#endif
// Local Variables:
// mode: c++
// c-file-style: "CLJ"
// End: