~ubuntu-branches/debian/sid/ember/sid

« back to all changes in this revision

Viewing changes to src/components/ogre/ogreopcode/src/Opcode/Ice/IceContainer.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michael Koch
  • Date: 2009-07-23 07:46:40 UTC
  • Revision ID: james.westby@ubuntu.com-20090723074640-wh0ukzis0kda36qv
Tags: upstream-0.5.6
ImportĀ upstreamĀ versionĀ 0.5.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
2
/**
 
3
 *      Contains a simple container class.
 
4
 *      \file           IceContainer.cpp
 
5
 *      \author         Pierre Terdiman
 
6
 *      \date           February, 5, 2000
 
7
 */
 
8
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
9
 
 
10
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
11
/**
 
12
 *      Contains a list of 32-bits values.
 
13
 *      Use this class when you need to store an unknown number of values. The list is automatically
 
14
 *      resized and can contains 32-bits entities (dwords or floats)
 
15
 *
 
16
 *      \class          Container
 
17
 *      \author         Pierre Terdiman
 
18
 *      \version        1.0
 
19
 *      \date           08.15.98
 
20
*/
 
21
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
22
 
 
23
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
24
// Precompiled Header
 
25
#include "Opcode/Stdafx.h"
 
26
 
 
27
using namespace IceCore;
 
28
 
 
29
// Static members
 
30
#ifdef CONTAINER_STATS
 
31
udword Container::mNbContainers = 0;
 
32
udword Container::mUsedRam = 0;
 
33
#endif
 
34
 
 
35
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
36
/**
 
37
 *      Constructor. No entries allocated there.
 
38
 */
 
39
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
40
Container::Container() : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(2.0f)
 
41
{
 
42
#ifdef CONTAINER_STATS
 
43
        mNbContainers++;
 
44
        mUsedRam+=sizeof(Container);
 
45
#endif
 
46
}
 
47
 
 
48
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
49
/**
 
50
 *      Constructor. Also allocates a given number of entries.
 
51
 */
 
52
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
53
Container::Container(udword size, float growth_factor) : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(growth_factor)
 
54
{
 
55
#ifdef CONTAINER_STATS
 
56
        mNbContainers++;
 
57
        mUsedRam+=sizeof(Container);
 
58
#endif
 
59
        SetSize(size);
 
60
}
 
61
 
 
62
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
63
/**
 
64
 *      Copy constructor.
 
65
 */
 
66
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
67
Container::Container(const Container& object) : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(2.0f)
 
68
{
 
69
#ifdef CONTAINER_STATS
 
70
        mNbContainers++;
 
71
        mUsedRam+=sizeof(Container);
 
72
#endif
 
73
        *this = object;
 
74
}
 
75
 
 
76
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
77
/**
 
78
 *      Destructor.     Frees everything and leaves.
 
79
 */
 
80
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
81
Container::~Container()
 
82
{
 
83
        Empty();
 
84
#ifdef CONTAINER_STATS
 
85
        mNbContainers--;
 
86
        mUsedRam-=GetUsedRam();
 
87
#endif
 
88
}
 
89
 
 
90
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
91
/**
 
92
 *      Clears the container. All stored values are deleted, and it frees used ram.
 
93
 *      \see            Reset()
 
94
 *      \return         Self-Reference
 
95
 */
 
96
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
97
Container& Container::Empty()
 
98
{
 
99
#ifdef CONTAINER_STATS
 
100
        mUsedRam-=mMaxNbEntries*sizeof(udword);
 
101
#endif
 
102
        DELETEARRAY(mEntries);
 
103
        mCurNbEntries = mMaxNbEntries = 0;
 
104
        return *this;
 
105
}
 
106
 
 
107
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
108
/**
 
109
 *      Resizes the container.
 
110
 *      \param          needed  [in] assume the container can be added at least "needed" values
 
111
 *      \return         true if success.
 
112
 */
 
113
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
114
bool Container::Resize(udword needed)
 
115
{
 
116
#ifdef CONTAINER_STATS
 
117
        // Subtract previous amount of bytes
 
118
        mUsedRam-=mMaxNbEntries*sizeof(udword);
 
119
#endif
 
120
 
 
121
        // Get more entries
 
122
        mMaxNbEntries = mMaxNbEntries ? udword(float(mMaxNbEntries)*mGrowthFactor) : 2; // Default nb Entries = 2
 
123
        if(mMaxNbEntries<mCurNbEntries + needed)        mMaxNbEntries = mCurNbEntries + needed;
 
124
 
 
125
        // Get some bytes for new entries
 
126
        udword* NewEntries = new udword[mMaxNbEntries];
 
127
        CHECKALLOC(NewEntries);
 
128
 
 
129
#ifdef CONTAINER_STATS
 
130
        // Add current amount of bytes
 
131
        mUsedRam+=mMaxNbEntries*sizeof(udword);
 
132
#endif
 
133
 
 
134
        // Copy old data if needed
 
135
        if(mCurNbEntries)       CopyMemory(NewEntries, mEntries, mCurNbEntries*sizeof(udword));
 
136
 
 
137
        // Delete old data
 
138
        DELETEARRAY(mEntries);
 
139
 
 
140
        // Assign new pointer
 
141
        mEntries = NewEntries;
 
142
 
 
143
        return true;
 
144
}
 
145
 
 
146
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
147
/**
 
148
 *      Sets the initial size of the container. If it already contains something, it's discarded.
 
149
 *      \param          nb              [in] Number of entries
 
150
 *      \return         true if success
 
151
 */
 
152
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
153
bool Container::SetSize(udword nb)
 
154
{
 
155
        // Make sure it's empty
 
156
        Empty();
 
157
 
 
158
        // Checkings
 
159
        if(!nb) return false;
 
160
 
 
161
        // Initialize for nb entries
 
162
        mMaxNbEntries = nb;
 
163
 
 
164
        // Get some bytes for new entries
 
165
        mEntries = new udword[mMaxNbEntries];
 
166
        CHECKALLOC(mEntries);
 
167
 
 
168
#ifdef CONTAINER_STATS
 
169
        // Add current amount of bytes
 
170
        mUsedRam+=mMaxNbEntries*sizeof(udword);
 
171
#endif
 
172
        return true;
 
173
}
 
174
 
 
175
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
176
/**
 
177
 *      Refits the container and get rid of unused bytes.
 
178
 *      \return         true if success
 
179
 */
 
180
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
181
bool Container::Refit()
 
182
{
 
183
#ifdef CONTAINER_STATS
 
184
        // Subtract previous amount of bytes
 
185
        mUsedRam-=mMaxNbEntries*sizeof(udword);
 
186
#endif
 
187
 
 
188
        // Get just enough entries
 
189
        mMaxNbEntries = mCurNbEntries;
 
190
        if(!mMaxNbEntries)      return false;
 
191
 
 
192
        // Get just enough bytes
 
193
        udword* NewEntries = new udword[mMaxNbEntries];
 
194
        CHECKALLOC(NewEntries);
 
195
 
 
196
#ifdef CONTAINER_STATS
 
197
        // Add current amount of bytes
 
198
        mUsedRam+=mMaxNbEntries*sizeof(udword);
 
199
#endif
 
200
 
 
201
        // Copy old data
 
202
        CopyMemory(NewEntries, mEntries, mCurNbEntries*sizeof(udword));
 
203
 
 
204
        // Delete old data
 
205
        DELETEARRAY(mEntries);
 
206
 
 
207
        // Assign new pointer
 
208
        mEntries = NewEntries;
 
209
 
 
210
        return true;
 
211
}
 
212
 
 
213
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
214
/**
 
215
 *      Checks whether the container already contains a given value.
 
216
 *      \param          entry                   [in] the value to look for in the container
 
217
 *      \param          location                [out] a possible pointer to store the entry location
 
218
 *      \see            Add(udword entry)
 
219
 *      \see            Add(float entry)
 
220
 *      \see            Empty()
 
221
 *      \return         true if the value has been found in the container, else false.
 
222
 */
 
223
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
224
bool Container::Contains(udword entry, udword* location) const
 
225
{
 
226
        // Look for the entry
 
227
        for(udword i=0;i<mCurNbEntries;i++)
 
228
        {
 
229
                if(mEntries[i]==entry)
 
230
                {
 
231
                        if(location)    *location = i;
 
232
                        return true;
 
233
                }
 
234
        }
 
235
        return false;
 
236
}
 
237
 
 
238
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
239
/**
 
240
 *      Deletes an entry. If the container contains such an entry, it's removed.
 
241
 *      \param          entry           [in] the value to delete.
 
242
 *      \return         true if the value has been found in the container, else false.
 
243
 *      \warning        This method is arbitrary slow (O(n)) and should be used carefully. Insertion order is not preserved.
 
244
 */
 
245
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
246
bool Container::Delete(udword entry)
 
247
{
 
248
        // Look for the entry
 
249
        for(udword i=0;i<mCurNbEntries;i++)
 
250
        {
 
251
                if(mEntries[i]==entry)
 
252
                {
 
253
                        // Entry has been found at index i. The strategy is to copy the last current entry at index i, and decrement the current number of entries.
 
254
                        DeleteIndex(i);
 
255
                        return true;
 
256
                }
 
257
        }
 
258
        return false;
 
259
}
 
260
 
 
261
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
262
/**
 
263
 *      Deletes an entry, preserving the insertion order. If the container contains such an entry, it's removed.
 
264
 *      \param          entry           [in] the value to delete.
 
265
 *      \return         true if the value has been found in the container, else false.
 
266
 *      \warning        This method is arbitrary slow (O(n)) and should be used carefully.
 
267
 */
 
268
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
269
bool Container::DeleteKeepingOrder(udword entry)
 
270
{
 
271
        // Look for the entry
 
272
        for(udword i=0;i<mCurNbEntries;i++)
 
273
        {
 
274
                if(mEntries[i]==entry)
 
275
                {
 
276
                        // Entry has been found at index i.
 
277
                        // Shift entries to preserve order. You really should use a linked list instead.
 
278
                        mCurNbEntries--;
 
279
                        for(udword j=i;j<mCurNbEntries;j++)
 
280
                        {
 
281
                                mEntries[j] = mEntries[j+1];
 
282
                        }
 
283
                        return true;
 
284
                }
 
285
        }
 
286
        return false;
 
287
}
 
288
 
 
289
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
290
/**
 
291
 *      Gets the next entry, starting from input one.
 
292
 *      \param          entry           [in/out] On input, the entry to look for. On output, the next entry
 
293
 *      \param          find_mode       [in] wrap/clamp
 
294
 *      \return         Self-Reference
 
295
 */
 
296
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
297
Container& Container::FindNext(udword& entry, FindMode find_mode)
 
298
{
 
299
        udword Location;
 
300
        if(Contains(entry, &Location))
 
301
        {
 
302
                Location++;
 
303
                if(Location==mCurNbEntries)     Location = find_mode==FIND_WRAP ? 0 : mCurNbEntries-1;
 
304
                entry = mEntries[Location];
 
305
        }
 
306
        return *this;
 
307
}
 
308
 
 
309
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
310
/**
 
311
 *      Gets the previous entry, starting from input one.
 
312
 *      \param          entry           [in/out] On input, the entry to look for. On output, the previous entry
 
313
 *      \param          find_mode       [in] wrap/clamp
 
314
 *      \return         Self-Reference
 
315
 */
 
316
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
317
Container& Container::FindPrev(udword& entry, FindMode find_mode)
 
318
{
 
319
        udword Location;
 
320
        if(Contains(entry, &Location))
 
321
        {
 
322
                Location--;
 
323
                if(Location==0xffffffff)        Location = find_mode==FIND_WRAP ? mCurNbEntries-1 : 0;
 
324
                entry = mEntries[Location];
 
325
        }
 
326
        return *this;
 
327
}
 
328
 
 
329
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
330
/**
 
331
 *      Gets the ram used by the container.
 
332
 *      \return         the ram used in bytes.
 
333
 */
 
334
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
335
udword Container::GetUsedRam() const
 
336
{
 
337
        return sizeof(Container) + mMaxNbEntries * sizeof(udword);
 
338
}
 
339
 
 
340
void Container::operator=(const Container& object)
 
341
{
 
342
        SetSize(object.GetNbEntries());
 
343
        CopyMemory(mEntries, object.GetEntries(), mMaxNbEntries*sizeof(udword));
 
344
        mCurNbEntries = mMaxNbEntries;
 
345
}