Statistics
| Branch: | Revision:

root / src / nedxml / nedelement.cc @ 68da4f12

History | View | Annotate | Download (7.72 KB)

1 01873262 Georg Kunz
//==========================================================================
2
// nedelement.cc  -
3
//
4
//                     OMNeT++/OMNEST
5
//            Discrete System Simulation in C++
6
//
7
// Contents:
8
//   class NEDElement
9
//
10
//==========================================================================
11
12
/*--------------------------------------------------------------*
13
  Copyright (C) 2002-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 <string.h>
21
#include <iostream>
22
23
#include "nedelement.h"
24
#include "nederror.h"
25
#include "nedexception.h"
26
27
USING_NAMESPACE
28
29
using std::ostream;
30
31
32
long NEDElement::lastid = 0;
33
long NEDElement::numcreated = 0;
34
long NEDElement::numexisting = 0;
35
36
bool NEDElement::stringToBool(const char *s)
37
{
38
    if (!strcmp(s,"true"))
39
        return true;
40
    else if (!strcmp(s,"false"))
41
        return false;
42
    else
43
        throw NEDException("invalid attribute value '%s': should be 'true' or 'false'",(s?s:""));
44
}
45
46
const char *NEDElement::boolToString(bool b)
47
{
48
    return b ? "true" : "false";
49
}
50
51
int NEDElement::stringToEnum(const char *s, const char *vals[], int nums[], int n)
52
{
53
    if (!s)
54
        throw NEDException("attribute cannot be empty: should be one of the allowed words '%s', etc.",vals[0]);
55
    for (int i=0; i<n; i++)
56
        if (!strcmp(s,vals[i]))
57
            return nums[i];
58
    if (n==0) throw NEDException("call to stringToEnum() with n=0");
59
    throw NEDException("invalid attribute value '%s': should be one of the allowed words '%s', etc.",s,vals[0]);
60
}
61
62
const char *NEDElement::enumToString(int b, const char *vals[], int nums[], int n)
63
{
64
    for (int i=0; i<n; i++)
65
        if (nums[i]==b)
66
            return vals[i];
67
    if (n==0) throw NEDException("call to enumToString() with n=0");
68
    throw NEDException("invalid integer value %d for enum attribute (not one of '%s'=%d etc)",b,vals[0],nums[0]);
69
}
70
71
void NEDElement::validateEnum(int b, const char *vals[], int nums[], int n)
72
{
73
    // code almost identical to enumToString()
74
    for (int i=0; i<n; i++)
75
        if (nums[i]==b)
76
            return;
77
    if (n==0) throw NEDException("call to validateEnum() with n=0");
78
    throw NEDException("invalid integer value %d for enum attribute",b,vals[0],nums[0]);
79
}
80
81
NEDElement::NEDElement()
82
{
83
    parent = 0;
84
    firstchild = 0;
85
    lastchild = 0;
86
    prevsibling = 0;
87
    nextsibling = 0;
88
    userdata = 0;
89
90
    id = ++lastid;
91
    numcreated++;
92
    numexisting++;
93
}
94
95
NEDElement::NEDElement(NEDElement *parent)
96
{
97
    this->parent = 0;
98
    firstchild = 0;
99
    lastchild = 0;
100
    prevsibling = 0;
101
    nextsibling = 0;
102
    userdata = 0;
103
104
    id = ++lastid;
105
    numcreated++;
106
    numexisting++;
107
108
    parent->appendChild(this);
109
}
110
111
NEDElement::~NEDElement()
112
{
113
    if (parent)
114
    {
115
        parent->removeChild(this);
116
    }
117
    delete userdata;
118
    while (firstchild)
119
    {
120
        delete removeChild(firstchild);
121
    }
122
    numexisting--;
123
}
124
125
NEDElement *NEDElement::dupTree() const
126
{
127
    NEDElement *newNode = dup();
128
    for (NEDElement *child = getFirstChild(); child; child = child->getNextSibling())
129
        newNode->appendChild(child->dupTree());
130
    return newNode;
131
}
132
133
void NEDElement::applyDefaults()
134
{
135
    int n = getNumAttributes();
136
    for (int i=0; i<n; i++)
137
    {
138
        const char *defaultval = getAttributeDefault(i);
139
        if (defaultval)
140
            setAttribute(i,defaultval);
141
    }
142
}
143
144
long NEDElement::getId() const
145
{
146
    return id;
147
}
148
149
void NEDElement::setId(long _id)
150
{
151
    id = _id;
152
}
153
154
const char *NEDElement::getSourceLocation() const
155
{
156
    return srcloc.c_str();
157
}
158
159
void NEDElement::setSourceLocation(const char *loc)
160
{
161
    srcloc = loc ? loc : "";
162
}
163
164
const NEDSourceRegion& NEDElement::getSourceRegion() const
165
{
166
    return srcregion;
167
}
168
169
void NEDElement::setSourceRegion(const NEDSourceRegion& region)
170
{
171
    srcregion = region;
172
}
173
174
int NEDElement::lookupAttribute(const char *attr) const
175
{
176
    int n = getNumAttributes();
177
    for (int i=0; i<n; i++)
178
    {
179
        const char *attnamei = getAttributeName(i);
180
        if (attr[0]==attnamei[0] && !strcmp(attr,attnamei))
181
        {
182
            return i;
183
        }
184
    }
185
    return -1;
186
}
187
188
const char *NEDElement::getAttribute(const char *attr) const
189
{
190
    int k = lookupAttribute(attr);
191
    return getAttribute(k);
192
}
193
194
void NEDElement::setAttribute(const char *attr, const char *value)
195
{
196
    int k = lookupAttribute(attr);
197
    setAttribute(k,value);
198
}
199
200
const char *NEDElement::getAttributeDefault(const char *attr) const
201
{
202
    int k = lookupAttribute(attr);
203
    return getAttributeDefault(k);
204
}
205
206
NEDElement *NEDElement::getParent() const
207
{
208
    return parent;
209
}
210
211
NEDElement *NEDElement::getFirstChild() const
212
{
213
   return firstchild;
214
}
215
216
NEDElement *NEDElement::getLastChild() const
217
{
218
    return lastchild;
219
}
220
221
NEDElement *NEDElement::getNextSibling() const
222
{
223
    return nextsibling;
224
}
225
226
NEDElement *NEDElement::getPrevSibling() const
227
{
228
    return prevsibling;
229
}
230
231
void NEDElement::appendChild(NEDElement *node)
232
{
233
    if (node->parent)
234
        node->parent->removeChild(node);
235
    node->parent = this;
236
    node->prevsibling = lastchild;
237
    node->nextsibling = 0;
238
    if (node->prevsibling)
239
        node->prevsibling->nextsibling = node;
240
    else
241
        firstchild = node;
242
    lastchild = node;
243
}
244
245
void NEDElement::insertChildBefore(NEDElement *where, NEDElement *node)
246
{
247
    if (node->parent)
248
        node->parent->removeChild(node);
249
    if (!where)
250
    {
251
        appendChild(node);
252
        return;
253
    }
254
    node->parent = this;
255
    node->prevsibling = where->prevsibling;
256
    node->nextsibling = where;
257
    where->prevsibling = node;
258
    if (node->prevsibling)
259
        node->prevsibling->nextsibling = node;
260
    else
261
        firstchild = node;
262
}
263
264
NEDElement *NEDElement::removeChild(NEDElement *node)
265
{
266
    if (node->prevsibling)
267
        node->prevsibling->nextsibling = node->nextsibling;
268
    else
269
        firstchild = node->nextsibling;
270
    if (node->nextsibling)
271
        node->nextsibling->prevsibling = node->prevsibling;
272
    else
273
        lastchild = node->prevsibling;
274
    node->parent = node->prevsibling = node->nextsibling = 0;
275
    return node;
276
}
277
278
NEDElement *NEDElement::getFirstChildWithTag(int tagcode) const
279
{
280
    NEDElement *node = firstchild;
281
    while (node)
282
    {
283
        if (node->getTagCode()==tagcode)
284
            return node;
285
        node = node->getNextSibling();
286
    }
287
    return 0;
288
}
289
290
NEDElement *NEDElement::getNextSiblingWithTag(int tagcode) const
291
{
292
    NEDElement *node = this->nextsibling;
293
    while (node)
294
    {
295
        if (node->getTagCode()==tagcode)
296
            return node;
297
        node = node->getNextSibling();
298
    }
299
    return 0;
300
}
301
302
303
int NEDElement::getNumChildren() const
304
{
305
    int n=0;
306
    for (NEDElement *node = firstchild; node; node = node->getNextSibling())
307
        n++;
308
    return n;
309
}
310
311
int NEDElement::getNumChildrenWithTag(int tagcode) const
312
{
313
    int n=0;
314
    for (NEDElement *node = firstchild; node; node = node->getNextSibling())
315
        if (node->getTagCode()==tagcode)
316
            n++;
317
    return n;
318
}
319
320
NEDElement *NEDElement::getFirstChildWithAttribute(int tagcode, const char *attr, const char *attrvalue)
321
{
322
    for (NEDElement *child=getFirstChildWithTag(tagcode); child; child = child->getNextSiblingWithTag(tagcode))
323
    {
324
        const char *val = child->getAttribute(attr);
325
        if (val && !strcmp(val,attrvalue))
326
            return child;
327
    }
328
    return NULL;
329
}
330
331
NEDElement *NEDElement::getParentWithTag(int tagcode)
332
{
333
    NEDElement *node = this;
334
    while (node && node->getTagCode()!=tagcode)
335
        node = node->getParent();
336
    return node;
337
}
338
339
void NEDElement::setUserData(NEDElementUserData *data)
340
{
341
    delete userdata;
342
    userdata = data;
343
}
344
345
NEDElementUserData *NEDElement::getUserData() const
346
{
347
    return userdata;
348
}