00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef __GNUG__
00029 #pragma interface
00030 #endif
00031
00032 #ifndef _util_class_class_h
00033 #define _util_class_class_h
00034
00035 #include <map>
00036 #include <set>
00037 #include <string>
00038
00039 #include <stdio.h>
00040 #include <string.h>
00041 #include <stdarg.h>
00042 #include <iostream>
00043 #include <iomanip>
00044 #include <typeinfo>
00045 #include <util/ref/ref.h>
00046 #include <util/misc/exenv.h>
00047
00048 namespace sc {
00049
00050 template <class T, class C>
00051 class DescribedMemberDatum {
00052 private:
00053 T C::*member_;
00054 public:
00055 DescribedMemberDatum(T C::*member): member_(member) {}
00056
00057 };
00058
00059 class DescribedClass;
00060 class ClassDesc;
00061 typedef ClassDesc* ClassDescP;
00062 typedef const ClassDesc* CClassDescP;
00063
00064 class ClassDesc;
00065
00067 class ParentClass
00068 {
00069 public:
00070 enum Access { Private, Protected, Public };
00071 private:
00072 Access _access;
00073 int _is_virtual;
00074 ClassDesc* _classdesc;
00075 public:
00076 ParentClass(ClassDesc*,Access access = Private,int is_virtual = 0);
00077 ParentClass(const ParentClass&);
00078 ~ParentClass();
00079 int is_virtual() const;
00080 Access access() const { return _access; }
00081 const ClassDesc* classdesc() const;
00082 void change_classdesc(ClassDesc*n);
00083 };
00084
00086 class ParentClasses
00087 {
00088 private:
00089 int _n;
00090 ParentClass** _classes;
00091 void add(ParentClass*);
00092
00093 ParentClasses(const ParentClasses&);
00094 void operator=(const ParentClasses&);
00095 public:
00096 ParentClasses();
00097 void init(const char*);
00098 ~ParentClasses();
00099 ParentClass& parent(int i) { return *_classes[i]; }
00100 const ParentClass& parent(int i) const { return *_classes[i]; }
00101 ParentClass& operator[](int i) { return *_classes[i]; }
00102 const ParentClass& operator[](int i) const { return *_classes[i]; }
00103 int n() const { return _n; }
00104 void change_parent(ClassDesc*oldcd,ClassDesc*newcd);
00105 };
00106
00107
00108 class KeyVal;
00109 class StateIn;
00110
00113 template <class T>
00114 DescribedClass* create()
00115 {
00116 return new T;
00117 }
00118
00121 template <class T>
00122 DescribedClass* create(const Ref<KeyVal>& keyval)
00123 {
00124 return new T(keyval);
00125 }
00126
00129 template <class T>
00130 DescribedClass* create(StateIn& statein)
00131 {
00132 return new T(statein);
00133 }
00134
00135 class type_info_key {
00136 private:
00137 const std::type_info *ti_;
00138 public:
00139 type_info_key(): ti_(0) {}
00140 type_info_key(const std::type_info *ti): ti_(ti) {}
00141 type_info_key& operator=(const type_info_key&);
00142 int operator==(const type_info_key&) const;
00143 int operator<(const type_info_key&) const;
00144 int cmp(const type_info_key&) const;
00145 };
00146
00158 class ClassDesc: public Identity {
00159 friend class ParentClasses;
00160 private:
00161 static std::map<std::string,ClassDescP> *all_;
00162 static std::map<type_info_key,ClassDescP> *type_info_all_;
00163 static char * classlib_search_path_;
00164 static std::set<std::string> *unresolved_parents_;
00165
00166 char* classname_;
00167 int version_;
00168 ParentClasses parents_;
00169 std::set<std::string> *children_;
00170 DescribedClass* (*ctor_)();
00171 DescribedClass* (*keyvalctor_)(const Ref<KeyVal>&);
00172 DescribedClass* (*stateinctor_)(StateIn&);
00173
00174 void change_parent(ClassDesc*oldcd,ClassDesc*newcd);
00175
00176
00177 ClassDesc(const ClassDesc&);
00178 void operator=(const ClassDesc&);
00179
00180
00181 ClassDesc(const char*);
00182 void init(const char*,int=1,const char* p=0,
00183 DescribedClass* (*ctor)()=0,
00184 DescribedClass* (*keyvalctor)(const Ref<KeyVal>&)=0,
00185 DescribedClass* (*stateinctor)(StateIn&)=0);
00186 public:
00187 ClassDesc(const std::type_info&, const char*,int=1,const char* p=0,
00188 DescribedClass* (*ctor)()=0,
00189 DescribedClass* (*keyvalctor)(const Ref<KeyVal>&)=0,
00190 DescribedClass* (*stateinctor)(StateIn&)=0);
00191 ~ClassDesc();
00192
00193 static std::map<std::string,ClassDescP>& all();
00194 const ParentClasses& parents() const { return parents_; }
00195
00197 static void list_all_classes();
00200 static ClassDesc* name_to_class_desc(const char*);
00202 static ClassDesc *class_desc(const std::type_info &);
00204 const char* name() const { return classname_; }
00206 int version() const { return version_; }
00208 DescribedClass* create_described_class() const;
00216 virtual DescribedClass* create() const;
00222 virtual DescribedClass* create(const Ref<KeyVal>&) const;
00228 virtual DescribedClass* create(StateIn&) const;
00229
00232 static int load_class(const char* classname);
00233 };
00234
00242 class DescribedClass : public RefCount {
00243 public:
00244 DescribedClass();
00245 DescribedClass(const DescribedClass&);
00246 DescribedClass& operator=(const DescribedClass&);
00247 virtual ~DescribedClass();
00250 ClassDesc* class_desc() const;
00252 const char* class_name() const;
00254 int class_version() const;
00256 virtual void print(std::ostream& = ExEnv::out0()) const;
00257 };
00258
00260 template <class T>
00261 inline ClassDesc *
00262 class_desc()
00263 {
00264 return ClassDesc::class_desc(typeid(T));
00265 }
00266
00269 inline ClassDesc *
00270 class_desc(DescribedClass *d)
00271 {
00272 return ClassDesc::class_desc(typeid(*d));
00273 }
00274
00277 template<class T>
00278 inline T
00279 require_dynamic_cast(DescribedClass*p,const char * errmsg,...)
00280 {
00281 T t = dynamic_cast<T>(p);
00282 if (p && !t) {
00283 va_list args;
00284 va_start(args,errmsg);
00285 fprintf(stderr,"A required dynamic_cast failed in: ");
00286 vfprintf(stderr,errmsg,args);
00287 fprintf(stderr,"\nwanted type \"%s\" but got \"%s\"\n",
00288 typeid(T).name(),p->class_desc()->name());
00289 fflush(stderr);
00290 va_end(args);
00291 abort();
00292 }
00293 return t;
00294 }
00295
00298 template<class T>
00299 inline T
00300 require_dynamic_cast(const DescribedClass*p,const char * errmsg,...)
00301 {
00302 T t = dynamic_cast<T>(p);
00303 if (p && !t) {
00304 va_list args;
00305 va_start(args,errmsg);
00306 fprintf(stderr,"A required dynamic_cast failed in: ");
00307 vfprintf(stderr,errmsg,args);
00308 fprintf(stderr,"\nwanted type \"%s\" but got \"%s\"\n",
00309 typeid(T).name(),p->class_desc()->name());
00310 fflush(stderr);
00311 va_end(args);
00312 abort();
00313 }
00314 return t;
00315 }
00316
00319 template <class A>
00320 class ForceLinkBase {
00321 public:
00322 virtual ~ForceLinkBase() {};
00323 virtual DescribedClass *create(A) = 0;
00324 };
00325
00335 template <class T, class A = const Ref<KeyVal> &>
00336 class ForceLink: public ForceLinkBase<A> {
00337 public:
00338 DescribedClass *create(A a) { return new T(a); }
00339 };
00340
00341 }
00342
00343 #endif
00344
00345
00346
00347
00348