vrecko
virtual reality framework
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
DynamicArray.h
Go to the documentation of this file.
1 #ifndef DYNAMICARRAY_H
2 #define DYNAMICARRAY_H
3 
4 // dynamically allocated array
5 
6 #include <new>
7 
8 #ifdef _DEBUG
9  #define DAINLINE
10 #else
11  #define DAINLINE inline
12 #endif
13 
14 namespace VK_NoStepInto_Namespace {
15 
16 template <class _Type>
17 class DynamicArray {
18 protected:
19  unsigned long dwAllocBy;
20  unsigned long dwAlloc; // number of items allocated
21  unsigned long dwInited; // number of items initialized
22 
23  // this should be true: dwNum <= dwInited <= dwAlloc
24 
25  bool InitItems (unsigned long dwStartIndex, unsigned long dwNumStructs);
26 
27 public:
28  _Type *lpBuffer;
29  unsigned long dwNum; // number of fields used
30  DAINLINE unsigned long GetAllocated();
31 
32  DynamicArray (void);
33  DynamicArray (unsigned long _dwAllocBy);
35  ~DynamicArray (void);
36 
37  DAINLINE const unsigned int size() const { return dwNum; };
38  // to achieve greater similarity with std::vector
39 
40  DAINLINE void push_back(const _Type& elem) { AddItem(elem); }
41 
42  bool FreeArray (void);
43 
44  bool Truncate (void);
45  // Lowers size of allocated memory to exact number of allocated items.
46 
47  bool PrepareNext (unsigned long _dwNum);
48 
49  bool Delete (unsigned long dwStartIndex, unsigned long dwNumStructs);
50 
51  DAINLINE bool DeleteAll(void);
52  inline bool clear(void) { DeleteAll(); };
53  // to achieve greater similarity with std::vector
54 
55  DAINLINE bool DeleteUnnecessary (void);
56 
57  bool Insert (unsigned long dwStartIndex, unsigned long dwNumStructs);
58 
59  bool CopyFrom (DynamicArray<_Type> *src);
60  // Deletes everything and copies items from given array.
61  // If the parameter is NULL, it only destroys everything.
62 
63  bool Swap (unsigned long dwIndex1, unsigned long dwIndex2);
64 
65  DAINLINE bool AddItem (const _Type& newItem);
66  // Add item at the end of the array
67 
68  DAINLINE _Type &Last (void);
69 
70  DAINLINE _Type &Act (void);
71  DAINLINE unsigned long &ActDWORD (void);
72  DAINLINE int &ActInt (void);
73 
74  DAINLINE _Type &Get(unsigned long index) { return (*this)[index]; }
75  DAINLINE const _Type &Get(unsigned long index) const { return (*this)[index]; }
76 
77  DAINLINE bool StoreByte (unsigned char bData);
78  // !!! WARNING !!! Can be only used in arrays, which have size of item = 1 byte !!!
79  // It also calls PrepareNext.
80  DAINLINE bool StoreDWORD (unsigned long dwData);
81  // !!! WARNING !!! Can be only used in arrays, which have size of item = 1, 2 or 4 bytes !!!
82  // It also calls PrepareNext.
83 
84  DAINLINE unsigned char ReadByte (void);
85  // !!! WARNING !!! Can be only used in arrays, which have size of item = 1 byte !!!
86  DAINLINE unsigned long ReadDWORD (void);
87  // !!! WARNING !!! Can be only used in arrays, which have size of item = 1, 2 or 4 bytes !!!
88 
89  DAINLINE _Type &operator[](unsigned long dw);
90  DAINLINE const _Type &operator[](unsigned long dw) const;
91 
92  DAINLINE _Type &at(unsigned long dw) { return lpBuffer[dw]; };
93  DAINLINE const _Type &at(unsigned long dw) const { return lpBuffer[dw]; };
94 };
95 
96 template <class _Type>
98 {
99  dwAllocBy = 1;
100 
101  dwNum = 0;
102  dwInited = 0;
103 
104  lpBuffer = NULL;
105  dwAlloc = 0;
106 }
107 
108 
109 template <class _Type>
111 {
112  dwAllocBy = src.dwAllocBy;
113 
114  dwNum = 0;
115  dwInited = 0;
116 
117  lpBuffer = NULL;
118  dwAlloc = 0;
119 
120  CopyFrom (&src);
121 }
122 
123 
124 template <class _Type>
125 DynamicArray<_Type>::DynamicArray (unsigned long _dwAllocBy)
126 {
127  dwAllocBy = _dwAllocBy;
128 
129  dwNum = 0;
130  dwInited = 0;
131 
132  lpBuffer = NULL;
133  dwAlloc = 0;
134 }
135 
136 
137 template <class _Type>
139 {
140  FreeArray ();
141 }
142 
143 template <class _Type>
145 {
146  return dwAlloc;
147 }
148 
149 template <class _Type>
151 {
152  if (!DeleteAll ())
153  return false;
154 
155  if (lpBuffer) {
156  free (lpBuffer);
157  lpBuffer = NULL;
158  }
159  dwAlloc = dwNum = dwInited = 0;
160 
161  return true;
162 }
163 
164 
165 template <class _Type>
167 {
168  unsigned long dw = dwAlloc - dwNum;
169 
170  if (!dw)
171  return true;
172 
173  if (!Delete (dwNum, dw))
174  return false;
175 
176  void *tmpMem;
177 
178  tmpMem = (_Type*)malloc (dwNum * sizeof (_Type));
179  if (!tmpMem && dwNum)
180  return false;
181  memcpy (tmpMem, lpBuffer, dwNum * sizeof (_Type));
182  free (lpBuffer);
183  lpBuffer = (_Type*)tmpMem;
184  dwAlloc = dwNum;
185  dwInited = dwNum;
186 
187  return true;
188 }
189 
190 
191 template <class _Type>
192 bool DynamicArray<_Type>::PrepareNext (unsigned long _dwNum)
193 {
194  unsigned long dw;
195  unsigned long dwNN = dwNum + _dwNum;
196 
197  if (dwNN <= dwInited)
198  return true;
199 
200  if (dwNN > dwAlloc) {
201 
202  void *tmpMem;
203  unsigned long dwLAlloc = dwAlloc;
204 
205 #if 0
206  dw = ((dwNN + dwAllocBy - 1) / dwAllocBy) * dwAllocBy;
207 #else
208  dw = dwNN + dwAllocBy - 1;
209  dw = dw - (dw % dwAllocBy);
210 #endif
211 
212 
213  tmpMem = (_Type*)malloc (dw * sizeof (_Type));
214  if (!tmpMem)
215  return false;
216 
217  if (lpBuffer) {
218  memcpy (tmpMem, lpBuffer, dwInited * sizeof (_Type));
219  free (lpBuffer);
220  }
221 
222  dwAlloc = dw;
223 
224  lpBuffer = (_Type*)tmpMem;
225 
226  }
227 
228  if (!InitItems (dwInited, dwNN - dwInited))
229  return false;
230  dwInited = dwNN;
231 
232  return true;
233 }
234 
235 
236 template <class _Type>
237 bool DynamicArray<_Type>::InitItems (unsigned long dwStartIndex, unsigned long dwNumStructs)
238 {
239  unsigned long dw;
240 
241  for (dw = dwStartIndex; dw < dwStartIndex + dwNumStructs; dw++) {
242  new ((void*)(lpBuffer + dw)) _Type;
243  }
244 
245  return true;
246 }
247 
248 
249 template <class _Type>
250 bool DynamicArray<_Type>::Delete (unsigned long dwStartIndex, unsigned long dwNumStructs)
251 {
252  if ((dwStartIndex >= dwAlloc) || (dwStartIndex >= dwInited) || (!dwNumStructs))
253  return true;
254 
255  unsigned long dw;
256 
257  if (dwStartIndex + dwNumStructs > dwInited)
258  dwNumStructs = dwInited - dwStartIndex;
259 
260  for (dw = dwStartIndex; dw < dwStartIndex + dwNumStructs; dw++)
261  ((_Type*)(lpBuffer + dw))->~_Type ();
262 
263 
264  memcpy (lpBuffer + dwStartIndex, lpBuffer + dwStartIndex + dwNumStructs, (dwInited - dwNumStructs - dwStartIndex) * sizeof (_Type));
265 
266  dwInited -= dwNumStructs;
267 
268  if (dwStartIndex < dwNum) {
269  if (dwStartIndex + dwNumStructs < dwNum)
270  dwNum -= dwNumStructs;
271  else
272  dwNum = dwStartIndex;
273  }
274 
275  return true;
276 }
277 
278 
279 template <class _Type>
281 {
282  return Delete (0, dwAlloc);
283 }
284 
285 
286 template <class _Type>
288 {
289  if (dwInited <= dwNum)
290  return true;
291 
292  return Delete (dwNum, dwInited - dwNum);
293 }
294 
295 
296 template <class _Type>
297 bool DynamicArray<_Type>::Insert (unsigned long dwStartIndex, unsigned long dwNumStructs)
298 {
299  if (!dwNumStructs)
300  return true;
301 
302  if (!PrepareNext (dwNumStructs))
303  return false;
304 
305  if (dwStartIndex >= dwNum) {
306  dwNum += dwNumStructs;
307  return true;
308  }
309 
310  _Type *tmpObjs = NULL;
311  if (!(tmpObjs = (_Type*)malloc (dwNumStructs * sizeof (_Type))))
312  return false;
313  memcpy (tmpObjs, lpBuffer + dwNum, dwNumStructs * sizeof (_Type));
314 
315  unsigned long dw;
316  for (dw = dwNum + dwNumStructs - 1; dw >= dwStartIndex + dwNumStructs; dw--)
317  lpBuffer[dw] = lpBuffer[dw - dwNumStructs];
318  dwNum += dwNumStructs;
319 
320  memcpy (lpBuffer + dwStartIndex, tmpObjs, dwNumStructs * sizeof (_Type));
321  free (tmpObjs);
322 
323  return true;
324 }
325 
326 
327 template <class _Type>
329 {
330  FreeArray ();
331  if (!src)
332  return true;
333 
334  lpBuffer = (_Type*)malloc (src->dwNum * sizeof (_Type));
335  if (!lpBuffer)
336  return false;
337 
338  dwNum = dwAlloc = dwInited = src->dwNum;
339 
340  unsigned long dw;
341  for (dw = 0; dw < src->dwNum; dw++) {
342  new ((void*)(lpBuffer + dw)) _Type (src->lpBuffer[dw]);
343  }
344 
345  return true;
346 }
347 
348 
349 template <class _Type>
350 bool DynamicArray<_Type>::Swap (unsigned long dwIndex1, unsigned long dwIndex2)
351 {
352  if (dwIndex1 == dwIndex2)
353  return true;
354 
355  if ((dwIndex1 >= dwInited) || (dwIndex2 >= dwInited))
356  return false;
357 
358  _Type tmp;
359 
360  memcpy (&tmp, lpBuffer + dwIndex1, sizeof (_Type));
361  memcpy (lpBuffer + dwIndex1, lpBuffer + dwIndex2, sizeof (_Type));
362  memcpy (lpBuffer + dwIndex2, &tmp, sizeof (_Type));
363 
364  return true;
365 }
366 
367 
368 template <class _Type>
369 bool DynamicArray<_Type>::AddItem (const _Type& newItem)
370 {
371  if (!PrepareNext (1))
372  return false;
373  lpBuffer[dwNum++] = newItem;
374  return true;
375 }
376 
377 
378 template <class _Type>
380 {
381 #ifdef _DEBUG
382 #ifdef WIN32
383  if (dw >= dwAlloc)
384  OutputDebugStringA ("ERROR: DynArray: index error: dw >= dwAlloc\n");
385  if (dw >= dwInited)
386  OutputDebugStringA ("ERROR: DynArray: index error: dw >= dwInited\n");
387 #endif
388 #endif
389  return lpBuffer[dw];
390 }
391 
392 
393 template <class _Type>
394 DAINLINE const _Type &DynamicArray<_Type>::operator[](unsigned long dw) const
395 {
396 #ifdef _DEBUG
397 #ifdef WIN32
398  if (dw >= dwAlloc)
399  OutputDebugStringA ("ERROR: DynArray: index error: dw >= dwAlloc\n");
400  if (dw >= dwInited)
401  OutputDebugStringA ("ERROR: DynArray: index error: dw >= dwInited\n");
402 #endif
403 #endif
404  return lpBuffer[dw];
405 }
406 
407 
408 template <class _Type>
410 {
411 #ifdef _DEBUG
412 #ifdef WIN32
413  unsigned long dw = dwNum - 1;
414  if (dw >= dwAlloc)
415  OutputDebugStringA ("ERROR: DynArray: index error: dw >= dwAlloc\n");
416  if (dw >= dwInited)
417  OutputDebugStringA ("ERROR: DynArray: index error: dw >= dwInited\n");
418 #endif
419 #endif
420 
421  return (lpBuffer[dwNum - 1]);
422 }
423 
424 
425 template <class _Type>
427 {
428 #ifdef _DEBUG
429 #ifdef WIN32
430  unsigned long dw = dwNum;
431  if (dw >= dwAlloc)
432  OutputDebugStringA ("ERROR: DynArray: index error: dw >= dwAlloc\n");
433  if (dw >= dwInited)
434  OutputDebugStringA ("ERROR: DynArray: index error: dw >= dwInited\n");
435 #endif
436 #endif
437 
438  return (lpBuffer[dwNum]);
439 }
440 
441 template <class _Type>
443 {
444  return (*((unsigned long*)(lpBuffer + dwNum)));
445 }
446 
447 template <class _Type>
449 {
450  return (*((int*)(lpBuffer + dwNum)));
451 }
452 
453 template <class _Type>
454 DAINLINE bool DynamicArray<_Type>::StoreByte (unsigned char bData)
455 {
456  if (sizeof (_Type) != 1)
457  return false;
458 
459  if (!PrepareNext (1))
460  return false;
461 
462  *((unsigned char*)(lpBuffer + dwNum)) = bData;
463  dwNum++;
464 
465  return true;
466 }
467 
468 template <class _Type>
469 DAINLINE bool DynamicArray<_Type>::StoreDWORD (unsigned long dwData)
470 {
471  if ((4 % sizeof (_Type)) != 0)
472  return false;
473  if (!PrepareNext (4 / sizeof (_Type)))
474  return false;
475 
476  *((unsigned long*)(lpBuffer + dwNum)) = dwData;
477  dwNum += 4 / sizeof (_Type);
478 
479  return true;
480 }
481 
482 template <class _Type>
484 {
485  return *((unsigned char*)(lpBuffer + (dwNum++)));
486 }
487 
488 template <class _Type>
490 {
491  unsigned long dw = *((unsigned long*)(lpBuffer + dwNum));
492  dwNum += 4 / sizeof (_Type);
493 
494  return dw;
495 }
496 
497 
498 } // VK_NoStepInto_Namespace
499 
500 
502 
503 
504 #endif // DYNAMICARRAY_H