Project

General

Profile

Statistics
| Branch: | Revision:

root / src / sim / cproperty.cc @ a3be1d55

History | View | Annotate | Download (6.96 KB)

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

12
  This file is distributed WITHOUT ANY WARRANTY. See the file
13
  `license' for details on this and other legal matters.
14
*--------------------------------------------------------------*/
15
16
#include <sstream>
17
#include "cproperty.h"
18
#include "cproperties.h"
19
20
USING_NAMESPACE
21
22
23
const char *cProperty::DEFAULTKEY = "";
24
25
cDummyStringPool cProperty::stringPool("cProperty::stringPool");
26
27
28
cProperty::cProperty(const char *name, const char *index) : cNamedObject(name, true)
29
{
30
    ownerp = NULL;
31
    propindex = propfullname = NULL;
32
    setIndex(index);
33
}
34
35
cProperty::~cProperty()
36
{
37
    // release pooled strings
38
    stringPool.release(propindex);
39
    stringPool.release(propfullname);
40
    int n = keyv.size();
41
    for (int i=0; i<n; i++)
42
    {
43
        stringPool.release(keyv[i]);
44
        releaseValues(valuesv[i]);
45
    }
46
}
47
48
void cProperty::releaseValues(CharPtrVector& vals)
49
{
50
    int n = vals.size();
51
    for (int i=0; i<n; i++)
52
        stringPool.release(vals[i]);
53
    vals.clear();
54
}
55
56
cProperty& cProperty::operator=(const cProperty& other)
57
{
58
    if (isLocked())
59
        throw cRuntimeError(this, eLOCKED);
60
61
    // note: do NOT copy islocked flag
62
    bool oldIsLocked = isLocked();
63
    cNamedObject::operator=(other);
64
    setFlag(FL_ISLOCKED, oldIsLocked);
65
66
    setName(other.getName()); // cNamedObject doesn't do that
67
68
    stringPool.release(propfullname);
69
    propfullname = NULL;
70
71
    setIndex(other.getIndex());
72
73
    // release old value
74
    int n = keyv.size();
75
    for (int i=0; i<n; i++)
76
    {
77
        stringPool.release(keyv[i]);
78
        releaseValues(valuesv[i]);
79
    }
80
    keyv.clear();
81
    valuesv.clear();
82
83
    // copy new value
84
    int m = other.keyv.size();
85
    for (int i=0; i<m; i++)
86
    {
87
        keyv.push_back(stringPool.get(other.keyv[i]));
88
        valuesv.push_back(CharPtrVector());
89
        CharPtrVector& vals = valuesv[i];
90
        const CharPtrVector& othervals = other.valuesv[i];
91
        int nn = othervals.size();
92
        vals.resize(nn);
93
        for (int j=0; j<nn; j++)
94
            vals[j] = stringPool.get(othervals[j]);
95
    }
96
    return *this;
97
}
98
99
void cProperty::setName(const char *name)
100
{
101
    if (isLocked())
102
        throw cRuntimeError(this, eLOCKED);
103
    if (name && name[0]=='@')
104
        throw cRuntimeError(this,"setName(): property name must be specified without the '@' character");
105
106
    cNamedObject::setName(name);
107
108
    stringPool.release(propfullname);
109
    propfullname = NULL;
110
}
111
112
const char *cProperty::getFullName() const
113
{
114
    if (!propfullname)
115
    {
116
        if (!propindex) {
117
            propfullname = stringPool.get(getName());
118
        }
119
        else {
120
            std::stringstream os;
121
            os << getName() << "[" << propindex << "]";
122
            propfullname = stringPool.get(os.str().c_str());
123
        }
124
    }
125
    return propfullname;
126
}
127
128
std::string cProperty::info() const
129
{
130
    std::stringstream os;
131
    os << "@" << getFullName();
132
    if (!keyv.empty())
133
    {
134
        os << "(";
135
        int n = keyv.size();
136
        for (int i=0; i<n; i++)
137
        {
138
            if (i!=0)
139
                os << ";";
140
            if (keyv[i] && *keyv[i])
141
                os << keyv[i] << "=";
142
            for (int j=0; j<(int)valuesv[i].size(); j++)
143
                os << (j==0 ? "" : ",") << valuesv[i][j];  //FIXME value may need quoting
144
        }
145
        os << ")";
146
    }
147
    return os.str();
148
}
149
150
void cProperty::parsimPack(cCommBuffer *buffer)
151
{
152
    throw cRuntimeError(this, eCANTPACK);
153
}
154
155
void cProperty::parsimUnpack(cCommBuffer *buffer)
156
{
157
    if (isLocked())
158
        throw cRuntimeError(this, eLOCKED);
159
    throw cRuntimeError(this, eCANTPACK);
160
}
161
162
void cProperty::setIndex(const char *index)
163
{
164
    if (isLocked())
165
        throw cRuntimeError(this, eLOCKED);
166
167
    stringPool.release(propindex);
168
    propindex = stringPool.get(index);
169
170
    stringPool.release(propfullname);
171
    propfullname = NULL;
172
}
173
174
const char *cProperty::getIndex() const
175
{
176
    return propindex;
177
}
178
179
void cProperty::setIsImplicit(bool b)
180
{
181
    if (isLocked())
182
        throw cRuntimeError(this, eLOCKED);
183
    setFlag(FL_ISIMPLICIT, b);
184
}
185
186
bool cProperty::isImplicit() const
187
{
188
    return flags&FL_ISIMPLICIT;
189
}
190
191
int cProperty::findKey(const char *key) const
192
{
193
    if (!key)
194
        key = "";
195
    for (int i=0; i<(int)keyv.size(); i++)
196
        if (!strcmp(key,keyv[i]))
197
            return i;
198
    return -1;
199
}
200
201
const std::vector<const char *>& cProperty::getKeys() const
202
{
203
    return keyv;
204
}
205
206
bool cProperty::containsKey(const char *key) const
207
{
208
    return findKey(key)!=-1;
209
}
210
211
void cProperty::addKey(const char *key)
212
{
213
    if (!key)
214
        key = "";
215
    int k = findKey(key);
216
    if (k==-1)
217
    {
218
        keyv.push_back(stringPool.get(key));
219
        valuesv.push_back(CharPtrVector());
220
    }
221
}
222
223
cProperty::CharPtrVector& cProperty::getValuesVector(const char *key) const
224
{
225
    if (!key)
226
        key = "";
227
    int k = findKey(key);
228
    if (k==-1)
229
        throw cRuntimeError(this, "property has no key named `%s'", key);
230
    return const_cast<CharPtrVector&>(valuesv[k]);
231
}
232
233
int cProperty::getNumValues(const char *key) const
234
{
235
    if (!key)
236
        key = "";
237
    int k = findKey(key);
238
    if (k==-1)
239
        return 0;
240
    return valuesv[k].size();
241
}
242
243
void cProperty::setNumValues(const char *key, int size)
244
{
245
    if (isLocked())
246
        throw cRuntimeError(this, eLOCKED);
247
    CharPtrVector& v = getValuesVector(key);
248
    int oldsize = v.size();
249
250
    // if shrink, release extra elements
251
    for (int i=size; i<oldsize; i++)
252
        stringPool.release(v[i]);
253
254
    // resize
255
    v.resize(size);
256
257
    // if grow, initialize extra elements
258
    for (int i=oldsize; i<size; i++)
259
        v[i] = stringPool.get("");
260
}
261
262
const char *cProperty::getValue(const char *key, int index) const
263
{
264
    if (!key)
265
        key = "";
266
    int k = findKey(key);
267
    if (k==-1)
268
        return NULL;
269
    const CharPtrVector& v = valuesv[k];
270
    if (index<0 || index>=(int)v.size())
271
        return NULL;
272
    return v[index];
273
}
274
275
void cProperty::setValue(const char *key, int index, const char *value)
276
{
277
    if (isLocked())
278
        throw cRuntimeError(this, eLOCKED);
279
    if (!value)
280
        value = "";
281
    CharPtrVector& v = getValuesVector(key);
282
    if (index<0)
283
        throw cRuntimeError(this, "negative property value index %d for key `%s'", index, key);
284
    if (index>=(int)v.size())
285
        setNumValues(key, index+1);
286
    stringPool.release(v[index]);
287
    v[index] = stringPool.get(value);
288
}
289
290
void cProperty::erase(const char *key)
291
{
292
    if (isLocked())
293
        throw cRuntimeError(this, eLOCKED);
294
295
    // erase
296
    int k = findKey(key);
297
    if (k!=-1)
298
    {
299
        stringPool.release(keyv[k]);
300
        releaseValues(valuesv[k]);
301
        keyv.erase(keyv.begin()+k);
302
        valuesv.erase(valuesv.begin()+k);
303
    }
304
}