1
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3
* Contains a simple container class.
4
* \file IceContainer.cpp
5
* \author Pierre Terdiman
6
* \date February, 5, 2000
8
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
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)
17
* \author Pierre Terdiman
21
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
23
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
25
#include "Opcode/Stdafx.h"
27
using namespace IceCore;
30
#ifdef CONTAINER_STATS
31
udword Container::mNbContainers = 0;
32
udword Container::mUsedRam = 0;
35
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
37
* Constructor. No entries allocated there.
39
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
40
Container::Container() : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(2.0f)
42
#ifdef CONTAINER_STATS
44
mUsedRam+=sizeof(Container);
48
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
50
* Constructor. Also allocates a given number of entries.
52
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
53
Container::Container(udword size, float growth_factor) : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(growth_factor)
55
#ifdef CONTAINER_STATS
57
mUsedRam+=sizeof(Container);
62
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
66
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
67
Container::Container(const Container& object) : mMaxNbEntries(0), mCurNbEntries(0), mEntries(null), mGrowthFactor(2.0f)
69
#ifdef CONTAINER_STATS
71
mUsedRam+=sizeof(Container);
76
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
78
* Destructor. Frees everything and leaves.
80
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
81
Container::~Container()
84
#ifdef CONTAINER_STATS
86
mUsedRam-=GetUsedRam();
90
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
92
* Clears the container. All stored values are deleted, and it frees used ram.
94
* \return Self-Reference
96
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
97
Container& Container::Empty()
99
#ifdef CONTAINER_STATS
100
mUsedRam-=mMaxNbEntries*sizeof(udword);
102
DELETEARRAY(mEntries);
103
mCurNbEntries = mMaxNbEntries = 0;
107
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
109
* Resizes the container.
110
* \param needed [in] assume the container can be added at least "needed" values
111
* \return true if success.
113
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
114
bool Container::Resize(udword needed)
116
#ifdef CONTAINER_STATS
117
// Subtract previous amount of bytes
118
mUsedRam-=mMaxNbEntries*sizeof(udword);
122
mMaxNbEntries = mMaxNbEntries ? udword(float(mMaxNbEntries)*mGrowthFactor) : 2; // Default nb Entries = 2
123
if(mMaxNbEntries<mCurNbEntries + needed) mMaxNbEntries = mCurNbEntries + needed;
125
// Get some bytes for new entries
126
udword* NewEntries = new udword[mMaxNbEntries];
127
CHECKALLOC(NewEntries);
129
#ifdef CONTAINER_STATS
130
// Add current amount of bytes
131
mUsedRam+=mMaxNbEntries*sizeof(udword);
134
// Copy old data if needed
135
if(mCurNbEntries) CopyMemory(NewEntries, mEntries, mCurNbEntries*sizeof(udword));
138
DELETEARRAY(mEntries);
140
// Assign new pointer
141
mEntries = NewEntries;
146
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
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
152
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
153
bool Container::SetSize(udword nb)
155
// Make sure it's empty
159
if(!nb) return false;
161
// Initialize for nb entries
164
// Get some bytes for new entries
165
mEntries = new udword[mMaxNbEntries];
166
CHECKALLOC(mEntries);
168
#ifdef CONTAINER_STATS
169
// Add current amount of bytes
170
mUsedRam+=mMaxNbEntries*sizeof(udword);
175
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
177
* Refits the container and get rid of unused bytes.
178
* \return true if success
180
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
181
bool Container::Refit()
183
#ifdef CONTAINER_STATS
184
// Subtract previous amount of bytes
185
mUsedRam-=mMaxNbEntries*sizeof(udword);
188
// Get just enough entries
189
mMaxNbEntries = mCurNbEntries;
190
if(!mMaxNbEntries) return false;
192
// Get just enough bytes
193
udword* NewEntries = new udword[mMaxNbEntries];
194
CHECKALLOC(NewEntries);
196
#ifdef CONTAINER_STATS
197
// Add current amount of bytes
198
mUsedRam+=mMaxNbEntries*sizeof(udword);
202
CopyMemory(NewEntries, mEntries, mCurNbEntries*sizeof(udword));
205
DELETEARRAY(mEntries);
207
// Assign new pointer
208
mEntries = NewEntries;
213
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
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)
221
* \return true if the value has been found in the container, else false.
223
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
224
bool Container::Contains(udword entry, udword* location) const
226
// Look for the entry
227
for(udword i=0;i<mCurNbEntries;i++)
229
if(mEntries[i]==entry)
231
if(location) *location = i;
238
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
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.
245
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
246
bool Container::Delete(udword entry)
248
// Look for the entry
249
for(udword i=0;i<mCurNbEntries;i++)
251
if(mEntries[i]==entry)
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.
261
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
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.
268
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
269
bool Container::DeleteKeepingOrder(udword entry)
271
// Look for the entry
272
for(udword i=0;i<mCurNbEntries;i++)
274
if(mEntries[i]==entry)
276
// Entry has been found at index i.
277
// Shift entries to preserve order. You really should use a linked list instead.
279
for(udword j=i;j<mCurNbEntries;j++)
281
mEntries[j] = mEntries[j+1];
289
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
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
296
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
297
Container& Container::FindNext(udword& entry, FindMode find_mode)
300
if(Contains(entry, &Location))
303
if(Location==mCurNbEntries) Location = find_mode==FIND_WRAP ? 0 : mCurNbEntries-1;
304
entry = mEntries[Location];
309
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
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
316
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
317
Container& Container::FindPrev(udword& entry, FindMode find_mode)
320
if(Contains(entry, &Location))
323
if(Location==0xffffffff) Location = find_mode==FIND_WRAP ? mCurNbEntries-1 : 0;
324
entry = mEntries[Location];
329
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
331
* Gets the ram used by the container.
332
* \return the ram used in bytes.
334
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
335
udword Container::GetUsedRam() const
337
return sizeof(Container) + mMaxNbEntries * sizeof(udword);
340
void Container::operator=(const Container& object)
342
SetSize(object.GetNbEntries());
343
CopyMemory(mEntries, object.GetEntries(), mMaxNbEntries*sizeof(udword));
344
mCurNbEntries = mMaxNbEntries;