Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/ode/ode-0.9/OPCODE/Ice/IceContainer.cpp @ 216

Last change on this file since 216 was 216, checked in by mathiask, 16 years ago

[Physik] add ode-0.9

File size: 13.7 KB
Line 
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 "Stdafx.h"
26
27using namespace IceCore;
28
29// Static members
30#ifdef CONTAINER_STATS
31udword Container::mNbContainers = 0;
32udword Container::mUsedRam = 0;
33#endif
34
35///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
36/**
37 *      Constructor. No entries allocated there.
38 */
39///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
40Container::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///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
53Container::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///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
67Container::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///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
81Container::~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///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
97Container& 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///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
114bool 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///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
153bool 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///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
181bool 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///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
224bool 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///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
246bool 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///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
269bool 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///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
297Container& 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///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
317Container& 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///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
335udword 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}*/
Note: See TracBrowser for help on using the repository browser.