[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:
|
---|