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