Starshatter_Open
Open source Starshatter engine
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
List.inl
Go to the documentation of this file.
1 /* Project FoundationEx
2  Destroyer Studios LLC
3  Copyright © 1997-2004. All Rights Reserved.
4 
5  SUBSYSTEM: FoundationEx
6  FILE: List.inl
7  AUTHOR: John DiCamillo
8 
9 
10  OVERVIEW
11  ========
12  Implementation of the List class template
13 */
14 
15 // +-------------------------------------------------------------------+
16 
17 void Print(const char* fmt, ...);
18 
19 // +-------------------------------------------------------------------+
20 
21 template <class T>
23  : items(l.items), extent(l.extent)
24 {
25 #ifdef MEM_DEBUG
26  array = new(__FILE__,__LINE__) PTR[extent];
27 #else
28  array = new PTR[extent];
29 #endif
30 
31  for (int i = 0; i < extent; i++)
32  array[i] = l.array[i];
33 }
34 
35 template <class T>
37 {
38  delete [] array;
39  items = 0;
40  extent = 0;
41  array = 0;
42 }
43 
44 template <class T>
46 {
47  if (items) {
48  items = 0; // prevent dangerous re-entrancy
49 
50  for (int i = 0; i < extent; i++)
51  delete array[i];
52 
53  delete [] array;
54  items = 0;
55  extent = 0;
56  array = 0;
57  }
58 }
59 
60 // +-------------------------------------------------------------------+
61 
62 template <class T>
63 bool List<T>::check(int& index) const
64 {
65  if (index < 0) {
66  Print("Bounds error in List(%08x) T=%s index=%d min=0\n", (int)this, T::TYPENAME(), index);
67  index = 0;
68  }
69 
70  else if (index >= items) {
71  Print("Bounds error in List(%08x) T=%s index=%d max=%d\n", (int)this, T::TYPENAME(), index, items-1);
72  index = items-1;
73  }
74 
75  return (index >= 0 && index < items);
76 }
77 
78 // +-------------------------------------------------------------------+
79 
80 template <class T>
81 T*& List<T>::operator[](int index)
82 {
83  if (check(index))
84  return array[index];
85 
86  if (!array || !extent)
87  resize(1);
88 
89  return array[0];
90 }
91 
92 template <class T>
93 T* List<T>::operator[](int index) const
94 {
95  if (check(index))
96  return array[index];
97  return 0;
98 }
99 
100 template <class T>
101 T*& List<T>::at(int index)
102 {
103  if (check(index))
104  return array[index];
105 
106  if (!array || !extent)
107  resize(1);
108 
109  return array[0];
110 }
111 
112 template <class T>
113 T* List<T>::at(int index) const
114 {
115  if (check(index))
116  return array[index];
117  return 0;
118 }
119 
120 // +-------------------------------------------------------------------+
121 
122 template <class T>
123 void List<T>::resize(int newsize)
124 {
125  if (newsize > extent) {
126  extent = 16 * (newsize/16 + 1);
127 
128 #ifdef MEM_DEBUG
129  T** v = new(__FILE__,__LINE__) PTR[extent];
130 #else
131  T** v = new PTR[extent];
132 #endif
133  int i;
134  for (i = 0; i < items; i++)
135  v[i] = array[i];
136 
137  for (; i < extent; i++)
138  v[i] = 0;
139 
140  delete [] array;
141  array = v;
142  }
143 }
144 
145 // +-------------------------------------------------------------------+
146 
147 template <class T>
148 void List<T>::append(const T* item)
149 {
150  if (item) {
151  if (items+1 > extent) resize(items+1);
152  array[items++] = (T*)item;
153  }
154 }
155 
156 template <class T>
158 {
159  if (&list != this && list.items > 0) {
160  int need = items + list.items;
161  if (need > extent) resize(need);
162 
163  for (int i = 0; i < list.items; i++)
164  array[items++] = list.array[i];
165  }
166 }
167 
168 // +-------------------------------------------------------------------+
169 
170 template <class T>
171 void List<T>::insert(const T* item, int index)
172 {
173  if (item && index >= 0 && index <= items) {
174  if (items+1 > extent) resize(items+1);
175 
176  // slide right:
177  for (int i = items; i > index; i--)
178  array[i] = array[i-1];
179 
180  array[index] = (T*)item;
181  items++;
182  }
183 }
184 
185 // +-------------------------------------------------------------------+
186 
187 template <class T>
188 void List<T>::insertSort(const T* item)
189 {
190  if (item) {
191  int i;
192  for (i = 0; i < items; i++) {
193  if (*item < *array[i])
194  break;
195  }
196 
197  insert(item, i);
198  }
199 }
200 
201 // +-------------------------------------------------------------------+
202 
203 template <class T>
204 T* List<T>::remove(const T* val)
205 {
206  if (items == 0 || val == 0)
207  return 0;
208 
209  for (int i = 0; i < items; i++) {
210  if (array[i] == val) {
211  return removeIndex(i);
212  }
213  }
214 
215  return 0;
216 }
217 
218 // +-------------------------------------------------------------------+
219 
220 template <class T>
221 T* List<T>::removeIndex(int index)
222 {
223  if (!check(index))
224  return 0;
225 
226  T* tmp = array[index];
227  array[index] = 0;
228 
229  // slide left:
230  for (int i = index; i < items-1; i++)
231  array[i] = array[i+1];
232 
233  // blank out the hole we just created:
234  array[items-1] = 0;
235 
236  items--;
237  return tmp;
238 }
239 
240 // +-------------------------------------------------------------------+
241 
242 template <class T>
243 bool List<T>::contains(const T* val) const
244 {
245  if (val) {
246  if (index(val) != -1)
247  return true;
248  }
249 
250  return false;
251 }
252 
253 // +-------------------------------------------------------------------+
254 
255 template <class T>
256 int List<T>::count(const T* val) const
257 {
258  int c = 0;
259 
260  if (val) {
261  for (int i = 0; i < items; i++) {
262  if (array[i] && ((*array[i])==(*val)))
263  c++;
264  }
265  }
266 
267  return c;
268 }
269 
270 // +-------------------------------------------------------------------+
271 
272 template <class T>
273 int List<T>::index(const T* val) const
274 {
275  if (val) {
276  for (int i = 0; i < items; i++) {
277  if (array[i] && ((*array[i])==(*val)))
278  return i;
279  }
280  }
281 
282  return -1;
283 }
284 
285 // +-------------------------------------------------------------------+
286 
287 template <class T>
288 T* List<T>::find(const T* val) const
289 {
290  if (val) {
291  for (int i = 0; i < items; i++) {
292  if (array[i] && ((*array[i])==(*val)))
293  return array[i];
294  }
295  }
296 
297  return 0;
298 }
299 
300 // +-------------------------------------------------------------------+
301 
302 template <class T>
303 void List<T>::swap(T** a, int i, int j)
304 {
305  if (i >= 0 && i < items && j >= 0 && j < items && i != j) {
306  T* t = a[i];
307  a[i] = a[j];
308  a[j] = t;
309  }
310 }
311 
312 template <class T>
313 void List<T>::qsort(T** a, int lo0, int hi0)
314 {
315  int lo = lo0;
316  int hi = hi0;
317 
318  // zero or one element list, nothing to do:
319  if (lo >= hi) {
320  return;
321  }
322 
323  // two element list, swap if needed:
324  else if (lo == hi-1) {
325  if (*a[hi] < *a[lo]) {
326  swap(a, lo, hi);
327  }
328  return;
329  }
330 
331  // pick a pivot, and move it out of the way:
332  int mid = (lo+hi)/2;
333  T* pivot = a[mid];
334  a[mid] = a[hi];
335  a[hi] = pivot;
336 
337  while (lo < hi) {
338  while ((*a[lo] <= *pivot) && lo < hi) lo++;
339  while ((*pivot <= *a[hi]) && lo < hi) hi--;
340 
341  if (lo < hi) {
342  swap(a, lo, hi);
343  }
344  }
345 
346  // Put the pivot into its final location:
347  a[hi0] = a[hi];
348  a[hi] = pivot;
349 
350  qsort(a, lo0, lo-1);
351  qsort(a, hi+1, hi0);
352 }
353 
354 template <class T>
356 {
357  if (items < 2)
358  return;
359 
360  qsort(array, 0, items-1);
361 }
362 
363 template <class T>
365 {
366  if (items < 3)
367  return;
368 
369  for (int s = 0; s < 5; s++) {
370  for (int i = 0; i < items; i++) {
371  int j = (rand()>>4) % items;
372  swap(array, i, j);
373  }
374  }
375 }
376 
377 // +===================================================================+
378 
379 template <class T>
381 {
382  if (list && step >= 0 && step < list->items)
383  return list->array[step];
384 
385  return 0;
386 }
387 
388 // +-------------------------------------------------------------------+
389 
390 template <class T>
392 {
393  if (list && step >= 0 && step < list->items)
394  return list->removeIndex(step--);
395 
396  return 0;
397 }
398 
399 // +-------------------------------------------------------------------+
400 
401 template <class T>
403 {
404  if (list && step >= -1 && step < list->items-1)
405  return list->array[++step];
406 
407  return 0;
408 }
409 
410 template <class T>
412 {
413  if (list && step > 0 && step < list->items)
414  return list->array[--step];
415 
416  return 0;
417 }
418 
419 // +-------------------------------------------------------------------+
420 
421 template <class T>
423 {
424  list = &l;
425  step = -1;
426 }
427 
428 // +-------------------------------------------------------------------+
429 
430 template <class T>
432 {
433  if (!list) return 0;
434  return list->items;
435 }
436 
437 // +-------------------------------------------------------------------+
438 
439 template <class T>
441 {
442  return *list;
443 }
444