| [0b990d] | 1 | // | 
|---|
|  | 2 | // class.h | 
|---|
|  | 3 | // | 
|---|
|  | 4 | // Copyright (C) 1996 Limit Point Systems, Inc. | 
|---|
|  | 5 | // | 
|---|
|  | 6 | // Author: Curtis Janssen <cljanss@limitpt.com> | 
|---|
|  | 7 | // Maintainer: LPS | 
|---|
|  | 8 | // | 
|---|
|  | 9 | // This file is part of the SC Toolkit. | 
|---|
|  | 10 | // | 
|---|
|  | 11 | // The SC Toolkit is free software; you can redistribute it and/or modify | 
|---|
|  | 12 | // it under the terms of the GNU Library General Public License as published by | 
|---|
|  | 13 | // the Free Software Foundation; either version 2, or (at your option) | 
|---|
|  | 14 | // any later version. | 
|---|
|  | 15 | // | 
|---|
|  | 16 | // The SC Toolkit is distributed in the hope that it will be useful, | 
|---|
|  | 17 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
|  | 18 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|---|
|  | 19 | // GNU Library General Public License for more details. | 
|---|
|  | 20 | // | 
|---|
|  | 21 | // You should have received a copy of the GNU Library General Public License | 
|---|
|  | 22 | // along with the SC Toolkit; see the file COPYING.LIB.  If not, write to | 
|---|
|  | 23 | // the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | 
|---|
|  | 24 | // | 
|---|
|  | 25 | // The U.S. Government is granted a limited license as per AL 91-7. | 
|---|
|  | 26 | // | 
|---|
|  | 27 |  | 
|---|
|  | 28 | #ifdef __GNUG__ | 
|---|
|  | 29 | #pragma interface | 
|---|
|  | 30 | #endif | 
|---|
|  | 31 |  | 
|---|
|  | 32 | #ifndef _util_class_class_h | 
|---|
|  | 33 | #define _util_class_class_h | 
|---|
|  | 34 |  | 
|---|
|  | 35 | #include <map> | 
|---|
|  | 36 | #include <set> | 
|---|
|  | 37 | #include <string> | 
|---|
|  | 38 |  | 
|---|
|  | 39 | #include <stdio.h> | 
|---|
|  | 40 | #include <string.h> | 
|---|
|  | 41 | #include <stdarg.h> | 
|---|
|  | 42 | #include <iostream> | 
|---|
|  | 43 | #include <iomanip> | 
|---|
|  | 44 | #include <typeinfo> | 
|---|
|  | 45 | #include <util/ref/ref.h> | 
|---|
|  | 46 | #include <util/misc/exenv.h> | 
|---|
|  | 47 |  | 
|---|
|  | 48 | namespace sc { | 
|---|
|  | 49 |  | 
|---|
|  | 50 | template <class T, class C> | 
|---|
|  | 51 | class DescribedMemberDatum { | 
|---|
|  | 52 | private: | 
|---|
|  | 53 | T C::*member_; | 
|---|
|  | 54 | public: | 
|---|
|  | 55 | DescribedMemberDatum(T C::*member): member_(member) {} | 
|---|
|  | 56 | //T &member(C *c) { return c->*member_; } | 
|---|
|  | 57 | }; | 
|---|
|  | 58 |  | 
|---|
|  | 59 | class DescribedClass; | 
|---|
|  | 60 | class ClassDesc; | 
|---|
|  | 61 | typedef ClassDesc* ClassDescP; | 
|---|
|  | 62 | typedef const ClassDesc* CClassDescP; | 
|---|
|  | 63 |  | 
|---|
|  | 64 | class ClassDesc; | 
|---|
|  | 65 |  | 
|---|
|  | 66 | /// Gives one parent class of a class. | 
|---|
|  | 67 | class ParentClass | 
|---|
|  | 68 | { | 
|---|
|  | 69 | public: | 
|---|
|  | 70 | enum Access { Private, Protected, Public }; | 
|---|
|  | 71 | private: | 
|---|
|  | 72 | Access _access; | 
|---|
|  | 73 | int _is_virtual; | 
|---|
|  | 74 | ClassDesc* _classdesc; | 
|---|
|  | 75 | public: | 
|---|
|  | 76 | ParentClass(ClassDesc*,Access access = Private,int is_virtual = 0); | 
|---|
|  | 77 | ParentClass(const ParentClass&); | 
|---|
|  | 78 | ~ParentClass(); | 
|---|
|  | 79 | int is_virtual() const; | 
|---|
|  | 80 | Access access() const { return _access; } | 
|---|
|  | 81 | const ClassDesc* classdesc() const; | 
|---|
|  | 82 | void change_classdesc(ClassDesc*n); | 
|---|
|  | 83 | }; | 
|---|
|  | 84 |  | 
|---|
|  | 85 | /// Gives a list of parent classes of a class. | 
|---|
|  | 86 | class ParentClasses | 
|---|
|  | 87 | { | 
|---|
|  | 88 | private: | 
|---|
|  | 89 | int _n; | 
|---|
|  | 90 | ParentClass** _classes; | 
|---|
|  | 91 | void add(ParentClass*); | 
|---|
|  | 92 | // do not allow copy constructor or assignment | 
|---|
|  | 93 | ParentClasses(const ParentClasses&); | 
|---|
|  | 94 | void operator=(const ParentClasses&); | 
|---|
|  | 95 | public: | 
|---|
|  | 96 | ParentClasses(); | 
|---|
|  | 97 | void init(const char*); | 
|---|
|  | 98 | ~ParentClasses(); | 
|---|
|  | 99 | ParentClass& parent(int i) { return *_classes[i]; } | 
|---|
|  | 100 | const ParentClass& parent(int i) const { return *_classes[i]; } | 
|---|
|  | 101 | ParentClass& operator[](int i) { return *_classes[i]; } | 
|---|
|  | 102 | const ParentClass& operator[](int i) const { return *_classes[i]; } | 
|---|
|  | 103 | int n() const { return _n; } | 
|---|
|  | 104 | void change_parent(ClassDesc*oldcd,ClassDesc*newcd); | 
|---|
|  | 105 | }; | 
|---|
|  | 106 |  | 
|---|
|  | 107 |  | 
|---|
|  | 108 | class KeyVal; | 
|---|
|  | 109 | class StateIn; | 
|---|
|  | 110 |  | 
|---|
|  | 111 | /** This is used to pass a function that make void constructor calls to the | 
|---|
|  | 112 | ClassDesc constructor. */ | 
|---|
|  | 113 | template <class T> | 
|---|
|  | 114 | DescribedClass* create() | 
|---|
|  | 115 | { | 
|---|
|  | 116 | return new T; | 
|---|
|  | 117 | } | 
|---|
|  | 118 |  | 
|---|
|  | 119 | /** This is used to pass a function that make KeyVal constructor calls to | 
|---|
|  | 120 | the ClassDesc constructor. */ | 
|---|
|  | 121 | template <class T> | 
|---|
|  | 122 | DescribedClass* create(const Ref<KeyVal>& keyval) | 
|---|
|  | 123 | { | 
|---|
|  | 124 | return new T(keyval); | 
|---|
|  | 125 | } | 
|---|
|  | 126 |  | 
|---|
|  | 127 | /** This is used to pass a function that make StateIn constructor calls to | 
|---|
|  | 128 | the ClassDesc constructor. */ | 
|---|
|  | 129 | template <class T> | 
|---|
|  | 130 | DescribedClass* create(StateIn& statein) | 
|---|
|  | 131 | { | 
|---|
|  | 132 | return new T(statein); | 
|---|
|  | 133 | } | 
|---|
|  | 134 |  | 
|---|
|  | 135 | class type_info_key { | 
|---|
|  | 136 | private: | 
|---|
|  | 137 | const std::type_info *ti_; | 
|---|
|  | 138 | public: | 
|---|
|  | 139 | type_info_key(): ti_(0) {} | 
|---|
|  | 140 | type_info_key(const std::type_info *ti): ti_(ti) {} | 
|---|
|  | 141 | type_info_key& operator=(const type_info_key&); | 
|---|
|  | 142 | int operator==(const type_info_key&) const; | 
|---|
|  | 143 | int operator<(const type_info_key&) const; | 
|---|
|  | 144 | int cmp(const type_info_key&) const; | 
|---|
|  | 145 | }; | 
|---|
|  | 146 |  | 
|---|
|  | 147 | /** This class is used to contain information about classes. | 
|---|
|  | 148 | Each DescribedClass type has a static ClassDesc | 
|---|
|  | 149 | member.  This member has lists of the parents, children | 
|---|
|  | 150 | and virtual parents for each class.  The | 
|---|
|  | 151 | ClassDesc class also has a static member that is | 
|---|
|  | 152 | a list of all described classes in the system.  These | 
|---|
|  | 153 | lists are constructed as the constructors for the static | 
|---|
|  | 154 | ClassDesc members for each class are called and | 
|---|
|  | 155 | are completed before main is entered.  See \ref class for | 
|---|
|  | 156 | more information. | 
|---|
|  | 157 | */ | 
|---|
|  | 158 | class ClassDesc: public Identity { | 
|---|
|  | 159 | friend class ParentClasses; | 
|---|
|  | 160 | private: | 
|---|
|  | 161 | static std::map<std::string,ClassDescP> *all_; | 
|---|
|  | 162 | static std::map<type_info_key,ClassDescP> *type_info_all_; | 
|---|
|  | 163 | static char * classlib_search_path_; | 
|---|
|  | 164 | static std::set<std::string> *unresolved_parents_; | 
|---|
|  | 165 |  | 
|---|
|  | 166 | char* classname_; | 
|---|
|  | 167 | int version_; | 
|---|
|  | 168 | ParentClasses parents_; | 
|---|
|  | 169 | std::set<std::string> *children_; | 
|---|
|  | 170 | DescribedClass* (*ctor_)(); | 
|---|
|  | 171 | DescribedClass* (*keyvalctor_)(const Ref<KeyVal>&); | 
|---|
|  | 172 | DescribedClass* (*stateinctor_)(StateIn&); | 
|---|
|  | 173 | const std::type_info *ti_; | 
|---|
|  | 174 |  | 
|---|
|  | 175 | void change_parent(ClassDesc*oldcd,ClassDesc*newcd); | 
|---|
|  | 176 |  | 
|---|
|  | 177 | // do not allow copy constructor or assignment | 
|---|
|  | 178 | ClassDesc(const ClassDesc&); | 
|---|
|  | 179 | void operator=(const ClassDesc&); | 
|---|
|  | 180 |  | 
|---|
|  | 181 | // this is used for temporary parent class descriptors | 
|---|
|  | 182 | ClassDesc(const char*); | 
|---|
|  | 183 | void init(const char*,int=1,const char* p=0, | 
|---|
|  | 184 | const std::type_info *ti=0, | 
|---|
|  | 185 | DescribedClass* (*ctor)()=0, | 
|---|
|  | 186 | DescribedClass* (*keyvalctor)(const Ref<KeyVal>&)=0, | 
|---|
|  | 187 | DescribedClass* (*stateinctor)(StateIn&)=0); | 
|---|
|  | 188 | public: | 
|---|
|  | 189 | ClassDesc(const std::type_info&, const char*,int=1,const char* p=0, | 
|---|
|  | 190 | DescribedClass* (*ctor)()=0, | 
|---|
|  | 191 | DescribedClass* (*keyvalctor)(const Ref<KeyVal>&)=0, | 
|---|
|  | 192 | DescribedClass* (*stateinctor)(StateIn&)=0); | 
|---|
|  | 193 | ~ClassDesc(); | 
|---|
|  | 194 |  | 
|---|
|  | 195 | static std::map<std::string,ClassDescP>& all(); | 
|---|
|  | 196 | const ParentClasses& parents() const { return parents_; } | 
|---|
|  | 197 |  | 
|---|
|  | 198 | /// Writes a list of all of the classes to ExEnv::out0(). | 
|---|
|  | 199 | static void list_all_classes(); | 
|---|
|  | 200 | /** Given the name of the class, return a pointer to the | 
|---|
|  | 201 | class descriptor. */ | 
|---|
|  | 202 | static ClassDesc* name_to_class_desc(const char*); | 
|---|
|  | 203 | /** Given a type_info object return a pointer to the ClassDesc. */ | 
|---|
|  | 204 | static ClassDesc *class_desc(const std::type_info &); | 
|---|
|  | 205 | /// Returns the name of the class. | 
|---|
|  | 206 | const char* name() const { return classname_; } | 
|---|
|  | 207 | /// Returns the version number of the class. | 
|---|
|  | 208 | int version() const { return version_; } | 
|---|
|  | 209 | /// This member has been replaced by create(). | 
|---|
|  | 210 | DescribedClass* create_described_class() const; | 
|---|
|  | 211 | /** Create an instance of DescribedClass with | 
|---|
|  | 212 | exact type equal to the class to which this class | 
|---|
|  | 213 | descriptor belongs.  The constructor which takes no | 
|---|
|  | 214 | arguments is used.  If this constructor doesn't exist or | 
|---|
|  | 215 | a static function that calls it with new wasn't | 
|---|
|  | 216 | given to this ClassDesc when it was created, then | 
|---|
|  | 217 | 0 will be returned. */ | 
|---|
|  | 218 | virtual DescribedClass* create() const; | 
|---|
|  | 219 | /** Create an instance of DescribedClass with exact type equal to the | 
|---|
|  | 220 | class to which this class descriptor belongs.  The KeyVal& | 
|---|
|  | 221 | constructor is used.  If this constructor doesn't exist or a static | 
|---|
|  | 222 | function that calls it with new wasn't passed to this ClassDesc, | 
|---|
|  | 223 | then 0 will be returned. */ | 
|---|
|  | 224 | virtual DescribedClass* create(const Ref<KeyVal>&) const; | 
|---|
|  | 225 | /** Create an instance of DescribedClass with exact type equal to the | 
|---|
|  | 226 | class to which this class descriptor belongs.  The StateIn& | 
|---|
|  | 227 | constructor is used.  If this constructor doesn't exist or a static | 
|---|
|  | 228 | function that calls it with new wasn't passed to this ClassDesc, | 
|---|
|  | 229 | then 0 will be returned. */ | 
|---|
|  | 230 | virtual DescribedClass* create(StateIn&) const; | 
|---|
|  | 231 |  | 
|---|
|  | 232 | /** Attempt to dynamically load the shared object file for | 
|---|
|  | 233 | classname. */ | 
|---|
|  | 234 | static int load_class(const char* classname); | 
|---|
|  | 235 | }; | 
|---|
|  | 236 |  | 
|---|
|  | 237 | /** Classes which need runtime information about themselves and their | 
|---|
|  | 238 | relationship to other classes can virtually inherit from | 
|---|
|  | 239 | DescribedClass.  This will provide the class with the ability to query | 
|---|
|  | 240 | its name and its version. | 
|---|
|  | 241 | Furthermore, the class's static ClassDesc can be obtained | 
|---|
|  | 242 | which permits several other operations.  See \ref class for | 
|---|
|  | 243 | more information. */ | 
|---|
|  | 244 | class DescribedClass : public RefCount { | 
|---|
|  | 245 | public: | 
|---|
|  | 246 | DescribedClass(); | 
|---|
|  | 247 | DescribedClass(const DescribedClass&); | 
|---|
|  | 248 | DescribedClass& operator=(const DescribedClass&); | 
|---|
|  | 249 | virtual ~DescribedClass(); | 
|---|
|  | 250 | /** This returns the unique pointer to the ClassDesc corresponding | 
|---|
|  | 251 | to the given type_info object.  Null is returned if it fails. */ | 
|---|
|  | 252 | ClassDesc* class_desc() const throw(); | 
|---|
|  | 253 | /// Return the name of the object's exact type. | 
|---|
|  | 254 | const char* class_name() const; | 
|---|
|  | 255 | /// Return the version of the class. | 
|---|
|  | 256 | int class_version() const; | 
|---|
|  | 257 | /// Print the object. | 
|---|
|  | 258 | virtual void print(std::ostream& = ExEnv::out0()) const; | 
|---|
|  | 259 | }; | 
|---|
|  | 260 |  | 
|---|
|  | 261 | /** Return the ClassDesc corresponding to template argument. */ | 
|---|
|  | 262 | template <class T> | 
|---|
|  | 263 | inline ClassDesc * | 
|---|
|  | 264 | class_desc() | 
|---|
|  | 265 | { | 
|---|
|  | 266 | return ClassDesc::class_desc(typeid(T)); | 
|---|
|  | 267 | } | 
|---|
|  | 268 |  | 
|---|
|  | 269 | /** Return the ClassDesc corresponding to the exact type for the | 
|---|
|  | 270 | argument. */ | 
|---|
|  | 271 | inline ClassDesc * | 
|---|
|  | 272 | class_desc(DescribedClass *d) | 
|---|
|  | 273 | { | 
|---|
|  | 274 | return ClassDesc::class_desc(typeid(*d)); | 
|---|
|  | 275 | } | 
|---|
|  | 276 |  | 
|---|
|  | 277 | /** Attempt to cast a DescribedClass pointer to a DescribedClass | 
|---|
|  | 278 | descendent.  It is an error for the result to be a null pointer. */ | 
|---|
|  | 279 | template<class T> | 
|---|
|  | 280 | inline T | 
|---|
|  | 281 | require_dynamic_cast(DescribedClass*p,const char * errmsg,...) | 
|---|
|  | 282 | { | 
|---|
|  | 283 | T t = dynamic_cast<T>(p); | 
|---|
|  | 284 | if (p && !t) { | 
|---|
|  | 285 | va_list args; | 
|---|
|  | 286 | va_start(args,errmsg); | 
|---|
|  | 287 | fprintf(stderr,"A required dynamic_cast failed in: "); | 
|---|
|  | 288 | vfprintf(stderr,errmsg,args); | 
|---|
|  | 289 | fprintf(stderr,"\nwanted type \"%s\" but got \"%s\"\n", | 
|---|
|  | 290 | typeid(T).name(),p->class_desc()->name()); | 
|---|
|  | 291 | fflush(stderr); | 
|---|
|  | 292 | va_end(args); | 
|---|
|  | 293 | abort(); | 
|---|
|  | 294 | } | 
|---|
|  | 295 | return t; | 
|---|
|  | 296 | } | 
|---|
|  | 297 |  | 
|---|
|  | 298 | /** Attempt to cast a const DescribedClass pointer to a DescribedClass | 
|---|
|  | 299 | descendent.  It is an error for the result to be a null pointer. */ | 
|---|
|  | 300 | template<class T> | 
|---|
|  | 301 | inline T | 
|---|
|  | 302 | require_dynamic_cast(const DescribedClass*p,const char * errmsg,...) | 
|---|
|  | 303 | { | 
|---|
|  | 304 | T t = dynamic_cast<T>(p); | 
|---|
|  | 305 | if (p && !t) { | 
|---|
|  | 306 | va_list args; | 
|---|
|  | 307 | va_start(args,errmsg); | 
|---|
|  | 308 | fprintf(stderr,"A required dynamic_cast failed in: "); | 
|---|
|  | 309 | vfprintf(stderr,errmsg,args); | 
|---|
|  | 310 | fprintf(stderr,"\nwanted type \"%s\" but got \"%s\"\n", | 
|---|
|  | 311 | typeid(T).name(),p->class_desc()->name()); | 
|---|
|  | 312 | fflush(stderr); | 
|---|
|  | 313 | va_end(args); | 
|---|
|  | 314 | abort(); | 
|---|
|  | 315 | } | 
|---|
|  | 316 | return t; | 
|---|
|  | 317 | } | 
|---|
|  | 318 |  | 
|---|
|  | 319 | /** This, together with ForceLink, is used to force code for particular | 
|---|
|  | 320 | classes to be linked into executables. */ | 
|---|
|  | 321 | template <class A> | 
|---|
|  | 322 | class ForceLinkBase { | 
|---|
|  | 323 | public: | 
|---|
|  | 324 | ForceLinkBase() {}; | 
|---|
|  | 325 | virtual ~ForceLinkBase() {}; | 
|---|
|  | 326 | virtual DescribedClass *create(A) = 0; | 
|---|
|  | 327 | }; | 
|---|
|  | 328 |  | 
|---|
|  | 329 | /** This, together with ForceLinkBase, is used to force code for particular | 
|---|
|  | 330 | classes to be linked into executables.  Objects are created from input and | 
|---|
|  | 331 | checkpoint files by using class name lookup to find that class's ClassDesc | 
|---|
|  | 332 | object.  The ClassDesc object has members that can create the class. | 
|---|
|  | 333 | Unfortunately, linking in a library doesn't cause code for the the | 
|---|
|  | 334 | ClassDesc, and thus the class itself, to be linked.  ForceLink objects are | 
|---|
|  | 335 | created in linkage.h files for each library.  The code containing the main | 
|---|
|  | 336 | routine for an executable can include these linkage files to force code for | 
|---|
|  | 337 | that library's classes to be linked. */ | 
|---|
|  | 338 | template <class T, class A = const Ref<KeyVal> &> | 
|---|
|  | 339 | class ForceLink: public ForceLinkBase<A> { | 
|---|
|  | 340 | public: | 
|---|
|  | 341 | ForceLink() {}; | 
|---|
|  | 342 | virtual ~ForceLink() {}; | 
|---|
|  | 343 | DescribedClass *create(A a) { return new T(a); } | 
|---|
|  | 344 | }; | 
|---|
|  | 345 |  | 
|---|
|  | 346 | } | 
|---|
|  | 347 |  | 
|---|
|  | 348 | #endif | 
|---|
|  | 349 |  | 
|---|
|  | 350 | // Local Variables: | 
|---|
|  | 351 | // mode: c++ | 
|---|
|  | 352 | // c-file-style: "CLJ" | 
|---|
|  | 353 | // End: | 
|---|