My Project
GrowableArray.h
1 #pragma once
2 //--------------------------------------------------------------------------------------
3 // A growable array
4 //--------------------------------------------------------------------------------------
5 namespace ParaEngine
6 {
7 
8 template< typename TYPE >
10 {
11 public:
12  CGrowableArray() { m_pData = NULL; m_nSize = 0; m_nMaxSize = 0; }
13  CGrowableArray( const CGrowableArray<TYPE>& a ) { for( int i=0; i < a.m_nSize; i++ ) Add( a.m_pData[i] ); }
14  ~CGrowableArray() { RemoveAll(); }
15 
16  const TYPE& operator[]( int nIndex ) const { return GetAt( nIndex ); }
17  TYPE& operator[]( int nIndex ) { return GetAt( nIndex ); }
18 
19  CGrowableArray& operator=( const CGrowableArray<TYPE>& a ) { if( this == &a ) return *this; RemoveAll(); for( int i=0; i < a.m_nSize; i++ ) Add( a.m_pData[i] ); return *this; }
20 
21  HRESULT SetSize( int nNewMaxSize ){
22  int nOldSize = m_nSize;
23 
24  if( nOldSize > nNewMaxSize )
25  {
26  // Removing elements. Call dtor.
27 
28  for( int i = nNewMaxSize; i < nOldSize; ++i )
29  m_pData[i].~TYPE();
30  }
31 
32  // Adjust buffer. Note that there's no need to check for error
33  // since if it happens, nOldSize == nNewMaxSize will be true.)
34  HRESULT hr = SetSizeInternal( nNewMaxSize );
35 
36  if( nOldSize < nNewMaxSize )
37  {
38  // Adding elements. Call ctor.
39 
40  for( int i = nOldSize; i < nNewMaxSize; ++i )
41  ::new (&m_pData[i]) TYPE;
42  }
43 
44  return hr;
45  };
46  HRESULT Add( const TYPE& value ){
47  HRESULT hr;
48  if( FAILED( hr = SetSizeInternal( m_nSize + 1 ) ) )
49  return hr;
50 
51  // Construct the new element
52  ::new (&m_pData[m_nSize]) TYPE;
53 
54  // Assign
55  m_pData[m_nSize] = value;
56  ++m_nSize;
57 
58  return S_OK;
59  };
60  HRESULT Insert( int nIndex, const TYPE& value ){
61  HRESULT hr;
62 
63  // Validate index
64  if( nIndex < 0 ||
65  nIndex > m_nSize )
66  {
67  PE_ASSERT( false );
68  return E_INVALIDARG;
69  }
70 
71  // Prepare the buffer
72  if( FAILED( hr = SetSizeInternal( m_nSize + 1 ) ) )
73  return hr;
74 
75  // Shift the array
76  MoveMemory( &m_pData[nIndex+1], &m_pData[nIndex], sizeof(TYPE) * (m_nSize - nIndex) );
77 
78  // Construct the new element
79  ::new (&m_pData[nIndex]) TYPE;
80 
81  // Set the value and increase the size
82  m_pData[nIndex] = value;
83  ++m_nSize;
84 
85  return S_OK;
86  };
87  HRESULT SetAt( int nIndex, const TYPE& value ){
88  // Validate arguments
89  if( nIndex < 0 ||
90  nIndex >= m_nSize )
91  {
92  PE_ASSERT( false );
93  return E_INVALIDARG;
94  }
95 
96  m_pData[nIndex] = value;
97  return S_OK;
98  };
99  TYPE& GetAt( int nIndex ) { PE_ASSERT( nIndex >= 0 && nIndex < m_nSize ); return m_pData[nIndex]; }
100  int GetSize() const { return m_nSize; }
101  TYPE* GetData() { return m_pData; }
102  bool Contains( const TYPE& value ){ return ( -1 != IndexOf( value ) ); }
103 
104  int IndexOf( const TYPE& value ) { return ( m_nSize > 0 ) ? IndexOf( value, 0, m_nSize ) : -1; }
105  int IndexOf( const TYPE& value, int iStart ) { return IndexOf( value, iStart, m_nSize - iStart ); }
106  int IndexOf( const TYPE& value, int nIndex, int nNumElements );
107 
108  int LastIndexOf( const TYPE& value ) { return ( m_nSize > 0 ) ? LastIndexOf( value, m_nSize-1, m_nSize ) : -1; }
109  int LastIndexOf( const TYPE& value, int nIndex ) { return LastIndexOf( value, nIndex, nIndex+1 ); }
110  int LastIndexOf( const TYPE& value, int nIndex, int nNumElements );
111 
112 HRESULT Remove( int nIndex ){
113  if( nIndex < 0 ||
114  nIndex >= m_nSize )
115  {
116  PE_ASSERT( false );
117  return E_INVALIDARG;
118  }
119 
120  // Destruct the element to be removed
121  m_pData[nIndex].~TYPE();
122 
123  // Compact the array and decrease the size
124  MoveMemory( &m_pData[nIndex], &m_pData[nIndex+1], sizeof(TYPE) * (m_nSize - (nIndex+1)) );
125  --m_nSize;
126 
127  return S_OK;
128 };
129  void RemoveAll() { SetSize(0); };
130 
131 protected:
132  TYPE* m_pData; // the actual array of data
133  int m_nSize; // # of elements (upperBound - 1)
134  int m_nMaxSize; // max allocated
135 
136  HRESULT SetSizeInternal( int nNewMaxSize ){
137  if( nNewMaxSize < 0 )
138  {
139  PE_ASSERT( false );
140  return E_INVALIDARG;
141  }
142 
143  if( nNewMaxSize == 0 )
144  {
145  // Shrink to 0 size & cleanup
146  if( m_pData )
147  {
148  free( m_pData );
149  m_pData = NULL;
150  }
151 
152  m_nMaxSize = 0;
153  m_nSize = 0;
154  }
155  else if( m_pData == NULL || nNewMaxSize > m_nMaxSize )
156  {
157  // Grow array
158  int nGrowBy = ( m_nMaxSize == 0 ) ? 16 : m_nMaxSize;
159  nNewMaxSize = Math::Max( nNewMaxSize, m_nMaxSize + nGrowBy );
160 
161  TYPE* pDataNew = (TYPE*) realloc( m_pData, nNewMaxSize * sizeof(TYPE) );
162  if( pDataNew == NULL )
163  return E_OUTOFMEMORY;
164 
165  m_pData = pDataNew;
166  m_nMaxSize = nNewMaxSize;
167  }
168 
169  return S_OK;
170  }; // This version doesn't call ctor or dtor.
171 };
172 }
Definition: GrowableArray.h:9
different physics engine has different winding order.
Definition: EventBinding.h:32
Definition: enum_maker.hpp:46
static T Max(const T A, const T B)
Returns higher value in a generic way.
Definition: ParaMath.h:462