Imported Upstream version 2.81
[platform/upstream/libbullet.git] / Extras / CDTestFramework / Opcode / Ice / IceContainer.h
1 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 /**
3  *      Contains a simple container class.
4  *      \file           IceContainer.h
5  *      \author         Pierre Terdiman
6  *      \date           February, 5, 2000
7  */
8 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9
10 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11 // Include Guard
12 #ifndef ICECONTAINER_H
13 #define ICECONTAINER_H
14
15 //      #define CONTAINER_STATS                 // #### doesn't work with micro-threads!
16
17         class LinkedList;
18
19         enum FindMode
20         {
21                 FIND_CLAMP,
22                 FIND_WRAP,
23
24                 FIND_FORCE_DWORD = 0x7fffffff
25         };
26
27         class ICECORE_API Container : public Allocateable
28 #ifdef CONTAINER_STATS
29                 , public ListElem
30 #endif
31         {
32                 public:
33                 // Constructor / Destructor
34                                                                 Container();
35                                                                 Container(const Container& object);
36                                                                 Container(udword size, float growth_factor);
37                                                                 ~Container();
38                 // Management
39                 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
40                 /**
41                  *      Initializes the container so that it uses an external memory buffer. The container doesn't own the memory, resizing is disabled.
42                  *      \param          max_entries             [in] max number of entries in the container
43                  *      \param          entries                 [in] external memory buffer
44                  */
45                 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
46                                 void                    InitSharedBuffers(udword max_entries, udword* entries);
47
48                 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
49                 /**
50                  *      A O(1) method to add a value in the container. The container is automatically resized if needed.
51                  *      The method is inline, not the resize. The call overhead happens on resizes only, which is not a problem since the resizing operation
52                  *      costs a lot more than the call overhead...
53                  *
54                  *      \param          entry           [in] a udword to store in the container
55                  *      \see            Add(float entry)
56                  *      \see            Empty()
57                  *      \see            Contains(udword entry)
58                  *      \return         Self-Reference
59                  */
60                 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
61                 inline_ Container&              Add(udword entry)
62                                                                 {
63                                                                         // Resize if needed
64                                                                         if(mCurNbEntries==mMaxNbEntries)        Resize();
65
66                                                                         // Add new entry
67                                                                         mEntries[mCurNbEntries++]       = entry;
68                                                                         return *this;
69                                                                 }
70
71                 inline_ Container&              Add(const udword* entries, udword nb)
72                                                                 {
73                                                                         if(entries && 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                                                                         }
82                                                                         return *this;
83                                                                 }
84
85                 inline_ Container&              Add(const Container& container)
86                                                                 {
87                                                                         return Add(container.GetEntries(), container.GetNbEntries());
88                                                                 }
89
90                 inline_ udword*                 Reserve(udword nb)
91                                                                 {
92                                                                         // Resize if needed
93                                                                         if(mCurNbEntries+nb>mMaxNbEntries)      Resize(nb);
94
95                                                                         // We expect the user to fill reserved memory with 'nb' udwords
96                                                                         udword* Reserved = &mEntries[mCurNbEntries];
97
98                                                                         // Meanwhile, we do as if it had been filled
99                                                                         mCurNbEntries += nb;
100
101                                                                         // This is mainly used to avoid the copy when possible
102                                                                         return Reserved;
103                                                                 }
104
105                 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
106                 /**
107                  *      A O(1) method to add a value in the container. The container is automatically resized if needed.
108                  *      The method is inline, not the resize. The call overhead happens on resizes only, which is not a problem since the resizing operation
109                  *      costs a lot more than the call overhead...
110                  *
111                  *      \param          entry           [in] a float to store in the container
112                  *      \see            Add(udword entry)
113                  *      \see            Empty()
114                  *      \see            Contains(udword entry)
115                  *      \return         Self-Reference
116                  */
117                 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
118                 inline_ Container&              Add(float entry)
119                                                                 {
120                                                                         // Resize if needed
121                                                                         if(mCurNbEntries==mMaxNbEntries)        Resize();
122
123                                                                         // Add new entry
124                                                                         mEntries[mCurNbEntries++]       = IR(entry);
125                                                                         return *this;
126                                                                 }
127
128                 inline_ Container&              Add(const float* entries, udword nb)
129                                                                 {
130                                                                         // Resize if needed
131                                                                         if(mCurNbEntries+nb>mMaxNbEntries)      Resize(nb);
132
133                                                                         // Add new entry
134                                                                         CopyMemory(&mEntries[mCurNbEntries], entries, nb*sizeof(float));
135                                                                         mCurNbEntries+=nb;
136                                                                         return *this;
137                                                                 }
138
139                 //! Add unique [slow]
140                 inline_ Container&              AddUnique(udword entry)
141                                                                 {
142                                                                         if(!Contains(entry))    Add(entry);
143                                                                         return *this;
144                                                                 }
145
146                 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
147                 /**
148                  *      Clears the container. All stored values are deleted, and it frees used ram.
149                  *      \see            Reset()
150                  *      \return         Self-Reference
151                  */
152                 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
153                                 Container&              Empty();
154
155                 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
156                 /**
157                  *      Resets the container. Stored values are discarded but the buffer is kept so that further calls don't need resizing again.
158                  *      That's a kind of temporal coherence.
159                  *      \see            Empty()
160                  */
161                 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
162                 inline_ void                    Reset()
163                                                                 {
164                                                                         // Avoid the write if possible
165                                                                         // ### CMOV
166                                                                         if(mCurNbEntries)       mCurNbEntries = 0;
167                                                                 }
168
169                 // HANDLE WITH CARE - I hope you know what you're doing
170                 inline_ void                    ForceSize(udword size)
171                                                                 {
172                                                                         mCurNbEntries = size;
173                                                                 }
174
175                 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
176                 /**
177                  *      Sets the initial size of the container. If it already contains something, it's discarded.
178                  *      \param          nb              [in] Number of entries
179                  *      \return         true if success
180                  */
181                 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
182                                 bool                    SetSize(udword nb);
183
184                 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
185                 /**
186                  *      Refits the container and get rid of unused bytes.
187                  *      \return         true if success
188                  */
189                 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
190                                 bool                    Refit();
191
192                                 bool                    Shrink();
193
194                 // Checks whether the container already contains a given value.
195                                 bool                    Contains(udword entry, udword* location=null) const;
196                 // Deletes an entry - doesn't preserve insertion order.
197                                 bool                    Delete(udword entry);
198                 // Deletes an entry - does preserve insertion order.
199                                 bool                    DeleteKeepingOrder(udword entry);
200                 //! Deletes the very last entry.
201                 inline_ void                    DeleteLastEntry()                                               { if(mCurNbEntries)     mCurNbEntries--;                        }
202                 //! Deletes the entry whose index is given
203                 inline_ void                    DeleteIndex(udword index)                               { mEntries[index] = mEntries[--mCurNbEntries];  }
204
205                 // Helpers
206                                 Container&              FindNext(udword& entry, FindMode find_mode=FIND_CLAMP);
207                                 Container&              FindPrev(udword& entry, FindMode find_mode=FIND_CLAMP);
208                 // Data access.
209                 inline_ udword                  GetNbEntries()                                  const   { return mCurNbEntries;                                 }       //!< Returns the current number of entries.
210                 inline_ udword                  GetMaxNbEntries()                               const   { return mMaxNbEntries;                                 }       //!< Returns max number of entries before resizing.
211                 inline_ udword                  GetEntry(udword i)                              const   { return mEntries[i];                                   }       //!< Returns ith entry.
212                 inline_ udword*                 GetEntries()                                    const   { return mEntries;                                              }       //!< Returns the list of entries.
213
214                 inline_ udword                  GetFirst()                                              const   { return mEntries[0];                                   }
215                 inline_ udword                  GetLast()                                               const   { return mEntries[mCurNbEntries-1];             }
216
217                 // Growth control
218                                 float                   GetGrowthFactor()                               const;                                                                                          //!< Returns the growth factor
219                                 void                    SetGrowthFactor(float growth);                                                                                                          //!< Sets the growth factor
220                 inline_ bool                    IsFull()                                                const   { return mCurNbEntries==mMaxNbEntries;  }       //!< Checks the container is full
221                 inline_ BOOL                    IsNotEmpty()                                    const   { return mCurNbEntries;                                 }       //!< Checks the container is empty
222
223                 //! Read-access as an array
224                 inline_ udword                  operator[](udword i)                    const   { ASSERT(i>=0 && i<mCurNbEntries); return mEntries[i];  }
225                 //! Write-access as an array
226                 inline_ udword&                 operator[](udword i)                                    { ASSERT(i>=0 && i<mCurNbEntries); return mEntries[i];  }
227
228                 // Stats
229                                 udword                  GetUsedRam()                                    const;
230
231                 //! Operator for "Container A = Container B"
232                                 void                    operator = (const Container& object);
233
234 #ifdef CONTAINER_STATS
235                 static  udword                  GetNbContainers()                                               { return mNbContainers; }
236                 static  udword                  GetTotalBytes()                                                 { return mUsedRam;              }
237                 static  LinkedList&             GetContainers()                                                 { return mContainers;   }
238                 private:
239
240                 static  udword                  mNbContainers;          //!< Number of containers around
241                 static  udword                  mUsedRam;                       //!< Amount of bytes used by containers in the system
242                 static  LinkedList              mContainers;
243 #endif
244                 private:
245                 // Resizing
246                                 bool                    Resize(udword needed=1);
247                 // Data
248                                 udword                  mMaxNbEntries;          //!< Maximum possible number of entries
249                                 udword                  mCurNbEntries;          //!< Current number of entries
250                                 udword*                 mEntries;                       //!< List of entries
251                                 float                   mGrowthFactor;          //!< Resize: new number of entries = old number * mGrowthFactor
252         };
253
254 #endif // ICECONTAINER_H