Umasoft
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
Array.h
Go to the documentation of this file.
1 //
2 // Array.h
3 //
4 // Copyright (c) 2001-2008 Virtual Terrain Project
5 // Free for all uses, see license.txt for details.
6 //
9 #ifndef ARRAYH
10 #define ARRAYH
11 
12 #ifdef _MSC_VER
13  #pragma warning(disable: 4786)
14  #pragma warning(disable: 4100)
15  #if _DEBUG
16  #define CRTDBG_MAP_ALLOC
17  #include <crtdbg.h>
18  #endif
19 #endif
20 
21 #include <stdlib.h> // for free()
22 #include <memory.h> // for memcpy()
23 #include <assert.h> // for assert()
24 
57 template <class E> class vtArray
58 {
59 public:
60  vtArray(uint size = 0);
61  vtArray(const vtArray<E>&);
62  virtual ~vtArray();
63 
64 // Accessors
65  uint GetSize() const;
66  uint GetMaxSize() const;
67  bool SetSize(uint);
68  bool SetMaxSize(uint);
69  uint GetElemSize() const;
70  E* GetData() const;
71  void FreeData();
72  bool IsEmpty() const;
73  E& GetAt(uint i) const;
74  bool SetAt(uint i, E);
75 
76 // Other operations
77  vtArray<E>& operator=(const vtArray<E>&);
78  E& operator[](uint i);
79  const E& operator[](uint i) const;
80  void Empty();
81  bool RemoveAt(uint i, int n = 1);
82  int Append(const E&);
83  int Append(const vtArray<E>&);
84  int Find(const E&) const;
85 
86 protected:
87 // Internal functions
88  virtual bool Grow(uint);
89  virtual void DestructItems(uint first, uint last);
90 
91 // Data members
92  uint m_Size; // number of elements added so far
93  uint m_MaxSize; // maximum number of elements we have room for
94  E* m_Data; // data area for array
95 };
96 
97 
114 template <class E> vtArray<E>::vtArray(uint size)
115 {
116  m_Size = 0; // empty to start
117  m_MaxSize = 0; // remember the size
118  m_Data = NULL;
119  if (size > 0) // make room for <size> elements
120  Grow(size);
121 }
122 
126 template <class E> void vtArray<E>::FreeData()
127 {
128  Empty();
129  if (m_Data)
130  free(m_Data);
131  m_Data = NULL;
132  m_MaxSize = 0;
133 }
134 
140 template <class E> vtArray<E>::vtArray(const vtArray<E>& a)
141 {
142  if( this == &a )
143  return;
144 
145  m_Size = 0; // empty to start
146  m_MaxSize = 0; // remember the size
147  m_Data = NULL;
148  Append(a); // copy each element from the given array
149 }
150 
151 
174 template <class E> inline void vtArray<E>::DestructItems(uint first, uint last)
175 {
176  //VTLOG("base DestructItems, %d %d\n", start, nitems);
177 }
178 
179 
183 template <class E> inline vtArray<E>::~vtArray()
184 {
185  //VTLOG("~vtArray, size %d, max %d\n", m_Size, m_MaxSize);
186  Empty();
187  free(m_Data);
188  m_Data = NULL;
189  m_MaxSize = 0;
190 }
191 
205 template <class E> bool vtArray<E>::Grow(uint growto)
206 {
207  int n = growto - m_MaxSize;
208  E* old_data;
209 
210  if (n >= 0)
211  {
212  if (m_Data == NULL) // make new data area?
213  {
214 // assert(m_Size == 0);
215  m_Data = (E*) malloc(sizeof(E) * growto);
216  if (m_Data == NULL) // could not enlarge?
217 // ERROR(("vtArray::Grow: out of memory"), false);
218  return false;
219  }
220  else
221  {
222  if (growto < 4) growto = 4; // minimum growth
223  old_data = m_Data;
224  m_Data = (E*) malloc(sizeof(E) * (growto));
225  memcpy(m_Data, old_data, sizeof(E) * m_Size);
226  free(old_data);
227  if (m_Data == NULL)
228 // ERROR(("vtArray::Grow: out of memory"), false);
229  return false;
230  }
231  m_MaxSize = growto; // remember new size
232  }
233  return true;
234 }
235 
236 template <class E> inline E* vtArray<E>::GetData() const
237 {
238  return m_Data;
239 }
240 
254 template <class E> bool vtArray<E>::SetMaxSize(uint s)
255 {
256  if (s > m_MaxSize) // enlarge array
257  return Grow(s); // if we can
258  return true;
259 }
260 
261 template <class E> inline uint vtArray<E>::GetMaxSize() const
262  { return m_MaxSize; }
263 
264 template <class E> inline uint vtArray<E>::GetElemSize() const
265  { return sizeof(E); }
266 
289 template <class E> bool inline vtArray<E>::SetSize(uint s)
290 {
291  assert(s >= 0);
292  if (s > m_MaxSize)
293  if (!Grow(s))
294  return false;
295  m_Size = s;
296  return true;
297 }
298 
299 template <class E> inline uint vtArray<E>::GetSize() const
300  { return m_Size; }
301 
323 template <class E> bool vtArray<E>::SetAt(uint i, E val)
324 {
325  if (i >= m_MaxSize) // need to extend array?
326  {
327  uint n = m_MaxSize;
328  n += (n >> 1); // grow to 1 1/2 times current size
329  if (n <= i) n = i + 1; // unless user wants more
330  if (!Grow(n)) // extend failure
331  return false;
332  }
333  m_Data[i] = val;
334  if (i >= m_Size) // enlarge array size if at end
335  m_Size = i + 1;
336  return true;
337 }
338 
349 template <class E> inline E& vtArray<E>::GetAt(uint i) const
350  { return m_Data[i]; }
351 
352 template <class E> inline const E& vtArray<E>::operator[](uint i) const
353  { return m_Data[i]; }
354 
355 template <class E> inline E& vtArray<E>::operator[](uint i)
356  { return m_Data[i]; }
357 
382 template <class E> int vtArray<E>::Find(const E& elem) const
383 {
384  const E* p = m_Data;
385 
386  for (uint i = 0; i < m_Size; ++i) // look for matching element
387  if (*p++ == elem)
388  return i; // found it
389  return -1;
390 }
391 
414 template <class E> int inline vtArray<E>::Append(const E& v)
415 {
416  int index = m_Size;
417 
418  if (!SetAt(index, v))
419  return -1;
420  return index;
421 }
422 
444 template <class E> bool vtArray<E>::RemoveAt(uint i, int n)
445 {
446  E* elem;
447  int shuffle;
448 
449  if ((i < 0) || (i >= m_Size)) // element out of range?
450  return false;
451  if (n == 0) n = 1; // default is one element
452  shuffle = m_Size - (i + n); // number to shuffle up
453  elem = m_Data + i;
454  memcpy(elem, elem + n, sizeof(E) * shuffle);
455  m_Size -= n;
456  return true;
457 }
458 
479 template <class E> int vtArray<E>::Append(const vtArray<E>& src)
480 {
481  int n = m_Size + src.m_Size;
482 
483  if (!Grow(n))
484  return -1;
485  for (uint i = 0; i < src.m_Size; ++i)
486  m_Data[m_Size + i] = src.m_Data[i];
487  m_MaxSize = n;
488  m_Size += src.m_Size;
489  return n - 1;
490 }
491 
498 template <class E> void vtArray<E>::Empty()
499 {
500  //VTLOG("Empty, size %d\n", m_Size);
501  if (m_Size > 0)
502  DestructItems(0, m_Size - 1);
503  m_Size = 0;
504 }
505 
513 template <class E> inline bool vtArray<E>::IsEmpty() const
514  { return m_Size == 0; }
515 
516 #endif