root / include / cwatch.h @ master
History | View | Annotate | Download (9.95 KB)
1 | 01873262 | Georg Kunz | //==========================================================================
|
---|---|---|---|
2 | // CWATCH.H - part of
|
||
3 | // OMNeT++/OMNEST
|
||
4 | // Discrete System Simulation in C++
|
||
5 | //
|
||
6 | //
|
||
7 | // Declaration of the following classes:
|
||
8 | // cWatchBase etc: make primitive types, structs etc inspectable
|
||
9 | //
|
||
10 | //==========================================================================
|
||
11 | |||
12 | /*--------------------------------------------------------------*
|
||
13 | Copyright (C) 1992-2008 Andras Varga
|
||
14 | Copyright (C) 2006-2008 OpenSim Ltd.
|
||
15 | |||
16 | This file is distributed WITHOUT ANY WARRANTY. See the file
|
||
17 | `license' for details on this and other legal matters.
|
||
18 | *--------------------------------------------------------------*/
|
||
19 | |||
20 | #ifndef __CWATCH_H
|
||
21 | #define __CWATCH_H
|
||
22 | |||
23 | #include <iostream> |
||
24 | #include <sstream> |
||
25 | #include "cownedobject.h" |
||
26 | |||
27 | NAMESPACE_BEGIN |
||
28 | |||
29 | |||
30 | /**
|
||
31 | * Utility class to make primitive types and non-cOwnedObject objects
|
||
32 | * inspectable in Tkenv. To be used only via the WATCH, WATCH_PTR,
|
||
33 | * WATCH_OBJ, WATCH_VECTOR etc macros.
|
||
34 | *
|
||
35 | * @ingroup Internals
|
||
36 | */
|
||
37 | class SIM_API cWatchBase : public cNoncopyableOwnedObject |
||
38 | { |
||
39 | public:
|
||
40 | /** @name Constructors, destructor, assignment */
|
||
41 | //@{
|
||
42 | /**
|
||
43 | * Initialize the shell to hold the given variable.
|
||
44 | */
|
||
45 | cWatchBase(const char *name) : cNoncopyableOwnedObject(name) {} |
||
46 | //@}
|
||
47 | |||
48 | /** @name New methods */
|
||
49 | //@{
|
||
50 | /**
|
||
51 | * Tells if changing the variable's value via assign() is supported.
|
||
52 | */
|
||
53 | virtual bool supportsAssignment() const = 0; |
||
54 | |||
55 | /**
|
||
56 | * Changes the watched variable's value. May only be called if
|
||
57 | * supportsAssignment() returns true.
|
||
58 | */
|
||
59 | virtual void assign(const char *s) {} |
||
60 | //@}
|
||
61 | }; |
||
62 | |||
63 | |||
64 | /**
|
||
65 | * Template Watch class, for any type that supports operator<<.
|
||
66 | * @ingroup Internals
|
||
67 | */
|
||
68 | template<typename T> |
||
69 | class cGenericReadonlyWatch : public cWatchBase |
||
70 | { |
||
71 | private:
|
||
72 | const T& r;
|
||
73 | public:
|
||
74 | cGenericReadonlyWatch(const char *name, const T& x) : cWatchBase(name), r(x) {} |
||
75 | virtual const char *getClassName() const {return opp_typename(typeid(T));} |
||
76 | virtual bool supportsAssignment() const {return false;} |
||
77 | virtual std::string info() const
|
||
78 | { |
||
79 | std::stringstream out; |
||
80 | out << r; |
||
81 | return out.str();
|
||
82 | } |
||
83 | }; |
||
84 | |||
85 | |||
86 | /**
|
||
87 | * Template Watch class, for any type that supports operator<<,
|
||
88 | * and operator>> for assignment.
|
||
89 | * @ingroup Internals
|
||
90 | */
|
||
91 | template<typename T> |
||
92 | class cGenericAssignableWatch : public cWatchBase |
||
93 | { |
||
94 | private:
|
||
95 | T& r; |
||
96 | public:
|
||
97 | cGenericAssignableWatch(const char *name, T& x) : cWatchBase(name), r(x) {} |
||
98 | virtual const char *getClassName() const {return opp_typename(typeid(T));} |
||
99 | virtual bool supportsAssignment() const {return true;} |
||
100 | virtual std::string info() const
|
||
101 | { |
||
102 | std::stringstream out; |
||
103 | out << r; |
||
104 | return out.str();
|
||
105 | } |
||
106 | virtual void assign(const char *s) |
||
107 | { |
||
108 | std::stringstream in(s); |
||
109 | in >> r; |
||
110 | } |
||
111 | }; |
||
112 | |||
113 | /**
|
||
114 | * Watch class, specifically for bool.
|
||
115 | * @ingroup Internals
|
||
116 | */
|
||
117 | class SIM_API cWatch_bool : public cWatchBase |
||
118 | { |
||
119 | private:
|
||
120 | bool& r;
|
||
121 | public:
|
||
122 | cWatch_bool(const char *name, bool& x) : cWatchBase(name), r(x) {} |
||
123 | virtual const char *getClassName() const {return "bool";} |
||
124 | virtual bool supportsAssignment() const {return true;} |
||
125 | virtual std::string info() const
|
||
126 | { |
||
127 | return r ? "true" : "false"; |
||
128 | } |
||
129 | virtual void assign(const char *s) |
||
130 | { |
||
131 | r = *s!='0' && *s!='n' && *s!='N' && *s!='f' && *s!='F'; |
||
132 | } |
||
133 | }; |
||
134 | |||
135 | /**
|
||
136 | * Watch class, specifically for char.
|
||
137 | * @ingroup Internals
|
||
138 | */
|
||
139 | class SIM_API cWatch_char : public cWatchBase |
||
140 | { |
||
141 | private:
|
||
142 | char& r;
|
||
143 | public:
|
||
144 | cWatch_char(const char *name, char& x) : cWatchBase(name), r(x) {} |
||
145 | virtual const char *getClassName() const {return "char";} |
||
146 | virtual bool supportsAssignment() const {return true;} |
||
147 | virtual std::string info() const
|
||
148 | { |
||
149 | std::stringstream out; |
||
150 | out << "'" << ((unsigned char)r<32 ? ' ' : r) << "' (" << int(r) << ")"; |
||
151 | return out.str();
|
||
152 | } |
||
153 | virtual void assign(const char *s) |
||
154 | { |
||
155 | if (s[0]=='\'') |
||
156 | r = s[1];
|
||
157 | else
|
||
158 | r = atoi(s); |
||
159 | } |
||
160 | }; |
||
161 | |||
162 | /**
|
||
163 | * Watch class, specifically for unsigned char.
|
||
164 | * @ingroup Internals
|
||
165 | */
|
||
166 | class SIM_API cWatch_uchar : public cWatchBase |
||
167 | { |
||
168 | private:
|
||
169 | unsigned char& r; |
||
170 | public:
|
||
171 | cWatch_uchar(const char *name, unsigned char& x) : cWatchBase(name), r(x) {} |
||
172 | virtual const char *getClassName() const {return "unsigned char";} |
||
173 | virtual bool supportsAssignment() const {return true;} |
||
174 | virtual std::string info() const
|
||
175 | { |
||
176 | std::stringstream out; |
||
177 | out << "'" << (char)(r<' ' ? ' ' : r) << "' (" << int(r) << ")"; |
||
178 | return out.str();
|
||
179 | } |
||
180 | virtual void assign(const char *s) |
||
181 | { |
||
182 | if (s[0]=='\'') |
||
183 | r = s[1];
|
||
184 | else
|
||
185 | r = atoi(s); |
||
186 | } |
||
187 | }; |
||
188 | |||
189 | /**
|
||
190 | * Watch class, specifically for std::string.
|
||
191 | * @ingroup Internals
|
||
192 | */
|
||
193 | class SIM_API cWatch_stdstring : public cWatchBase |
||
194 | { |
||
195 | private:
|
||
196 | std::string& r; |
||
197 | public:
|
||
198 | cWatch_stdstring(const char *name, std::string& x) : cWatchBase(name), r(x) {} |
||
199 | virtual const char *getClassName() const {return "std::string";} |
||
200 | virtual bool supportsAssignment() const {return true;} |
||
201 | virtual std::string info() const;
|
||
202 | virtual void assign(const char *s); |
||
203 | }; |
||
204 | |||
205 | /**
|
||
206 | * Watch class, specifically for objects subclassed from cObject.
|
||
207 | * @ingroup Internals
|
||
208 | */
|
||
209 | class SIM_API cWatch_cObject : public cWatchBase |
||
210 | { |
||
211 | private:
|
||
212 | cObject& r; |
||
213 | public:
|
||
214 | cWatch_cObject(const char *name, cObject& ref) : cWatchBase(name), r(ref) {} |
||
215 | virtual const char *getClassName() const {return r.getClassName();} |
||
216 | virtual std::string info() const {return r.info();} |
||
217 | virtual bool supportsAssignment() const {return false;} |
||
218 | virtual cClassDescriptor *getDescriptor() {return r.getDescriptor();}
|
||
219 | }; |
||
220 | |||
221 | /**
|
||
222 | * Watch class, specifically for pointers to objects subclassed from cObject.
|
||
223 | * @ingroup Internals
|
||
224 | */
|
||
225 | class SIM_API cWatch_cObjectPtr : public cWatchBase |
||
226 | { |
||
227 | private:
|
||
228 | cObject *&rp; |
||
229 | public:
|
||
230 | cWatch_cObjectPtr(const char *name, cObject *&ptr) : cWatchBase(name), rp(ptr) {} |
||
231 | virtual const char *getClassName() const {return rp? rp->getClassName() : "n/a";} |
||
232 | virtual std::string info() const {return rp ? rp->info() : "<null>";} |
||
233 | virtual bool supportsAssignment() const {return false;} |
||
234 | virtual cClassDescriptor *getDescriptor() {return rp ? rp->getDescriptor() : NULL;} |
||
235 | }; |
||
236 | |||
237 | |||
238 | inline cWatchBase *createWatch(const char *varname, short& d) { |
||
239 | return new cGenericAssignableWatch<short>(varname, d); |
||
240 | } |
||
241 | |||
242 | inline cWatchBase *createWatch(const char *varname, unsigned short& d) { |
||
243 | return new cGenericAssignableWatch<unsigned short>(varname, d); |
||
244 | } |
||
245 | |||
246 | inline cWatchBase *createWatch(const char *varname, int& d) { |
||
247 | return new cGenericAssignableWatch<int>(varname, d); |
||
248 | } |
||
249 | |||
250 | inline cWatchBase *createWatch(const char *varname, unsigned int& d) { |
||
251 | return new cGenericAssignableWatch<unsigned int>(varname, d); |
||
252 | } |
||
253 | |||
254 | inline cWatchBase *createWatch(const char *varname, long& d) { |
||
255 | return new cGenericAssignableWatch<long>(varname, d); |
||
256 | } |
||
257 | |||
258 | inline cWatchBase *createWatch(const char *varname, unsigned long& d) { |
||
259 | return new cGenericAssignableWatch<unsigned long>(varname, d); |
||
260 | } |
||
261 | |||
262 | inline cWatchBase *createWatch(const char *varname, float& d) { |
||
263 | return new cGenericAssignableWatch<float>(varname, d); |
||
264 | } |
||
265 | |||
266 | inline cWatchBase *createWatch(const char *varname, double& d) { |
||
267 | return new cGenericAssignableWatch<double>(varname, d); |
||
268 | } |
||
269 | |||
270 | inline cWatchBase *createWatch(const char *varname, bool& d) { |
||
271 | return new cWatch_bool(varname, d);
|
||
272 | } |
||
273 | |||
274 | inline cWatchBase *createWatch(const char *varname, char& d) { |
||
275 | return new cWatch_char(varname, d);
|
||
276 | } |
||
277 | |||
278 | inline cWatchBase *createWatch(const char *varname, unsigned char& d) { |
||
279 | return new cWatch_uchar(varname, d);
|
||
280 | } |
||
281 | |||
282 | inline cWatchBase *createWatch(const char *varname, signed char& d) { |
||
283 | return new cWatch_char(varname, *(char *)&d); |
||
284 | } |
||
285 | |||
286 | inline cWatchBase *createWatch(const char *varname, std::string& v) { |
||
287 | return new cWatch_stdstring(varname, v);
|
||
288 | } |
||
289 | |||
290 | // this is the fallback, if none of the above match
|
||
291 | template<typename T> |
||
292 | inline cWatchBase *createWatch(const char *varname, T& d) { |
||
293 | return new cGenericReadonlyWatch<T>(varname, d);
|
||
294 | } |
||
295 | |||
296 | // to be used if T also has op>> defined
|
||
297 | template<typename T> |
||
298 | inline cWatchBase *createWatch_genericAssignable(const char *varname, T& d) { |
||
299 | return new cGenericAssignableWatch<T>(varname, d);
|
||
300 | } |
||
301 | |||
302 | // for objects
|
||
303 | inline cWatchBase *createWatch_cObject(const char *varname, cObject& obj) { |
||
304 | return new cWatch_cObject(varname, obj);
|
||
305 | } |
||
306 | |||
307 | // for pointers to objects.
|
||
308 | // NOTE: this is a bit tricky. C++ thinks that (cObject*&) and
|
||
309 | // (SomeDerivedType*&) are unrelated, so we have to force the cast
|
||
310 | // in the WATCH_PTR() macro. But to stay type-safe, we include a 3rd arg
|
||
311 | // of type cObject*: the compiler has to be able to cast that
|
||
312 | // implicitly from SomeDerivedType* -- this way we do not accept pointers
|
||
313 | // that are REALLY unrelated.
|
||
314 | inline cWatchBase *createWatch_cObjectPtr(const char *varname, cObject *&refp, cObject *p) { |
||
315 | ASSERT(refp==p); |
||
316 | return new cWatch_cObjectPtr(varname, refp);
|
||
317 | } |
||
318 | |||
319 | |||
320 | /**
|
||
321 | * @ingroup Macros
|
||
322 | * @defgroup MacrosWatch WATCH macros
|
||
323 | */
|
||
324 | //@{
|
||
325 | |||
326 | /**
|
||
327 | * Makes primitive types and types with operator<< inspectable in Tkenv.
|
||
328 | * See also WATCH_RW(), WATCH_PTR(), WATCH_OBJ(), WATCH_VECTOR(),
|
||
329 | * WATCH_PTRVECTOR(), etc. macros.
|
||
330 | *
|
||
331 | * @hideinitializer
|
||
332 | */
|
||
333 | #define WATCH(variable) createWatch(#variable,(variable)) |
||
334 | |||
335 | /**
|
||
336 | * Makes types with operator\<\< and operator\>\> inspectable in Tkenv.
|
||
337 | * operator\>\> is used to enable changing the variable's value interactively.
|
||
338 | *
|
||
339 | * @hideinitializer
|
||
340 | */
|
||
341 | #define WATCH_RW(variable) createWatch_genericAssignable(#variable,(variable)) |
||
342 | |||
343 | /**
|
||
344 | * Makes classes derived from cObject inspectable in Tkenv.
|
||
345 | * See also WATCH_PTR().
|
||
346 | *
|
||
347 | * @hideinitializer
|
||
348 | */
|
||
349 | #define WATCH_OBJ(variable) createWatch_cObject(#variable,(variable)) |
||
350 | |||
351 | /**
|
||
352 | * Makes pointers to objects derived from cObject inspectable in Tkenv.
|
||
353 | * See also WATCH_OBJ().
|
||
354 | *
|
||
355 | * @hideinitializer
|
||
356 | */
|
||
357 | #define WATCH_PTR(variable) createWatch_cObjectPtr(#variable,(cObject*&)(variable),(variable)) |
||
358 | //@}
|
||
359 | |||
360 | NAMESPACE_END |
||
361 | |||
362 | |||
363 | #endif
|
||
364 |