Statistics
| Branch: | Revision:

root / src / sim / cclassdescriptor.cc @ e26d3d25

History | View | Annotate | Download (6.55 KB)

1 01873262 Georg Kunz
//==========================================================================
2
//  CCLASSDESCRIPTOR.CC - part of
3
//                     OMNeT++/OMNEST
4
//            Discrete System Simulation in C++
5
//
6
//
7
//  Declaration of the following classes:
8
//    cClassDescriptor : meta-info about structures
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
#include <stdio.h>   // sprintf
21
#include <stdlib.h>  // atol
22
#include <string.h>
23
#include "cclassdescriptor.h"
24
#include "carray.h"
25
#include "cenum.h"
26
#include "simutil.h"
27
#include "opp_ctype.h"
28
#include "cobjectfactory.h"  // createOne()
29
30
USING_NAMESPACE
31
32
33
#define LL  INT64_PRINTF_FORMAT  /* abbreviation */
34
35
std::string cClassDescriptor::long2string(long l)
36
{
37
    char buf[32];
38
    sprintf(buf, "%ld", l);
39
    return buf;
40
}
41
42
long cClassDescriptor::string2long(const char *s)
43
{
44
    return strtol(s, NULL, 10);
45
}
46
47
std::string cClassDescriptor::ulong2string(unsigned long l)
48
{
49
    char buf[32];
50
    sprintf(buf, "%lu", l);
51
    return buf;
52
}
53
54
unsigned long cClassDescriptor::string2ulong(const char *s)
55
{
56
    return strtoul(s, NULL, 10);
57
}
58
59
std::string cClassDescriptor::int642string(int64 l)
60
{
61
    char buf[32];
62
    sprintf(buf, "%"LL"d", l);
63
    return buf;
64
}
65
66
int64 cClassDescriptor::string2int64(const char *s)
67
{
68
    return strtoll(s, NULL, 10);
69
}
70
71
std::string cClassDescriptor::uint642string(uint64 l)
72
{
73
    char buf[32];
74
    sprintf(buf, "%"LL"u", l);
75
    return buf;
76
}
77
78
uint64 cClassDescriptor::string2uint64(const char *s)
79
{
80
    return strtoull(s, NULL, 10);
81
}
82
83
std::string cClassDescriptor::bool2string(bool b)
84
{
85
    return b ? "true" : "false";
86
}
87
88
bool cClassDescriptor::string2bool(const char *s)
89
{
90
    return s[0]=='t' || s[0]=='T' || s[0]=='y' || s[0]=='Y' || s[0]=='1';
91
}
92
93
94
std::string cClassDescriptor::double2string(double d)
95
{
96
    char buf[32];
97
    sprintf(buf, "%f", d);
98
    return buf;
99
}
100
101
102
double cClassDescriptor::string2double(const char *s)
103
{
104
    return atof(s);
105
}
106
107
std::string cClassDescriptor::enum2string(long e, const char *enumname)
108
{
109
    char buf[32];
110
    sprintf(buf, "%ld", e);
111
112
    cEnum *enump = cEnum::find(enumname);
113
    if (!enump)
114
        return buf; // this enum type is not registered
115
116
    const char *name = enump->getStringFor(e);
117
    if (!name)
118
        return strcat(buf, " (unknown)");  // no string for this numeric value
119
120
    return std::string(buf) + " (" + name + ")";
121
}
122
123
long cClassDescriptor::string2enum(const char *s, const char *enumname)
124
{
125
    // return zero if string cannot be parsed
126
127
    // try to interpret it as numeric value
128
    if (opp_isdigit(*s))
129
        return atol(s);
130
131
    // try to recognize string
132
    cEnum *enump = cEnum::find(enumname);
133
    if (!enump)
134
        return 0; // this enum type is not registered
135
136
    // TBD should strip possible spaces, parens etc.
137
    return enump->lookup(s,0);
138
}
139
140
141
//-----------------------------------------------------------
142
143
cClassDescriptor::cClassDescriptor(const char *classname, const char *_baseclassname) :
144
cNoncopyableOwnedObject(classname, false)
145
{
146
    baseclassname = _baseclassname ? _baseclassname : "";
147
    baseclassdesc = NULL;
148
    inheritancechainlength = 1;
149
    extendscobject = -1;
150
}
151
152
cClassDescriptor::~cClassDescriptor()
153
{
154
}
155
156
cClassDescriptor *cClassDescriptor::getBaseClassDescriptor() const
157
{
158
    if (!baseclassdesc && !baseclassname.empty())
159
    {
160
        cClassDescriptor *this_ = const_cast<cClassDescriptor*>(this);
161
        this_->baseclassdesc = getDescriptorFor(baseclassname.c_str());
162
        if (baseclassdesc)
163
            this_->inheritancechainlength = 1 + baseclassdesc->getInheritanceChainLength();
164
    }
165
    return baseclassdesc;
166
}
167
168
bool cClassDescriptor::extendsCObject() const
169
{
170
    if (extendscobject == -1) {
171
        cClassDescriptor *this_ = const_cast<cClassDescriptor*>(this);
172
        this_->extendscobject = false;
173
        const cClassDescriptor *current = this;
174
175
        while (current) {
176
            if (!strcmp("cObject", current->getName())) {
177
                this_->extendscobject = true;
178
                break;
179
            }
180
            else {
181
                current = current->getBaseClassDescriptor();
182
            }
183
        }
184
    }
185
    return extendscobject;
186
}
187
188
int cClassDescriptor::getInheritanceChainLength() const
189
{
190
    getBaseClassDescriptor(); // force resolution of inheritance
191
    return inheritancechainlength;
192
}
193
194
const char *cClassDescriptor::getFieldDeclaredOn(void *object, int field) const
195
{
196
    cClassDescriptor *base = getBaseClassDescriptor();
197
    if (base && field < base->getFieldCount(object))
198
        return base->getFieldDeclaredOn(object, field);
199
    return getName();
200
}
201
202
cClassDescriptor *cClassDescriptor::getDescriptorFor(const char *classname)
203
{
204
    return dynamic_cast<cClassDescriptor *>(classDescriptors.getInstance()->lookup(classname));
205
}
206
207
cClassDescriptor *cClassDescriptor::getDescriptorFor(cObject *object)
208
{
209
    // find descriptor by class name
210
    cClassDescriptor *desc = cClassDescriptor::getDescriptorFor(object->getClassName());
211
    if (desc)
212
        return desc;
213
214
    // bad luck: no descriptor for exactly this class. Try to find one for some base class.
215
    //XXX we could even cache the result in a {classname->descriptor} hashtable.
216
    cClassDescriptor *bestDesc = NULL;
217
    int bestInheritanceChainLength = -1;
218
    cRegistrationList *array = classDescriptors.getInstance();
219
    for (int i=0; i<array->size(); i++)
220
    {
221
        cClassDescriptor *desc = dynamic_cast<cClassDescriptor *>(array->get(i));
222
        if (!desc || !desc->doesSupport(object))
223
            continue; // skip holes
224
        int inheritanceChainLength = desc->getInheritanceChainLength();
225
        if (inheritanceChainLength > bestInheritanceChainLength)
226
        {
227
            bestDesc = desc;
228
            bestInheritanceChainLength = inheritanceChainLength;
229
        }
230
    }
231
    return bestDesc;
232
}
233
234
// for backward compatilibity with 4.0
235
bool cClassDescriptor::getFieldAsString(void *object, int field, int i, char *buf, int bufsize) const
236
{
237
    std::string result = getFieldAsString(object, field, i);
238
    strncpy(buf, result.c_str(), bufsize);
239
    buf[bufsize-1] = 0;
240
    return true;
241
}
242
243
int cClassDescriptor::findField(void *object, const char *fieldName) const
244
{
245
    int n = getFieldCount(object);
246
    for (int i=0; i<n; i++)
247
        if (strcmp(fieldName, getFieldName(object, i))==0)
248
            return i;
249
    return -1;
250
}