Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
linkedlist.h
Go to the documentation of this file.
1/*
2** Command & Conquer Generals Zero Hour(tm)
3** Copyright 2025 Electronic Arts Inc.
4**
5** This program is free software: you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation, either version 3 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19/****************************************************************************\
20* C O N F I D E N T I A L --- W E S T W O O D S T U D I O S *
21******************************************************************************
22Project Name:
23File Name : linkedlist.h
24Author : Neal Kettler
25Start Date : June 19, 1997
26Last Update : June 19, 1997
27
28Linked list template. This is a fairly standard doubly linked list that
29allows insertion and removal at any point in the list. A current pointer
30is used to quickly access items when they are examined sequentially.
31Copies of the data are stored instead of a pointer to the original.
32
33If you want to store pointers then the template should be of a pointer type.
34\****************************************************************************/
35
36#ifndef LINKEDLIST_HEADER
37#define LINKEDLIST_HEADER
38
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42#include <assert.h>
43
44#include "wstypes.h"
45
46template <class T>
47class LNode
48{
49 public:
50 T Node;
51 LNode<T> *Next;
52 LNode<T> *Prev;
53};
54
55template <class T>
56class LinkedList
57{
58 public:
62
63 // Remove all entries from the lsit
64 void clear(void);
65
66 // Add a node after the zero based 'pos'
67 bit8 add(IN T &node,sint32 pos, OUT T **newnodeptr=NULL);
68 bit8 addTail(IN T &node, OUT T **newnodeptr=NULL);
69 bit8 addHead(IN T &node, OUT T **newnodeptr=NULL);
70
71 // Remove a node
72 bit8 remove(OUT T &node,sint32 pos);
75 bit8 removeTail(OUT T &node);
76
77
78 // Get a node without removing from the list
79 bit8 get(OUT T &node,sint32 pos);
80 bit8 getHead(OUT T &node);
81 bit8 getTail(OUT T &node);
82
83 // Get a pointer to the internally managed data (careful!)
84 bit8 getPointer(OUT T **node, sint32 pos);
85
86 // Get the number of entries in the list
88
89 // Print information on the list
90 void print(IN FILE *out);
91
92 // assignment operator
94
95 private:
96 sint32 Entries; // Number of entries
97 LNode<T> *Head; // Head of the list
98 LNode<T> *Tail; // Tail of the list
99
100 LNode<T> *Current; // Current pointer & index for speed only
101 sint32 CurIndex;
102};
103
104
105//Create the empty list
106template <class T>
108{
109 Entries=0;
110 Head=Tail=Current=NULL;
111 CurIndex=-1; // Not valid when 0 entries
112}
113
114// copy constructor
115template <class T>
117{
118 Entries=0;
119 Head=Tail=Current=NULL;
120 CurIndex=-1; // Not valid when 0 entries
121 (*this)=other;
122}
123
124//Free all the memory...
125template <class T>
127{
128 clear(); // Remove the entries
129}
130
131// assignment operator
132template <class T>
134{
135 T node;
136 clear();
137 for (int i=0; i<other.length(); i++)
138 {
139 other.get(node,i);
140 addTail(node);
141 }
142 return(*this);
143}
144
145
146// Remove all the entries and free the memory
147template <class T>
149{
150 LNode<T> *temp,*del;
151
152 temp=Head;
153 while (temp) {
154 del=temp;
155 temp=temp->Next;
156 delete(del);
157 }
158 Entries=0;
159 CurIndex=-1;
160 Head=Tail=Current=NULL;
161}
162
163// When adding into a position, the new node goes at the zero based slot
164// specified by pos. All other nodes get moved one slot down.
165template <class T>
166bit8 LinkedList<T>::add(IN T &node,sint32 pos, OUT T **newnodeptr)
167{
168 LNode<T> *temp;
169 LNode<T> *item;
170
171 if (pos<0)
172 pos=0;
173 if (pos>Entries)
174 pos=Entries;
175
176 item=(LNode<T> *)new LNode<T>;
177 assert(item!=NULL);
178 item->Node=node; // copy the passed in object
179 item->Prev=NULL;
180 item->Next=NULL;
181
182 if (newnodeptr)
183 *newnodeptr=&(item->Node);
184
185 if ((pos==0)||(pos==Entries)) { // Both cases can be true for a new list!
186 if (pos==0) {
187 item->Next=Head;
188 if (Head)
189 Head->Prev=item;
190 Head=item;
191 }
192 if (pos==Entries) {
193 item->Prev=Tail;
194 if (Tail)
195 Tail->Next=item;
196 Tail=item;
197 }
198 Entries++;
199 Current=item;
200 CurIndex=pos;
201 return(TRUE);
202 }
203
204 // If control is here, we know the new node is not an endpoint
205
206 // Check for possible speedup, so we don't have to scan the list
207 if (pos==CurIndex) {
208 item->Next=Current;
209 item->Prev=Current->Prev;
210 Current->Prev=item;
211 item->Prev->Next=item;
212 Current=item;
213 Entries++;
214 return(TRUE);
215 }
216 // Check the other possible speedup (adding after CurIndex)
217 if (pos==CurIndex+1) {
218 item->Next=Current->Next;
219 item->Prev=Current;
220 Current->Next=item;
221 item->Next->Prev=item;
222 Current=item;
223 CurIndex++;
224 Entries++;
225 return(TRUE);
226 }
227
228 // If control reaches here we have to scan the whole thing
229 temp=Head->Next; // Can start at node '1' because head was special cased
230 for (int i=1; i<pos; i++) {
231 temp=temp->Next;
232 assert(temp!=NULL);
233 }
234 item->Next=temp;
235 item->Prev=temp->Prev;
236 temp->Prev=item;
237 item->Prev->Next=item;
238 Current=item;
239 CurIndex=pos;
240 Entries++;
241
242 return(TRUE);
243}
244
245
246// Add to the first node, all others get shifted down one slot
247template <class T>
248bit8 LinkedList<T>::addHead(IN T &node, OUT T **newnodeptr)
249{
250 return(add(node,0,newnodeptr));
251}
252
253
254// Append to the end of the list
255template <class T>
256bit8 LinkedList<T>::addTail(IN T &node, OUT T **newnodeptr)
257{
258 return(add(node,length(),newnodeptr));
259}
260
261
262// Remove at the zero based index specified by 'pos'. When removing from
263// a slot, all others get shifted up by one.
264template <class T>
266{
268 LNode<T> *item;
269
270 if (Entries==0)
271 return(FALSE);
272
273 if (pos<0)
274 pos=0;
275 if (pos>=Entries)
276 pos=Entries-1;
277
278 if ((pos==0)||(pos==Entries-1)) { // Both can be true for a 1 item list
279 if (pos==0) {
280 item=Head;
281 if (item->Next)
282 item->Next->Prev=NULL;
283 Head=item->Next;
284 node=item->Node;
285 Current=Head;
286 CurIndex=0;
287 }
288 if (pos==Entries-1) {
289 item=Tail;
290 if (item->Prev)
291 item->Prev->Next=NULL;
292 Tail=item->Prev;
293 node=item->Node;
294 Current=Tail;
295 CurIndex=Entries-2;
296 }
297 delete(item);
298 Entries--;
299
300 if (Entries==0) { // Super paranoia check
301 assert(Current==NULL);
302 assert(CurIndex==-1);
303 assert(Head==NULL);
304 assert(Tail==NULL);
305 }
306 return(TRUE);
307 }
308 // If control is here, we know the target node is not an endpoint
309
310 // Check for possible speedup, so we don't have to scan the list
311 if (pos==CurIndex) {
312 item=Current;
313 item->Prev->Next=item->Next;
314 item->Next->Prev=item->Prev;
315 Current=item->Next;
316 // CurIndex stays the same
317 node=item->Node;
318 delete(item);
319 Entries--;
320 return(TRUE);
321 }
322
323 // Check the other possible speedup (removing after CurIndex)
324 if (pos==CurIndex+1) {
325 item=Current->Next;
326 item->Prev->Next=item->Next;
327 item->Next->Prev=item->Prev;
328 Current=item->Next;
329 CurIndex++;
330 node=item->Node;
331 delete(item);
332 Entries--;
333 return(TRUE);
334 }
335
336
337 // If control reaches here we have to scan the whole thing
338 item=Head->Next; // Can start at node '1' because head was special cased
339 for (int i=1; i<pos; i++) {
340 item=item->Next;
341 assert(item!=NULL);
342 }
343
344 item->Prev->Next=item->Next;
345 item->Next->Prev=item->Prev;
346 Current=item->Next;
347 CurIndex=pos;
348 node=item->Node;
349 delete(item);
350 Entries--;
351
352 return(TRUE);
353}
354
355
356
357
358// Remove at the zero based index specified by 'pos'. When removing from
359// a slot, all others get shifted up by one.
360template <class T>
362{
363 T temp_node;
364 return(remove(temp_node,pos));
365}
366
367
368// Remove the first node of the list
369template <class T>
371{
372 return(remove(node,0));
373}
374
375
376// Remove the last node of the list
377template <class T>
379{
380 return(remove(node,Entries-1));
381}
382
383
384
385template <class T>
386bit8 LinkedList<T>::get(OUT T &node, sint32 pos)
387{
388 T *objptr;
389 bool retval=getPointer(&objptr,pos);
390 if (retval && objptr)
391 node=*objptr;
392
393 return(retval);
394}
395
396
397template <class T>
399{
400 if ((node==0)||(Entries==0))
401 return(FALSE);
402
403 LNode<T> *item;
404
405 if (pos<0)
406 {
407 //pos=0;
408 return(FALSE);
409 }
410 if (pos>=Entries)
411 {
412 //pos=Entries-1;
413 return(FALSE);
414 }
415
416 if (pos==0) {
417 *node=&(Head->Node);
418 return(TRUE);
419 } else if (pos==Entries-1) {
420 *node=&(Tail->Node);
421 return(TRUE);
422 }
423 // If control reaches here, we know target is not an endpoint
424
425 // Check for possible speedup, so we don't have to scan the list
426 if (pos==CurIndex) {
427 *node=&(Current->Node);
428 return(TRUE);
429 } else if (pos==CurIndex+1) {
430 *node=&(Current->Next->Node);
431 CurIndex++;
432 Current=Current->Next;
433 return(TRUE);
434 } else if (pos==CurIndex-1) {
435 *node=&(Current->Prev->Node);
436 CurIndex--;
437 Current=Current->Prev;
438 return(TRUE);
439 }
440
441 // If control reaches here we have to scan the whole thing
442 item=Head->Next; // Can start at node '1' because head was special cased
443 for (int i=1; i<pos; i++) {
444 item=item->Next;
445 assert(item!=NULL);
446 }
447 *node=&(item->Node);
448 CurIndex=pos;
449 Current=item;
450
451 return(TRUE);
452}
453
454
455// Remove the first node of the list
456template <class T>
458{
459 return(get(node,0));
460}
461
462
463// Remove the last node of the list
464template <class T>
466{
467 return(get(node,Entries-1));
468}
469
470
471template <class T>
472void LinkedList<T>::print(IN FILE *out)
473{
474 LNode<T> *temp;
475
476 fprintf(out,"--------------------\n");
477 fprintf(out,"Entries = %d\n",length());
478 fprintf(out,"H = %8p C = %8p (%d) T = %8p\n",Head,Current,CurIndex,Tail);
479
480 temp=Head;
481 while (temp) {
482 fprintf(out," %8p<-((%8p))->%8p \n",temp->Prev,temp,temp->Next);
483 temp=temp->Next;
484 }
485
486 fprintf(out,"--------------------\n");
487}
488
489// Return the current length of the list
490template <class T>
492 return(Entries);
493}
494
495#endif
#define NULL
Definition BaseType.h:92
#define TRUE
Definition BaseType.h:109
#define FALSE
Definition BaseType.h:113
char bit8
Definition wstypes.h:61
#define IN
Definition wstypes.h:57
#define OUT
Definition wstypes.h:58
signed long sint32
Definition bittype.h:51
void add(float *sum, float *addend)
LNode< T > * Next
Definition linkedlist.h:51
LNode< T > * Prev
Definition linkedlist.h:52
bit8 remove(sint32 pos)
bit8 get(OUT T &node, sint32 pos)
bit8 remove(OUT T &node, sint32 pos)
LinkedList(LinkedList< T > &other)
void print(IN FILE *out)
bit8 getPointer(OUT T **node, sint32 pos)
bit8 addHead(IN T &node, OUT T **newnodeptr=NULL)
bit8 getHead(OUT T &node)
sint32 length(void)
LinkedList< T > & operator=(LinkedList< T > &other)
bit8 getTail(OUT T &node)
bit8 removeHead(OUT T &node)
bit8 addTail(IN T &node, OUT T **newnodeptr=NULL)
bit8 add(IN T &node, sint32 pos, OUT T **newnodeptr=NULL)
void clear(void)
bit8 removeTail(OUT T &node)