Project

General

Profile

Statistics
| Branch: | Revision:

root / include / simutil.h @ 0e7ff5c8

History | View | Annotate | Download (10.5 KB)

1 01873262 Georg Kunz
//==========================================================================
2
//  SIMUTIL.H - part of
3
//                     OMNeT++/OMNEST
4
//            Discrete System Simulation in C++
5
//
6
//
7
//  Utility functions
8
//
9
//==========================================================================
10
11
/*--------------------------------------------------------------*
12
  Copyright (C) 1992-2008 Andras Varga
13
  Copyright (C) 2006-2008 OpenSim Ltd.
14

15
  This file is distributed WITHOUT ANY WARRANTY. See the file
16
  `license' for details on this and other legal matters.
17
*--------------------------------------------------------------*/
18
19
#ifndef __SIMUTIL_H
20
#define __SIMUTIL_H
21
22
#include <string.h>  // for strlen, etc.
23
#include <stdarg.h>  // for va_list
24
#include <stdio.h>   // for sprintf
25
#include <stdlib.h>  // for gcvt
26
#include <typeinfo>  // for type_info
27
#include "simkerneldefs.h"
28
#include "platdep/platmisc.h" // for gcvt, etc
29
#include "errmsg.h"
30
31
NAMESPACE_BEGIN
32
33
// forward declarations
34
class cComponent;
35
36
// logically belongs to csimulation.h but must be here because of declaration order
37
enum {CTX_NONE, CTX_BUILD, CTX_INITIALIZE, CTX_EVENT, CTX_FINISH, CTX_CLEANUP};
38
39
40
#ifdef USE_DOUBLE_SIMTIME
41
/**
42
 * @ingroup Functions
43
 * @defgroup FunctionsSimtime Converting simulation time to and from string form
44
 */
45
//@{
46
47
/**
48
 * Convert a string to simtime_t. The string should have a format
49
 * similar to the one output by simtimeToStr() (like "1s 34ms").
50
 *
51
 * Throws an exception if the whole string cannot be interpreted as time.
52
 * Empty string (or only spaces+tabs) is also an error.
53
 */
54
SIM_API double strToSimtime(const char *str);
55
56
/**
57
 * Convert the beginning of a string to simtime_t. Similar to
58
 * strToSimtime(), only it processes the string as far as it
59
 * can be interpreted as simulation time. It sets the pointer
60
 * passed to the first character which cannot be interpreted
61
 * as part of the time string, or to the terminating zero.
62
 * Empty string is accepted as 0.0.
63
 *
64
 * Example: strToSimtime0("3s 600ms x") will return 3.6 and the
65
 * str pointer will point to the character 'x'.
66
 */
67
SIM_API double strToSimtime0(const char *&str);
68
69
/**
70
 * Converts simulation time (passed as simtime_t) into a
71
 * string like "0.0120000 (12ms)". If no destination pointer
72
 * is given, it will use a static buffer.
73
 */
74
SIM_API char *simtimeToStr(double t, char *dest=NULL);
75
76
/**
77
 * Converts simulation time (passed as simtime_t) into a short string
78
 * form like "12.37ms". If no destination pointer is given, it will use
79
 * a static buffer.
80
 */
81
SIM_API char *simtimeToStrShort(double t, char *buf=NULL);
82
//@}
83
#endif //USE_DOUBLE_SIMTIME
84
85
86
/**
87
 * Some of these functions are similar to \<string.h\> functions, with the
88
 * exception that they also accept NULL pointers as empty strings (""),
89
 * and use operator new instead of malloc(). It is recommended to use these
90
 * functions instead of the original \<string.h\> functions.
91
 *
92
 * @ingroup Functions
93
 * @defgroup FunctionsString String-related
94
 */
95
//@{
96
/**
97
 * Same as the standard strlen() function, except that does not crash
98
 * on NULL pointers but returns 0.
99
 */
100
inline int opp_strlen(const char *);
101
102
/**
103
 * Duplicates the string, using <tt>new char[]</tt>. For NULLs and empty
104
 * strings it returns NULL.
105
 */
106
inline char *opp_strdup(const char *);
107
108
/**
109
 * Same as the standard strcpy() function, except that NULL pointers
110
 * in the second argument are treated like pointers to a null string ("").
111
 */
112
inline char *opp_strcpy(char *,const char *);
113
114
/**
115
 * Same as the standard strcmp() function, except that NULL pointers
116
 * are treated exactly as empty strings ("").
117
 */
118
inline int opp_strcmp(const char *, const char *);
119
120
/**
121
 * Copies src string into desc, and if its length would exceed maxlen,
122
 * it is truncated with an ellipsis. For example, <tt>opp_strprettytrunc(buf,
123
 * "long-long",6)</tt> yields <tt>"lon..."</tt>.
124
 */
125
SIM_API char *opp_strprettytrunc(char *dest, const char *src, unsigned maxlen);
126
127
//@}
128
129
/**
130
 * DEPRECATED: Error handling functions.
131
 */
132
//@{
133
134
/**
135
 * DEPRECATED: use <tt>throw cRuntimeError(...)</tt> instead!
136
 *
137
 * Terminates the simulation with an error message.
138
 */
139
SIM_API void opp_error(OppErrorCode errcode,...);
140
141
/**
142
 * DEPRECATED: use <tt>throw cRuntimeError(...)</tt> instead!
143
 *
144
 * Same as function with the same name, but using custom message string.
145
 * To be called like printf().
146
 */
147
SIM_API void opp_error(const char *msg,...);
148
149
/**
150
 * This method can be used to report non-fatal discrepancies to the user.
151
 * Generally, warnings should VERY RARELY be used, if ever.
152
 * Argument list is like printf().
153
 *
154
 * Unlike in earlier versions, the user will NOT be offered the possibility
155
 * to stop the simulation. (In Cmdenv, warnings will be written
156
 * to the standard error, and in Tkenv it will probably pop up an
157
 * [OK] dialog.
158
 */
159
SIM_API void opp_warning(OppErrorCode errcode,...);
160
161
/**
162
 * This method can be used to report non-fatal discrepancies to the user.
163
 * Generally, warnings should VERY RARELY be used, if ever.
164
 * Argument list works like printf().
165
 *
166
 * Unlike in earlier versions, the user will NOT be offered the possibility
167
 * to stop the simulation. (In Cmdenv, warnings will be written
168
 * to the standard error, and in Tkenv it will probably pop up an
169
 * [OK] dialog.
170
 */
171
SIM_API void opp_warning(const char *msg,...);
172
173
/**
174
 * DEPRECATED.
175
 *
176
 * Print message and set error number.
177
 */
178
SIM_API void opp_terminate(OppErrorCode errcode,...);
179
180
/**
181
 * DEPRECATED.
182
 *
183
 * Same as function with the same name, but using custom message string.
184
 * To be called like printf().
185
 */
186
SIM_API void opp_terminate(const char *msg,...);
187
//@}
188
189
// INTERNAL: returns the name of a C++ type, correcting the quirks of various compilers.
190
SIM_API const char *opp_typename(const std::type_info& t);
191
192
193
/**
194
 * Denotes module class member function as callable from other modules.
195
 *
196
 * Usage: <tt>Enter_Method(fmt, arg1, arg2...);</tt>
197
 *
198
 * Example: <tt>Enter_Method("requestPacket(%d)",n);</tt>
199
 *
200
 * The macro should be put at the top of every module member function
201
 * that may be called from other modules. This macro arranges to
202
 * temporarily switch the context to the called module (the old context
203
 * will be restored automatically when the method returns),
204
 * and also lets the graphical user interface animate the method call.
205
 *
206
 * The argument(s) should specify the method name (and parameters) --
207
 * it will be used for the animation. The argument list works as in
208
 * <tt>printf()</tt>, so it is easy to include the actual parameter values.
209
 *
210
 * @see Enter_Method_Silent() macro
211
 */
212
#define Enter_Method cMethodCallContextSwitcher __ctx(this); __ctx.methodCall
213
214
/**
215
 * Denotes module class member function as callable from other modules.
216
 * This macro is similar to the Enter_Method() macro, only it does not animate
217
 * the call on the GUI; the call is still recorded into the the event log file.
218
 *
219
 * The macro may be called with or without arguments. When called with arguments,
220
 * they should be a printf-style format string, and parameters to be substituted
221
 * into it; the resulting string should contain the method name and the actual
222
 * arguments.
223
 *
224
 * Usage: <tt>Enter_Method_Silent();</tt>, <tt>Enter_Method_Silent(fmt, arg1, arg2...);</tt>
225
 *
226
 * Example: <tt>Enter_Method_Silent("getRouteFor(address=%d)",address);</tt>
227
 *
228
 * @see Enter_Method() macro
229
 */
230
#define Enter_Method_Silent cMethodCallContextSwitcher __ctx(this); __ctx.methodCallSilent
231
232
/**
233
 * The constructor switches the context to the given component, and the
234
 * destructor restores the original context.
235
 *
236
 * @see cSimulation::getContextModule(), cSimulation::setContextModule()
237
 * @ingroup Internals
238
 */
239
class SIM_API cContextSwitcher
240
{
241
  protected:
242
    cComponent *callerContext;
243
  public:
244
    /**
245
     * Switches context to the given module
246
     */
247
    cContextSwitcher(const cComponent *newContext);
248
249
    /**
250
     * Restores the original context
251
     */
252
    ~cContextSwitcher();
253
};
254
255
/**
256
 * Internal class. May only be used via the Enter_Method() and Enter_Method_Silent() macros!
257
 * @ingroup Internals
258
 */
259
class SIM_API cMethodCallContextSwitcher : public cContextSwitcher
260
{
261
  public:
262
    /**
263
     * Switches context to the given module
264
     */
265
    cMethodCallContextSwitcher(const cComponent *newContext);
266
267
    /**
268
     * Restores the original context
269
     */
270
    ~cMethodCallContextSwitcher();
271
272
    /**
273
     * Various ways to tell the user interface about the method call so that
274
     * the call can be animated, recorded into the event log, etc.
275
     */
276
    void methodCall(const char *methodFmt,...);
277
    void methodCallSilent(const char *methodFm,...);
278
    void methodCallSilent();
279
};
280
281
/**
282
 * The constructor switches the context type, and the destructor restores
283
 * the original context type.
284
 *
285
 * @see cSimulation::getContextModule(), cSimulation::setContextModule()
286
 * @ingroup Internals
287
 */
288
class SIM_API cContextTypeSwitcher
289
{
290
  private:
291
    int savedcontexttype;
292
293
  public:
294
    /**
295
     * Switches the context type (see CTX_xxx constants)
296
     */
297
    cContextTypeSwitcher(int contexttype);
298
299
    /**
300
     * Restores the original context type
301
     */
302
    ~cContextTypeSwitcher();
303
};
304
305
//==========================================================================
306
//=== Implementation of utility functions:
307
308
#ifndef _STRINGUTIL_H_   // avoid clash with similar defs in common/stringutil.h
309
310
inline char *opp_strcpy(char *s1,const char *s2)
311
{
312
    return strcpy(s1, s2 ? s2 : "");
313
}
314
315
inline int opp_strlen(const char *s)
316
{
317
    return s ? strlen(s) : 0;
318
}
319
320
inline char *opp_strdup(const char *s)
321
{
322
    if (!s || !s[0]) return NULL;
323
    char *p = new char[strlen(s)+1];
324
    strcpy(p,s);
325
    return p;
326
}
327
328
inline int opp_strcmp(const char *s1, const char *s2)
329
{
330
    if (s1)
331
        return s2 ? strcmp(s1,s2) : (*s1 ? 1 : 0);
332
    else
333
        return (s2 && *s2) ? -1 : 0;
334
}
335
336
#endif //_STRINGUTIL_H_
337
338
// internally used: appends [num] to the given string
339
inline void opp_appendindex(char *s, unsigned int i)
340
{
341
   while (*s) s++;
342
   *s++ = '[';
343
   if (i<10)
344
       {*s++ = '0'+i; *s++=']'; *s=0; return;}
345
   if (i<100)
346
       {*s++ = '0'+i/10; *s++='0'+i%10; *s++=']'; *s=0; return;}
347
   sprintf(s,"%d]",i);
348
}
349
350
inline long double_to_long(double d)
351
{
352
    // gcc feature: if double d=0xc0000000, (long)d yields 0x80000000 !
353
    // This only happens with long: unsigned long is OK.
354
    // This causes trouble if we in fact want to cast this long to unsigned long, see NED_expr_2.test.
355
    // Workaround follows. Note: even the ul variable is needed: when inlining it, gcc will do the wrong cast!
356
    long l = (long)d;
357
    unsigned long ul = (unsigned long)d;
358
    return d<0 ? l : ul;
359
}
360
361
// internal
362
inline std::string double_to_str(double t)
363
{
364
   char buf[32];
365
   return gcvt(t,16,buf);
366
}
367
368
369
NAMESPACE_END
370
371
372
#endif
373