uLib  User mode C/C++ extended API library for Win32 programmers.
DynArray.cpp
Go to the documentation of this file.
1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2 // Project: uLib - User mode library.
3 // Module: DynArray -- Dynamic arrays in C++
4 // Author: Copyright (c) Love Nystrom 1999
5 // License: NNOSL (BSD descendant, see NNOSL.txt in the base directory).
6 // Credits: Someone at Borland International (original Pascal class).
7 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 
9 #include <uLib/DynArray.h>
10 #include <uLib/MemFunc.h>
11 
13 
14 // Protected identifiers preceded with one underscore.
15 // Private identifiers preceded with two underscores.
16 
17 void* DynArray::__alloc( size_t Bytes ) {
18  return mem_Alloc( Bytes );
19  }
20 
21 void* DynArray::__realloc( void* pBlk, size_t Bytes ) {
22  if (!pBlk) return mem_Alloc( Bytes );
23  else return mem_Realloc( pBlk, Bytes );
24  }
25 
26 void* DynArray::__free( void* pBlk ) {
27  return mem_Free( pBlk ); // I.e: pFoo = __free( pFoo );
28  }
29 
30 #ifdef _MSC_VER
31 #pragma warning( disable: 4355 ) // 'this' in base member initializer list
32 #endif
33 
34 DynArray::DynArray( DWORD dwSize, WORD wDelta )
35 : Count(_count), Size(_size), Items(*this) // Self-ref to access operator[] via a pointer.
36 {
37  _count = 0;
38  _items = NULL;
39  Init( dwSize, wDelta );
40 }
41 
42 #ifdef _MSC_VER
43 #pragma warning( default: 4355 )
44 #endif
45 
46 DynArray::~DynArray() // virtual
47 {
48  Done();
49 }
50 
51 void DynArray::Init( DWORD dwSize, WORD wDelta )
52 {
53  Done(); // Dispose old items (if any).
54  dwSize = dwSize ? ROUND_UP( dwSize, wDelta ) : wDelta;
55 
56  _count = 0;
57  _delta = wDelta;
58  #if USE_DYNARRAY_LIMIT
59  _size = (dwSize <= MAX_DYNITEM) ? dwSize : MAX_DYNITEM;
60  #else
61  _size = dwSize;
62  #endif
63  _items = _size ? (PVOID*)__alloc( _size*sizeof(PVOID) ) : NULL;
64 }
65 
67 {
68  if (_count) DeleteAll();
69  if (_items) _items = (PVOID*)__free( _items );
70 }
71 
72 PVOID DynArray::Insert( PVOID Item )
73 {
74  #if USE_DYNARRAY_LIMIT
75  if( Item == NULL || _count == MAX_DYNITEM )
76  #else
77  if (Item == NULL)
78  #endif
79  return NULL; // failure, ret NULL
80 
81  PVOID tmp = _items;
82  _count++;
83  if (_count > _size) { // Only place that deals with reallocation
84  _size += _delta;
85  #if USE_DYNARRAY_LIMIT
86  if (_size > MAX_DYNITEM) _size = MAX_DYNITEM;
87  #endif
88  size_t nbytes = _size*sizeof(PVOID);
89  tmp = _items ? __realloc( _items,nbytes ) : __alloc( nbytes );
90  if (tmp) { // SUCCESS
91  _items = (PVOID*) tmp; // set items PVOID, and..
92  } else { // FAILURE
93  tmp = NULL; // signal failure by returning NULL
94  _size -= _delta; // reset previous
95  _count--; // reset previous
96  }
97  }
98  if (tmp) {
99  _items[_count-1] = Item;
100  tmp = Item; // signal success by returning Item
101  }
102  return tmp;
103 }
104 
105 PVOID DynArray::InsertAt( DWORD Index,PVOID Item )
106 {
107  // Begin by inserting Item at end of collection (to adjust count etc)
108 
109  PVOID p = DynArray::Insert( Item ); // Force use of base class method
110  if ((Index >= (_count-1)) || (!p))
111  return p;
112 
113  // Index not at end, so make a hole at index and set p at index position
114 
115  size_t nbytes = (_count-Index-1)*sizeof(PVOID);
116  memmove( &_items[Index+1], &_items[Index], nbytes ); // shove upward
117  _items[Index] = p;
118  return p;
119 }
120 
121 PVOID DynArray::Push( PVOID Item ) // Insert Item into stack/fifo
122 {
123  return Insert( Item );
124 }
125 
126 PVOID DynArray::Pull( void ) // Push/Pull = FIFO action
127 {
128  return Remove( (DWORD) 0 );
129 }
130 
131 PVOID DynArray::Pop( void ) // Push/Pop = stack action
132 {
133  return Remove( _count-1 );
134 }
135 
136 void DynArray::DeleteItem( PVOID& Item )
137 {
138  mem_Free( Item );
139  Item = NULL;
140 }
141 
142 void DynArray::Delete( PVOID& Item )
143 {
144  LONG index = IndexOf( Item );
145  if (index >= 0) Delete( index );
146 }
147 
148 void DynArray::Delete( DWORD Index )
149 {
150  if (Index >= _count) return;
151  DeleteItem( _items[Index] );
152  Remove( Index );
153 }
154 
156 {
157  while( _count ) Delete( _count-1 );
158 }
159 
160 PVOID DynArray::Remove( PVOID Item )
161 {
162  LONG index = IndexOf( Item );
163  return (index >= 0) ? Remove( index ) : NULL;
164 }
165 
166 PVOID DynArray::Remove( DWORD Index )
167 {
168  if (Index >= _count) return NULL;
169  PVOID item = At( Index );
170  _count--;
171  DWORD bytes = (_count-Index)*sizeof(PVOID);
172  if (bytes) memmove( &_items[Index], &_items[Index+1], bytes ); // Contract
173  _items[_count] = NULL;
174  return item;
175 }
176 
177 LONG DynArray::IndexOf( PVOID Item ) const
178 {
179  if( Item != NULL )
180  for( DWORD i=0; i<_count; i++ ) // This can get inefficient on big counts
181  if (_items[i] == Item) return LONG( i ); // but there is no alternative.
182  return -1;
183 }
184 
185 PVOID DynArray::At( DWORD Index ) const
186 {
187  if (Index >= _count) return NULL;
188  return _items[Index];
189 }
190 
191 PVOID DynArray::FirstThat( DYN_ITEMFUNC Match, PVOID userData ) const
192 {
193  for( DWORD i=0; i<_count; i++ )
194  if (Match( _items[i],userData ))
195  return _items[i];
196  return NULL;
197 }
198 
199 PVOID DynArray::LastThat( DYN_ITEMFUNC Match, PVOID userData ) const
200 {
201  for( DWORD i=_count; i>0; i-- )
202  if (Match( _items[i-1],userData ))
203  return _items[i-1];
204  return NULL;
205 }
206 
207 bool DynArray::ForEach( DYN_ITEMFUNC Action, PVOID userData ) const
208 {
209  for( DWORD i=0; i<_count; i++ )
210  if( !Action( _items[i],userData ))
211  return false;
212  return true;
213 }
214 
215 // ------------------------------------------------------------------------
216 
218 : DynArray( dwSize, wDelta )
219 {
220  Duplicates = false;
221 }
222 
223 PVOID SortDynArray::KeyOf( PVOID Item )
224 {
225  return Item;
226 }
227 
228 short SortDynArray::Compare( PVOID Item1, PVOID Item2 )
229 {
230  // Base method assumes items are strings, and collates per default C(++).
231  if (!Item1) return 1; else if (!Item2) return -1;
232  return _tcscmp( (TSTR)Item1, (TSTR)Item2 );
233 }
234 
235 bool SortDynArray::Search( PVOID Key, DWORD& Index )
236 {
237  // Linear search.. Inefficient as hell, but works if the array is not too big.
238  // PONDER: Implement iterative binary search here..?
239  for( Index=0; Index < _count; Index++ ) {
240  PVOID itemKey = _items[ Index ];
241  if (itemKey) itemKey = KeyOf( itemKey );
242  if (!itemKey) break;
243  int cmp = Compare( itemKey, Key );
244  if (cmp == 0) return true; // Item was found, return it's index
245  else if (cmp > 0) return false; // Item would have been here if it existed
246  }
247  // No key equal or bigger than Key was found, Index equals Count
248  return false;
249 }
250 
251 PVOID SortDynArray::Insert( PVOID Item )
252 {
253  if (!Item) return NULL;
254  DWORD ix;
255  if (!Search( KeyOf(Item),ix )) return InsertAt( ix, Item );
256  else if (Duplicates) return InsertAt( ix+1, Item );
257  else return NULL;
258 }
259 
261 // EOF
unsigned long DWORD
Definition: Common.h:414
PVOID Insert(PVOID Item)
Definition: DynArray.cpp:72
unsigned short WORD
Definition: Common.h:413
void * mem_Realloc(void *pBlk, size_t Bytes)
Definition: MemFunc.cpp:80
void * mem_Alloc(size_t Bytes)
Definition: MemFunc.cpp:33
virtual void DeleteAll(void)
Definition: DynArray.cpp:155
#define TSTR
Definition: Common.h:328
#define END_NAMESPACE(name)
Definition: Common.h:225
virtual ~DynArray()
Definition: DynArray.cpp:46
bool(CALLBACK * DYN_ITEMFUNC)(PVOID Item, PVOID UserData)
Definition: DynArray.h:43
PVOID Pop(void)
Definition: DynArray.cpp:131
void Init(DWORD Size, WORD Delta)
Definition: DynArray.cpp:51
void Delete(PVOID &Item)
<
Definition: DynArray.cpp:142
PVOID Push(PVOID Item)
Definition: DynArray.cpp:121
PVOID Remove(PVOID Item)
Definition: DynArray.cpp:160
PVOID InsertAt(DWORD Index, PVOID Item)
Definition: DynArray.cpp:105
PVOID Pull(void)
Definition: DynArray.cpp:126
void * mem_Free(void *pBlk)
Definition: MemFunc.cpp:124
Definition: DynArray.h:18
PVOID FirstThat(DYN_ITEMFUNC Match, PVOID userData) const
Definition: DynArray.cpp:191
PVOID At(DWORD Index) const
Definition: DynArray.cpp:185
#define ROUND_UP(x, chunk)
Definition: Common.h:979
virtual short Compare(PVOID Key1, PVOID Key2)
Definition: DynArray.cpp:228
virtual void DeleteItem(PVOID &Item)
Definition: DynArray.cpp:136
LONG IndexOf(PVOID Item) const
Definition: DynArray.cpp:177
SortDynArray(DWORD Size=16, WORD Delta=16)
Definition: DynArray.cpp:217
virtual PVOID KeyOf(PVOID Item)
Definition: DynArray.cpp:223
#define BEGIN_NAMESPACE(name)
Definition: Common.h:224
bool ForEach(DYN_ITEMFUNC Action, PVOID userData) const
Definition: DynArray.cpp:207
PVOID LastThat(DYN_ITEMFUNC Match, PVOID userData) const
Definition: DynArray.cpp:199
bool Search(PVOID Key, DWORD &Index)
Definition: DynArray.cpp:235
PVOID Insert(PVOID Item)
Definition: DynArray.cpp:251