GL Studio C++ Runtime API
dynamic_array.h
Go to the documentation of this file.
1 /*! \file
2  \brief The disti::DynamicArray class. A templated array of objects capable of dynamically growing.
3 
4  \par Copyright Information
5 
6  Copyright (c) 2017 by The DiSTI Corporation.<br>
7  11301 Corporate Blvd., Suite 100<br>
8  Orlando, Florida 32817<br>
9  USA<br>
10  <br>
11  All rights reserved.<br>
12 
13  This Software contains proprietary trade secrets of DiSTI and may not be
14 reproduced, in whole or part, in any form, or by any means of electronic,
15 mechanical, or otherwise, without the written permission of DiSTI. Said
16 permission may be derived through the purchase of applicable DiSTI product
17 licenses which detail the distribution rights of this content and any
18 Derivative Works based on this or other copyrighted DiSTI Software.
19 
20  NO WARRANTY. THE SOFTWARE IS PROVIDED "AS-IS," WITHOUT WARRANTY OF ANY KIND,
21 AND ANY USE OF THIS SOFTWARE PRODUCT IS AT YOUR OWN RISK. TO THE MAXIMUM EXTENT
22 PERMITTED BY APPLICABLE LAW, DISTI AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES
23 AND CONDITIONS, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
24 IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY AND/OR FITNESS FOR A
25 PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT, WITH REGARD TO THE SOFTWARE.
26 
27  LIMITATION OF LIABILITY. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW,
28 IN NO EVENT SHALL DISTI OR ITS SUPPLIERS BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
29 INDIRECT, OR CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION,
30 DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS
31 INFORMATION, OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR
32 INABILITY TO USE THE SOFTWARE, EVEN IF DISTI HAS BEEN ADVISED OF THE POSSIBILITY
33 OF SUCH DAMAGES. DISTI'S ENTIRE LIABILITY AND YOUR EXCLUSIVE REMEDY SHALL NOT
34 EXCEED FIVE DOLLARS (US$5.00).
35 
36  The aforementioned terms and restrictions are governed by the laws of the
37 State of Florida and the United States of America.
38 
39 */
40 #ifndef INCLUDED_DISTI_DYNAMIC_ARRAY_H
41 #define INCLUDED_DISTI_DYNAMIC_ARRAY_H
42 
43 #include "disti_assert.h"
44 #include "gls_include.h"
45 #include "string.h"
46 
47 namespace disti
48 {
49 // Warn level 4 has trouble with TypeIsSimple parameter since it is a constant
50 #if defined( _MSC_VER )
51 # pragma warning( push, 3 )
52 #endif
53 
54 /**
55  A templated array of objects. The array dynamically resizes as needed.
56  \param TypeIsSimple set to true for types which can be initialized to
57  all zero using memset.
58  If T is a class with a default constructor, a working '=' operator,
59  set TypeIsSimple to false.
60 */
61 template<class T, bool TypeIsSimple = true>
63 {
64 protected:
65  unsigned int _size; /** Number of elements in the array */
66  unsigned int _count; /** Number of elements used */
67  T* _objects; /** Dynamic array is an array of objects */
68 
69  /** Grow the array. If nothing has been allocated yet, set the size to 2 elements. Otherwise double the array size. */
70  void GrowArray( void )
71  {
72  if( !_objects || _size == 0 )
73  Size( 2 );
74  else
75  Size( _size * 2 );
76  }
77 
78 public:
79  typedef T ElementType;
80 
81  /** DynamicArray constructor
82  * \param initialSize The initial number of elements to be allocated for the array
83  */
84  DynamicArray( int initialSize = 0 )
85  {
86  _size = initialSize;
87  _count = 0;
88  _objects = NULL;
89 
90  if( initialSize )
91  Size( initialSize );
92  }
93 
94  DynamicArray( const DynamicArray& other )
95  {
96  _size = 0;
97  _count = 0;
98  _objects = NULL;
99 
100  *this = other;
101  }
102 
103  /** DynamicArray destructor. Clears the array but does not delete the objects being pointed to by the array
104  */
106  {
107  if( _objects )
108  {
109  delete[] _objects;
110  }
111  };
112 
113  /** Set the "Count" value for this array
114  */
115  void Count( const unsigned int count )
116  {
117  _count = count;
118 
119  if( _count > _size )
120  {
121  Size( _count );
122  }
123  }
124 
125  /** Returns the number of elements used of this dynamic array
126  * \return The number of elements used of the array (number of elements)
127  */
128  inline unsigned int Count() const { return _count; }
129 
130  /** Returns the current size of this dynamic array
131  * \return The current size of the array (number of elements)
132  */
133  inline unsigned int Size() const { return _size; }
134 
135  /** Sets the array size to the new size given. Reallocates the array as needed
136  * \param newSize The new number of elements in the array
137  */
138  void Size( unsigned int newSize )
139  {
140  T* newobjs;
141 
142  if( newSize > 0 )
143  {
144  // Test for case when array has not yet been allocated
145  if( !_objects )
146  {
147  _objects = new T[ newSize ];
148  DistiAssert( _objects );
149 
150  if( TypeIsSimple )
151  memset( _objects, 0, newSize * sizeof( T ) );
152 
153  _size = newSize;
154  }
155 
156  // Don't reallocate if the size doesn't change
157  if( newSize == _size )
158  return;
159 
160  newobjs = new T[ newSize ];
161  DistiAssert( newobjs );
162 
163  if( newSize > _size )
164  {
165  if( TypeIsSimple )
166  {
167  // Because it is just a pointer or other simple type,
168  // we can just memcpy the data
169  memcpy( newobjs, _objects, _size * sizeof( T ) );
170  }
171  else
172  {
173  for( unsigned int i = 0; i < _size; i++ )
174  {
175  newobjs[ i ] = _objects[ i ];
176  }
177  }
178 
179  if( TypeIsSimple )
180  memset( newobjs + _size, 0, ( newSize - _size ) * sizeof( T ) );
181  }
182  else
183  {
184  if( TypeIsSimple )
185  {
186  // Because it is just a pointer or other simple type,
187  // we can just memcpy the data
188  memcpy( newobjs, _objects, newSize * sizeof( T ) );
189  }
190  else
191  {
192  for( unsigned int i = 0; i < newSize; i++ )
193  {
194  newobjs[ i ] = _objects[ i ];
195  }
196  }
197  }
198 
199  if( _objects )
200  delete[] _objects;
201 
202  _objects = newobjs;
203  }
204  else // newSize is zero
205  {
206  if( _objects )
207  delete[] _objects;
208 
209  _objects = NULL;
210  }
211 
212  _size = newSize;
213 
214  // Just in case the user shrank the array, reduce count to match size if needed
215  if( _count > _size )
216  _count = _size;
217  }
218 
219  /** Attempts to insert the object into the list at the specified location. If the
220  * specified location is beyond the array bounds, the object is inserted at the next
221  * position in the array.
222  * \param obj The object to insert
223  * \param loc The index location to insert into
224  */
225  void InsertObject( const T& obj, unsigned int loc )
226  {
227  _count++; // we are adding an object, increase the count
228 
229  // Check to see if the count exceeds the size, if so Grow
230  if( _count > _size )
231  {
232  GrowArray();
233  }
234 
235  // If the Location Index exceeds the array bounds,
236  // put the new object at the end of the array
237  if( loc >= _count )
238  {
239  loc = _count - 1;
240  }
241 
242  // Move the array elements up to make room to insert the new element
243  for( unsigned int i = _count - 1; i > loc; i-- )
244  {
245  _objects[ i ] = _objects[ i - 1 ];
246  }
247 
248  _objects[ loc ] = obj; // Insert the new object.
249  }
250 
251  /** Adds the specified object into the list, at the end of the list
252  * \param obj A pointer to the object to add
253  * \return Where the object was inserted
254  */
255  unsigned int InsertObject( const T& obj )
256  {
257  unsigned int rval;
258 
259  rval = _count;
260 
261  InsertObject( obj, _count );
262 
263  return rval;
264  }
265 
266  /** Adds the specified object into the list, at the head of the list
267  * Treats the list like a stack, hence the name Push
268  * \param obj A pointer to the object to add
269  */
270  void PushObject( const T& obj )
271  {
272  InsertObject( obj, 0 );
273  }
274 
275  /** Insert the object into the list at the specified location
276  * \param obj The object to insert
277  * \param loc The index location to insert into
278  */
279  void InsertObjectAfter( const T& obj, unsigned int loc )
280  {
281  InsertObject( obj, loc + 1 );
282  }
283 
284  /** Deletes the specified object from the list. Does not free it
285  * \param obj A pointer to the object to delete
286  * \return true if object was found and deleted else false
287  */
288  bool DeleteObject( const T& obj )
289  {
290  int loc = Position( obj );
291 
292  if( loc >= 0 )
293  return DeleteObjectAtIndex( loc );
294 
295  return false;
296  }
297 
298  /** Deletes the object at the specified index. Does not free it
299  * \param index Index of the object to delete
300  * \return true if object was found and deleted else false
301  */
302  bool DeleteObjectAtIndex( unsigned int index )
303  {
304  if( index >= _count )
305  {
306  return false;
307  }
308  else
309  {
310  for( unsigned int j = index; j < ( _count - 1u ); j++ )
311  {
312  _objects[ j ] = _objects[ j + 1u ];
313  }
314 
315  _count--;
316  }
317  return true;
318  }
319 
320  /** Get the index position of the specified object in the list
321  * \param obj The object to find
322  * \return The index of the object in the list, -1 if it isn't in the list
323  */
324  int Position( const T& obj )
325  {
326  for( unsigned int i = 0; i < _count; i++ )
327  if( obj == _objects[ i ] )
328  return i;
329  return -1;
330  }
331 
332  /** Empties the list, calling delete on all of its elements
333  * This method is intended for pointer data types only.
334  */
335  void EmptyList( void )
336  {
337  for( unsigned int i = 0; i < Count(); i++ )
338  delete _objects[ i ];
339 
340  ClearList();
341  }
342 
343  /** Clears the list so Count() is zero. Does not attempt to delete the objects data */
344  void ClearList( void )
345  {
346  // Clear object array
347  if( _objects )
348  {
349  if( TypeIsSimple )
350  {
351  memset( _objects, 0, sizeof( T ) * _size );
352  }
353  else
354  {
355  // For non simple objects, just delete them all, and
356  // as they are accessed, new ones will be created.
357  delete[] _objects;
358  _objects = NULL;
359  _size = 0;
360  }
361  }
362 
363  _count = 0;
364  }
365 
366  /** Overload of array operator to get element at desired index */
367  T& operator[]( unsigned int index )
368  {
369  DistiAssert( int( index ) >= 0 ); //test for passing in -1, which would resize the array to size 0
370 
371  // This gets an element, resizing the array if needed
372 
373  if( index >= _size )
374  {
375  Size( index + 1 );
376  _count = index + 1;
377  }
378  else if( index >= _count )
379  {
380  _count = index + 1;
381  }
382 
383  return _objects[ index ];
384  }
385 
386  /** Overload of array operator to get element at desired index */
387  const T& operator[]( const unsigned int index ) const
388  {
389  GLS_ASSERT( index < _size && index < _count );
390  return _objects[ index ];
391  }
392 
393  /** Return the internal array pointer
394  * If you call any other methods on this object it invalidates the pointer.*/
396  {
397  return _objects;
398  }
399 
400  /** Return the internal array pointer
401  * If you call any other methods on this object it invalidates the pointer.*/
402  const T* InternalArray() const
403  {
404  return _objects;
405  }
406 
407  /** Overload the assignment operator to create a duplicate of the righthand operand */
409  {
410  Size( right.Size() );
411  for( unsigned int i = 0; i < Size(); i++ )
412  {
413  _objects[ i ] = right._objects[ i ];
414  }
415  _count = right.Count();
416  return *this;
417  }
418 
419  /** \return true if the list is empty */
420  bool IsEmpty( void ) const
421  {
422  return ( _count == 0 );
423  }
424 };
425 
426 /// Overload begin() so that range-for loops and other constructs work with DynamicArray
427 template<class T, bool TypeIsSimple>
429 {
430  if( array.Count() == 0 )
431  {
432  return NULL;
433  }
434  return array.InternalArray();
435 }
436 
437 /// Overload begin() so that range-for loops and other constructs work with DynamicArray
438 template<class T, bool TypeIsSimple>
439 const T* begin( const DynamicArray<T, TypeIsSimple>& array )
440 {
441  if( array.Count() == 0 )
442  {
443  return NULL;
444  }
445  return array.InternalArray();
446 }
447 
448 /// Overload end() so that range-for loops and other constructs work with DynamicArray
449 template<class T, bool TypeIsSimple>
451 {
452  return begin( array ) + array.Count();
453 }
454 
455 /// Overload end() so that range-for loops and other constructs work with DynamicArray
456 template<class T, bool TypeIsSimple>
457 const T* end( const DynamicArray<T, TypeIsSimple>& array )
458 {
459  return begin( array ) + array.Count();
460 }
461 
462 #if defined( _MSC_VER )
463 # pragma warning( pop )
464 #endif
465 
466 } // namespace disti
467 
468 #endif
void ClearList(void)
Definition: dynamic_array.h:344
DynamicArray< T, TypeIsSimple > & operator=(const DynamicArray< T, TypeIsSimple > &right)
Definition: dynamic_array.h:408
unsigned int Count() const
Definition: dynamic_array.h:128
Definition: dynamic_array.h:62
T & operator[](unsigned int index)
Definition: dynamic_array.h:367
T * begin(DynamicArray< T, TypeIsSimple > &array)
Overload begin() so that range-for loops and other constructs work with DynamicArray.
Definition: dynamic_array.h:428
int Position(const T &obj)
Definition: dynamic_array.h:324
void EmptyList(void)
Definition: dynamic_array.h:335
void InsertObjectAfter(const T &obj, unsigned int loc)
Definition: dynamic_array.h:279
unsigned int InsertObject(const T &obj)
Definition: dynamic_array.h:255
bool IsEmpty(void) const
Definition: dynamic_array.h:420
bool DeleteObjectAtIndex(unsigned int index)
Definition: dynamic_array.h:302
void InsertObject(const T &obj, unsigned int loc)
Definition: dynamic_array.h:225
A file for all GL Studio files to include.
void GrowArray(void)
Definition: dynamic_array.h:70
bool DeleteObject(const T &obj)
Definition: dynamic_array.h:288
void Count(const unsigned int count)
Definition: dynamic_array.h:115
T * end(DynamicArray< T, TypeIsSimple > &array)
Overload end() so that range-for loops and other constructs work with DynamicArray.
Definition: dynamic_array.h:450
~DynamicArray(void)
Definition: dynamic_array.h:105
unsigned int _count
Definition: dynamic_array.h:66
T * InternalArray()
Definition: dynamic_array.h:395
void PushObject(const T &obj)
Definition: dynamic_array.h:270
DynamicArray(int initialSize=0)
Definition: dynamic_array.h:84
void Size(unsigned int newSize)
Definition: dynamic_array.h:138
const T * InternalArray() const
Definition: dynamic_array.h:402
const T & operator[](const unsigned int index) const
Definition: dynamic_array.h:387
Contains the DistiAssert macro.
unsigned int Size() const
Definition: dynamic_array.h:133
Definition: bmpimage.h:46
T * _objects
Definition: dynamic_array.h:67
#define GLS_ASSERT(exp)
Definition: disti_assert.h:135