Imported Upstream version 2.81
[platform/upstream/libbullet.git] / Extras / CDTestFramework / Opcode / Ice / _IceContainer.h
1 /*
2  *      ICE / OPCODE - Optimized Collision Detection
3  * http://www.codercorner.com/Opcode.htm
4  * 
5  * Copyright (c) 2001-2008 Pierre Terdiman,  pierre@codercorner.com
6
7 This software is provided 'as-is', without any express or implied warranty.
8 In no event will the authors be held liable for any damages arising from the use of this software.
9 Permission is granted to anyone to use this software for any purpose, 
10 including commercial applications, and to alter it and redistribute it freely, 
11 subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
14 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
15 3. This notice may not be removed or altered from any source distribution.
16 */
17 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
18 /**
19  *      Contains a simple container class.
20  *      \file           IceContainer.h
21  *      \author         Pierre Terdiman
22  *      \date           February, 5, 2000
23  */
24 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
25
26 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
27 // Include Guard
28 #ifndef __ICECONTAINER_H__
29 #define __ICECONTAINER_H__
30
31         #define CONTAINER_STATS
32
33         enum FindMode
34         {
35                 FIND_CLAMP,
36                 FIND_WRAP,
37
38                 FIND_FORCE_DWORD = 0x7fffffff
39         };
40
41         class ICECORE_API Container
42         {
43                 public:
44                 // Constructor / Destructor
45                                                                 Container();
46                                                                 Container(const Container& object);
47                                                                 Container(udword size, float growth_factor);
48                                                                 ~Container();
49                 // Management
50                 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
51                 /**
52                  *      A O(1) method to add a value in the container. The container is automatically resized if needed.
53                  *      The method is inline, not the resize. The call overhead happens on resizes only, which is not a problem since the resizing operation
54                  *      costs a lot more than the call overhead...
55                  *
56                  *      \param          entry           [in] a udword to store in the container
57                  *      \see            Add(float entry)
58                  *      \see            Empty()
59                  *      \see            Contains(udword entry)
60                  *      \return         Self-Reference
61                  */
62                 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
63                 inline_ Container&              Add(udword entry)
64                                                                 {
65                                                                         // Resize if needed
66                                                                         if(mCurNbEntries==mMaxNbEntries)        Resize();
67
68                                                                         // Add new entry
69                                                                         mEntries[mCurNbEntries++]       = entry;
70                                                                         return *this;
71                                                                 }
72
73                 inline_ Container&              Add(const udword* entries, udword nb)
74                                                                 {
75                                                                         // Resize if needed
76                                                                         if(mCurNbEntries+nb>mMaxNbEntries)      Resize(nb);
77
78                                                                         // Add new entry
79                                                                         CopyMemory(&mEntries[mCurNbEntries], entries, nb*sizeof(udword));
80                                                                         mCurNbEntries+=nb;
81                                                                         return *this;
82                                                                 }
83
84                 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
85                 /**
86                  *      A O(1) method to add a value in the container. The container is automatically resized if needed.
87                  *      The method is inline, not the resize. The call overhead happens on resizes only, which is not a problem since the resizing operation
88                  *      costs a lot more than the call overhead...
89                  *
90                  *      \param          entry           [in] a float to store in the container
91                  *      \see            Add(udword entry)
92                  *      \see            Empty()
93                  *      \see            Contains(udword entry)
94                  *      \return         Self-Reference
95                  */
96                 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
97                 inline_ Container&              Add(float entry)
98                                                                 {
99                                                                         // Resize if needed
100                                                                         if(mCurNbEntries==mMaxNbEntries)        Resize();
101
102                                                                         // Add new entry
103                                                                         mEntries[mCurNbEntries++]       = IR(entry);
104                                                                         return *this;
105                                                                 }
106
107                 inline_ Container&              Add(const float* entries, udword nb)
108                                                                 {
109                                                                         // Resize if needed
110                                                                         if(mCurNbEntries+nb>mMaxNbEntries)      Resize(nb);
111
112                                                                         // Add new entry
113                                                                         CopyMemory(&mEntries[mCurNbEntries], entries, nb*sizeof(float));
114                                                                         mCurNbEntries+=nb;
115                                                                         return *this;
116                                                                 }
117
118                 //! Add unique [slow]
119                 inline_ Container&              AddUnique(udword entry)
120                                                                 {
121                                                                         if(!Contains(entry))    Add(entry);
122                                                                         return *this;
123                                                                 }
124
125                 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
126                 /**
127                  *      Clears the container. All stored values are deleted, and it frees used ram.
128                  *      \see            Reset()
129                  *      \return         Self-Reference
130                  */
131                 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
132                                 Container&              Empty();
133
134                 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
135                 /**
136                  *      Resets the container. Stored values are discarded but the buffer is kept so that further calls don't need resizing again.
137                  *      That's a kind of temporal coherence.
138                  *      \see            Empty()
139                  */
140                 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
141                 inline_ void                    Reset()
142                                                                 {
143                                                                         // Avoid the write if possible
144                                                                         // ### CMOV
145                                                                         if(mCurNbEntries)       mCurNbEntries = 0;
146                                                                 }
147
148                 // HANDLE WITH CARE
149                 inline_ void                    ForceSize(udword size)
150                                                                 {
151                                                                         mCurNbEntries = size;
152                                                                 }
153
154                 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
155                 /**
156                  *      Sets the initial size of the container. If it already contains something, it's discarded.
157                  *      \param          nb              [in] Number of entries
158                  *      \return         true if success
159                  */
160                 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
161                                 bool                    SetSize(udword nb);
162
163                 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
164                 /**
165                  *      Refits the container and get rid of unused bytes.
166                  *      \return         true if success
167                  */
168                 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
169                                 bool                    Refit();
170
171                 // Checks whether the container already contains a given value.
172                                 bool                    Contains(udword entry, udword* location=null) const;
173                 // Deletes an entry - doesn't preserve insertion order.
174                                 bool                    Delete(udword entry);
175                 // Deletes an entry - does preserve insertion order.
176                                 bool                    DeleteKeepingOrder(udword entry);
177                 //! Deletes the very last entry.
178                 inline_ void                    DeleteLastEntry()                                               { if(mCurNbEntries)     mCurNbEntries--;                        }
179                 //! Deletes the entry whose index is given
180                 inline_ void                    DeleteIndex(udword index)                               { mEntries[index] = mEntries[--mCurNbEntries];  }
181
182                 // Helpers
183                                 Container&              FindNext(udword& entry, FindMode find_mode=FIND_CLAMP);
184                                 Container&              FindPrev(udword& entry, FindMode find_mode=FIND_CLAMP);
185                 // Data access.
186                 inline_ udword                  GetNbEntries()                                  const   { return mCurNbEntries;                                 }       //!< Returns the current number of entries.
187                 inline_ udword                  GetEntry(udword i)                              const   { return mEntries[i];                                   }       //!< Returns ith entry
188                 inline_ udword*                 GetEntries()                                    const   { return mEntries;                                              }       //!< Returns the list of entries.
189
190                 inline_ udword                  GetFirst()                                              const   { return mEntries[0];                                   }
191                 inline_ udword                  GetLast()                                               const   { return mEntries[mCurNbEntries-1];             }
192
193                 // Growth control
194                 inline_ float                   GetGrowthFactor()                               const   { return mGrowthFactor;                                 }       //!< Returns the growth factor
195                 inline_ void                    SetGrowthFactor(float growth)                   { mGrowthFactor = growth;                               }       //!< Sets the growth factor
196                 inline_ bool                    IsFull()                                                const   { return mCurNbEntries==mMaxNbEntries;  }       //!< Checks the container is full
197                 inline_ BOOL                    IsNotEmpty()                                    const   { return mCurNbEntries;                                 }       //!< Checks the container is empty
198
199                 //! Read-access as an array
200                 inline_ udword                  operator[](udword i)                    const   { ASSERT(i>=0 && i<mCurNbEntries); return mEntries[i];  }
201                 //! Write-access as an array
202                 inline_ udword&                 operator[](udword i)                                    { ASSERT(i>=0 && i<mCurNbEntries); return mEntries[i];  }
203
204                 // Stats
205                                 udword                  GetUsedRam()                                    const;
206
207                 //! Operator for "Container A = Container B"
208                                 void                    operator = (const Container& object);
209
210 #ifdef CONTAINER_STATS
211                 inline_ udword                  GetNbContainers()                               const   { return mNbContainers;         }
212                 inline_ udword                  GetTotalBytes()                                 const   { return mUsedRam;                      }
213                 private:
214
215                 static  udword                  mNbContainers;          //!< Number of containers around
216                 static  udword                  mUsedRam;                       //!< Amount of bytes used by containers in the system
217 #endif
218                 private:
219                 // Resizing
220                                 bool                    Resize(udword needed=1);
221                 // Data
222                                 udword                  mMaxNbEntries;          //!< Maximum possible number of entries
223                                 udword                  mCurNbEntries;          //!< Current number of entries
224                                 udword*                 mEntries;                       //!< List of entries
225                                 float                   mGrowthFactor;          //!< Resize: new number of entries = old number * mGrowthFactor
226         };
227
228 #endif // __ICECONTAINER_H__