Statistics
| Branch: | Revision:

root / src / sim / carray.cc @ e26d3d25

History | View | Annotate | Download (9.86 KB)

1
//=========================================================================
2
//  CARRAY.CC - part of
3
//
4
//                  OMNeT++/OMNEST
5
//           Discrete System Simulation in C++
6
//
7
//   Member functions of
8
//    cArray : flexible array to store cObject objects
9
//
10
//  Author: Andras Varga
11
//
12
//=========================================================================
13

    
14
/*--------------------------------------------------------------*
15
  Copyright (C) 1992-2008 Andras Varga
16
  Copyright (C) 2006-2008 OpenSim Ltd.
17

18
  This file is distributed WITHOUT ANY WARRANTY. See the file
19
  `license' for details on this and other legal matters.
20
*--------------------------------------------------------------*/
21

    
22
#include <string.h>  // memcmp, memcpy, memset
23
#include <algorithm>  // min, max
24
#include <sstream>
25
#include "carray.h"
26
#include "globals.h"
27
#include "cexception.h"
28

    
29
#ifdef WITH_PARSIM
30
#include "ccommbuffer.h"
31
#endif
32

    
33
USING_NAMESPACE
34

    
35
Register_Class(cArray);
36

    
37

    
38
//XXX this needs to be tested (test suite!) with:
39
// 1) non-cOwnedObject objects, where getOwner() returns NULL
40
// 2) non-cOwnedObject objects, where getOwner()!=NULL (and possible the array)
41
// 3) cOwnedObject objects with takeownership==false
42
// 4) cOwnedObject objects with takeownership==true
43

    
44
void cArray::Iterator::init(const cArray& a, bool athead)
45
{
46
    array = const_cast<cArray *>(&a); // we don't want a separate Const_Iterator class
47

    
48
    if (athead)
49
    {
50
        // fast-forward to first non-empty slot
51
        // (Note: we exploit that get(k) just returns NULL when k is out of bounds)
52
        k = 0;
53
        while (!array->get(k) && k<array->size())
54
            k++;
55

    
56
    }
57
    else
58
    {
59
        // rewind to first non-empty slot
60
        k = array->size()-1;
61
        while (!array->get(k) && k>=0)
62
            k--;
63
    }
64
}
65

    
66
cObject *cArray::Iterator::operator++(int)
67
{
68
    if (k<0 || k>=array->size())
69
        return NULL;
70
    cObject *obj = array->get(k);
71

    
72
    k++;
73
    while (!array->get(k) && k<array->size())
74
        k++;
75
    return obj;
76
}
77

    
78
cObject *cArray::Iterator::operator--(int)
79
{
80
    if (k<0 || k>=array->size())
81
        return NULL;
82
    cObject *obj = array->get(k);
83
    k--;
84
    while (!array->get(k) && k>=0)
85
        k--;
86
    return obj;
87
}
88

    
89
//----
90

    
91
cArray::cArray(const cArray& other) : cOwnedObject()
92
{
93
    vect = NULL;
94
    last = -1;
95
    setName(other.getName());
96
    operator=(other);
97
}
98

    
99
cArray::cArray(const char *name, int cap, int dt) : cOwnedObject(name)
100
{
101
    setFlag(FL_TKOWNERSHIP,true);
102
    delta = std::max(1,dt);
103
    capacity = std::max(cap,0);
104
    firstfree = 0;
105
    last = -1;
106
    vect = new cObject *[capacity];
107
    for (int i=0; i<capacity; i++)
108
        vect[i] = NULL;
109
}
110

    
111
cArray::~cArray()
112
{
113
    clear();
114
    delete [] vect;
115
}
116

    
117
cArray& cArray::operator=(const cArray& other)
118
{
119
    if (this == &other)
120
        return *this;
121

    
122
    clear();
123

    
124
    cOwnedObject::operator=(other);
125

    
126
    capacity = other.capacity;
127
    delta = other.delta;
128
    firstfree = other.firstfree;
129
    last = other.last;
130
    delete [] vect;
131
    vect = new cObject *[capacity];
132
    memcpy(vect, other.vect, capacity * sizeof(cObject *));
133

    
134
    for (int i=0; i<=last; i++)
135
    {
136
        if (vect[i])
137
        {
138
            if (!vect[i]->isOwnedObject())
139
                vect[i] = vect[i]->dup();
140
            else if (vect[i]->getOwner()==const_cast<cArray*>(&other))
141
                take(static_cast<cOwnedObject*>(vect[i] = vect[i]->dup()));
142
        }
143
    }
144
    return *this;
145
}
146

    
147
std::string cArray::info() const
148
{
149
    if (last==-1)
150
        return std::string("empty");
151
    std::stringstream out;
152
    out << "size=" << last+1;
153
    return out.str();
154
}
155

    
156
void cArray::forEachChild(cVisitor *v)
157
{
158
    for (int i=0; i<=last; i++)
159
        if (vect[i])
160
            v->visit(vect[i]);
161
}
162

    
163
void cArray::parsimPack(cCommBuffer *buffer)
164
{
165
#ifndef WITH_PARSIM
166
    throw cRuntimeError(this,eNOPARSIM);
167
#else
168
    cOwnedObject::parsimPack(buffer);
169

    
170
    buffer->pack(capacity);
171
    buffer->pack(delta);
172
    buffer->pack(firstfree);
173
    buffer->pack(last);
174

    
175
    for (int i = 0; i <= last; i++)
176
    {
177
        if (buffer->packFlag(vect[i]!=NULL))
178
        {
179
            if (vect[i]->isOwnedObject() && vect[i]->getOwner() != this)
180
                throw cRuntimeError(this,"parsimPack(): refusing to transmit an object not owned by the container");
181
            buffer->packObject(vect[i]);
182
        }
183
    }
184
#endif
185
}
186

    
187
void cArray::parsimUnpack(cCommBuffer *buffer)
188
{
189
#ifndef WITH_PARSIM
190
    throw cRuntimeError(this,eNOPARSIM);
191
#else
192
    cOwnedObject::parsimUnpack(buffer);
193

    
194
    delete [] vect;
195

    
196
    buffer->unpack(capacity);
197
    buffer->unpack(delta);
198
    buffer->unpack(firstfree);
199
    buffer->unpack(last);
200

    
201
    vect = new cObject *[capacity];
202
    for (int i = 0; i <= last; i++)
203
    {
204
        if (!buffer->checkFlag())
205
            vect[i] = NULL;
206
        else {
207
            vect[i] = buffer->unpackObject();
208
            if (vect[i]->isOwnedObject())
209
                take(static_cast<cOwnedObject *>(vect[i]));
210
        }
211
    }
212
#endif
213
}
214

    
215
void cArray::clear()
216
{
217
    for (int i=0; i<=last; i++)
218
    {
219
        cObject *obj = vect[i];
220
        if (obj)
221
        {
222
            if (!obj->isOwnedObject())
223
                delete obj;
224
            else if (obj->getOwner()==this)
225
                dropAndDelete(static_cast<cOwnedObject *>(obj));
226
            vect[i] = NULL;  // this is not strictly necessary
227
        }
228
    }
229
    firstfree = 0;
230
    last = -1;
231
}
232

    
233
void cArray::setCapacity(int newCapacity)
234
{
235
    if (newCapacity < size())
236
        throw cRuntimeError(this,"setCapacity: new capacity %d cannot be less than current size %d", newCapacity,size());
237

    
238
    cObject **newVect = new cObject *[newCapacity];
239
    for (int i=0; i<=last; i++)
240
        newVect[i] = vect[i];
241
    for (int i=last+1; i<capacity; i++)
242
        newVect[i] = NULL;
243
    delete [] vect;
244
    vect = newVect;
245
    capacity = newCapacity;
246
}
247

    
248
int cArray::add(cObject *obj)
249
{
250
    if (!obj)
251
        throw cRuntimeError(this,"cannot insert NULL pointer");
252

    
253
    if (obj->isOwnedObject() && getTakeOwnership())
254
        take(static_cast<cOwnedObject *>(obj));
255

    
256
    int retval;
257
    if (firstfree < capacity)  // fits in current vector
258
    {
259
        vect[firstfree] = obj;
260
        retval = firstfree;
261
        last = std::max(last,firstfree);
262
        do {
263
            firstfree++;
264
        } while (firstfree<=last && vect[firstfree]!=NULL);
265
    }
266
    else // must allocate bigger vector
267
    {
268
        cObject **v = new cObject *[capacity+delta];
269
        memcpy(v, vect, sizeof(cObject*)*capacity );
270
        memset(v+capacity, 0, sizeof(cObject*)*delta);
271
        delete [] vect;
272
        vect = v;
273
        vect[capacity] = obj;
274
        retval = last = capacity;
275
        firstfree = capacity+1;
276
        capacity += delta;
277
    }
278
    return retval;
279
}
280

    
281
int cArray::addAt(int m, cObject *obj)
282
{
283
    if (!obj)
284
        throw cRuntimeError(this,"cannot insert NULL pointer");
285

    
286
    if (m<capacity)  // fits in current vector
287
    {
288
        if (m<0)
289
            throw cRuntimeError(this,"addAt(): negative position %d",m);
290
        if (vect[m]!=NULL)
291
            throw cRuntimeError(this,"addAt(): position %d already used",m);
292
        vect[m] = obj;
293
        if (obj->isOwnedObject() && getTakeOwnership())
294
            take(static_cast<cOwnedObject *>(obj));
295
        last = std::max(m,last);
296
        if (firstfree==m)
297
            do {
298
                firstfree++;
299
            } while (firstfree<=last && vect[firstfree]!=NULL);
300
    }
301
    else // must allocate bigger vector
302
    {
303
        cObject **v = new cObject *[m+delta];
304
        memcpy(v, vect, sizeof(cObject*)*capacity);
305
        memset(v+capacity, 0, sizeof(cObject*)*(m+delta-capacity));
306
        delete [] vect;
307
        vect = v;
308
        vect[m] = obj;
309
        if (obj->isOwnedObject() && getTakeOwnership())
310
            take(static_cast<cOwnedObject *>(obj));
311
        capacity = m+delta;
312
        last = m;
313
        if (firstfree==m)
314
            firstfree++;
315
    }
316
    return m;
317
}
318

    
319
int cArray::set(cObject *obj)
320
{
321
    if (!obj)
322
        throw cRuntimeError(this,"cannot insert NULL pointer");
323

    
324
    int i = find(obj->getName());
325
    if (i<0)
326
    {
327
        return add(obj);
328
    }
329
    else
330
    {
331
        if (!vect[i]->isOwnedObject())
332
            delete vect[i];
333
        else if (vect[i]->getOwner()==this)
334
            dropAndDelete(static_cast<cOwnedObject *>(vect[i]));
335
        vect[i] = obj;
336
        if (obj->isOwnedObject() && getTakeOwnership())
337
            take(static_cast<cOwnedObject *>(obj));
338
        return i;
339
    }
340
}
341

    
342
int cArray::find(cObject *obj) const
343
{
344
    int i;
345
    for (i=0; i<=last; i++)
346
        if (vect[i]==obj)
347
            break;
348
    if (i<=last)
349
        return i;
350
    else
351
        return -1;
352
}
353

    
354
int cArray::find(const char *objname) const
355
{
356
    int i;
357
    for (i=0; i<=last; i++)
358
        if (vect[i] && vect[i]->isName(objname))
359
            break;
360
    if (i<=last)
361
        return i;
362
    else
363
        return -1;
364
}
365

    
366
cObject *cArray::get(int m)
367
{
368
    if (m>=0 && m<=last && vect[m])
369
        return vect[m];
370
    else
371
        return NULL;
372
}
373

    
374
const cObject *cArray::get(int m) const
375
{
376
    if (m>=0 && m<=last && vect[m])
377
        return vect[m];
378
    else
379
        return NULL;
380
}
381

    
382
cObject *cArray::get(const char *objname)
383
{
384
    int m = find( objname );
385
    if (m==-1)
386
        return NULL;
387
    return get(m);
388
}
389

    
390
const cObject *cArray::get(const char *objname) const
391
{
392
    int m = find( objname );
393
    if (m==-1)
394
        return NULL;
395
    return get(m);
396
}
397

    
398
cObject *cArray::remove(const char *objname)
399
{
400
    int m = find(objname);
401
    if (m==-1)
402
        return NULL;
403
    return remove(m);
404
}
405

    
406
cObject *cArray::remove(cObject *obj)
407
{
408
    if (!obj) return NULL;
409

    
410
    int m = find( obj );
411
    if (m==-1)
412
        return NULL;
413
    return remove(m);
414
}
415

    
416
cObject *cArray::remove(int m)
417
{
418
    if (m<0 || m>last || vect[m]==NULL)
419
        return NULL;
420

    
421
    cObject *obj = vect[m]; vect[m] = NULL;
422
    firstfree = std::min(firstfree, m);
423
    if (m==last)
424
        do {
425
            last--;
426
        } while (last>=0 && vect[last]==NULL);
427
    if (obj->isOwnedObject() && obj->getOwner()==this)
428
        drop(static_cast<cOwnedObject *>(obj));
429
    return obj;
430
}
431

    
432