slist.h 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  1. /*
  2. ** Command & Conquer Renegade(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. * Project Name : G *
  21. * *
  22. * File Name : SLIST.H *
  23. * *
  24. * Programmer : Philip W. Gorrow *
  25. * *
  26. * Start Date : 03/11/97 *
  27. * *
  28. * Last Update : March 11, 1997 [PWG] *
  29. * *
  30. * The Single List Class is responsible for all management functions that *
  31. * can be performed on a singular linked list. It uses the SLNode class *
  32. * to track the links and maintain a pointer to the object being tracked. *
  33. * *
  34. * The singlely linked list class is non destructive. That is only *
  35. * pointers to the actual data being stored in the nodes are kept. The *
  36. * users is responsible for creating the objects to be added and deleting *
  37. * the objects once they are removed from the list if they need to be. *
  38. *-------------------------------------------------------------------------*
  39. * Functions: *
  40. * *SList<T>::Remove_Head -- Removes the head of the list *
  41. * *SList<T>::Remove_Tail -- Removes the tail element from the list *
  42. * SList<T>::Get_Count -- Returns a count of the entries in the list *
  43. * *SList<T>::Head -- Returns the head node of the list *
  44. * *SList<T>::Tail -- Returns the tail node of the list *
  45. * SList<T>::Is_Empty -- Returns true if the list is empty *
  46. * SList<T>::Add_Head -- Adds a node to the head of the list *
  47. * SList<T>::Add_Head -- Adds a list to to the head of the list *
  48. * SList<T>::Add_Tail -- Adds a node to the tail of the list *
  49. * SList<T>::Add_Tail -- Adds a list to the tail of the list *
  50. * *SList<T>::Find_Node -- returns first node in list matching the input *
  51. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  52. #if _MSC_VER >= 1000
  53. #pragma once
  54. #endif // _MSC_VER >= 1000
  55. #ifndef __SLIST_H__
  56. #define __SLIST_H__
  57. #include "slnode.h"
  58. #ifndef NULL
  59. #define NULL 0L
  60. #endif
  61. template <class T>
  62. class SList {
  63. private:
  64. SLNode<T> *HeadNode; // Note: Constructor not called for pointer.
  65. SLNode<T> *TailNode;
  66. public:
  67. //
  68. // This constructor is inlined because G++ will not create the
  69. // constructor correctly if it is not defined within the class
  70. // definition.
  71. //
  72. SList(void)
  73. {
  74. HeadNode = NULL;
  75. TailNode = NULL;
  76. };
  77. virtual ~SList(void) { Remove_All(); };
  78. //
  79. // Returns the current head of the list. Used to walk the list.
  80. //
  81. SLNode<T> *Head(void) const;
  82. SLNode<T> *Tail(void) const;
  83. SLNode<T> *Find_Node(T * data) const;
  84. virtual bool Add_Head(T *data); // Add object to head of list
  85. virtual bool Add_Head(SList<T>& list); // Add a list to head of list
  86. virtual bool Add_Tail(T *data); // Add object to tail of list
  87. virtual bool Add_Tail(SList<T>& list); // Add a list to tail of list
  88. virtual T *Remove_Head(void); // Remove head node from list
  89. virtual T *Remove_Tail(void); // Remove tail node from list
  90. virtual bool Remove(T *element); // remove an individual element
  91. virtual void Remove_All(void); // Remove all nodes from list
  92. // Insert before oldnode, if oldnode is NULL then before head node
  93. virtual bool Insert_Before(T *newnode, T *oldnode = NULL);
  94. // Could possibly implement an InsertBefore that operates on a whole list
  95. // Insert after oldnode, if oldnode is NULL then insert at head
  96. virtual bool Insert_After(T *newnode, T *oldnode = NULL);
  97. // Could possibly implement an InsertAfter that operates on a whole list
  98. virtual bool Is_Empty(void) const; // True if list is empty
  99. virtual long Get_Count(void) const; // Returns number of nodes in list
  100. };
  101. /**************************************************************************
  102. * SList<T>::Insert_Before -- Inserts entry prior to specified entry *
  103. * *
  104. * Inserts an entry prior to the specified entry in the list. If the *
  105. * specified entry is null, it will add it prior to the head of the *
  106. * list. Returns true if sucessfully added, false otherwise. *
  107. * *
  108. * INPUT: *
  109. * *
  110. * OUTPUT: *
  111. * *
  112. * WARNINGS: *
  113. * *
  114. * HISTORY: *
  115. * 03/11/1997 PWG : Created. *
  116. *========================================================================*/
  117. template<class T>
  118. bool SList<T>::Insert_Before(T *newnode, T *oldnode)
  119. {
  120. // if not adding anything then just skip the add.
  121. if (newnode == NULL)
  122. return false;
  123. // if there is no head to the list then add it to head
  124. if (oldnode == NULL || HeadNode == NULL || HeadNode->Data() == oldnode) {
  125. return(Add_Head(newnode));
  126. }
  127. // now we need to walk the list in an attempt to add the
  128. // node. since we are a singlely linked list we need
  129. // to stop one prior to the entry.
  130. SLNode<T> *cur;
  131. for (cur=HeadNode; cur->Next() && cur->Next()->Data() != oldnode; cur=cur->Next()) {}
  132. // Verify that we found the entry as it might not have been in the list.
  133. // Note: Cur will be valid because it wont be assigned unless Next is
  134. // valid.
  135. if (cur->Next() != NULL && cur->Next()->Data() == oldnode) {
  136. SLNode<T> *temp = new SLNode<T> (newnode);
  137. temp->Set_Next(cur->Next());
  138. cur->Set_Next(temp);
  139. return(true);
  140. }
  141. return(false);
  142. }
  143. /**************************************************************************
  144. * SList<T>::Insert_After -- Inserts an entry after specified entry *
  145. * *
  146. * Inserts an entry after to the specified entry in the list. If the *
  147. * specified entry is null, it will add it prior to the head of the list. *
  148. * Returns true if sucessfully added, false otherwise. *
  149. * *
  150. * INPUT: *
  151. * *
  152. * OUTPUT: *
  153. * *
  154. * WARNINGS: *
  155. * *
  156. * HISTORY: *
  157. * 03/11/1997 PWG : Created. *
  158. *========================================================================*/
  159. template<class T>
  160. bool SList<T>::Insert_After(T *newnode, T *oldnode)
  161. {
  162. if (newnode == NULL)
  163. return false;
  164. if (oldnode == NULL || HeadNode == NULL) {
  165. return(Add_Head(newnode));
  166. }
  167. // Search for oldnode in list
  168. SLNode<T> *cur;
  169. for (cur = HeadNode; cur && cur->Data() != oldnode; cur = cur->Next()) {}
  170. // Did we find the data we want to insert after?
  171. if (cur != NULL && cur->Data() == oldnode) {
  172. if (cur == TailNode) { // Inserting after tail
  173. return(Add_Tail(newnode));
  174. }
  175. SLNode<T> *temp = new SLNode<T>(newnode);
  176. temp->Set_Next(cur->Next());
  177. cur->Set_Next(temp);
  178. return true;
  179. }
  180. return false;
  181. }
  182. /**************************************************************************
  183. * SList<T>::Remove_All -- Removes all of the entries in the current list *
  184. * *
  185. * INPUT: *
  186. * *
  187. * OUTPUT: *
  188. * *
  189. * WARNINGS: *
  190. * *
  191. * HISTORY: *
  192. * 03/11/1997 PWG : Created. *
  193. *========================================================================*/
  194. template<class T>
  195. void SList<T>::Remove_All(void)
  196. {
  197. SLNode<T> *next;
  198. for (SLNode<T> *cur = HeadNode; cur; cur = next) {
  199. next = cur->Next();
  200. delete cur;
  201. }
  202. HeadNode = TailNode = NULL;
  203. }
  204. /**************************************************************************
  205. * SList<T>::Remove -- Removes an element in the list. *
  206. * *
  207. * INPUT: *
  208. * *
  209. * OUTPUT: true if element could be removed, false if it could not be *
  210. * *
  211. * WARNINGS: *
  212. * *
  213. * HISTORY: *
  214. * 03/11/1997 PWG : Created. *
  215. *========================================================================*/
  216. template<class T>
  217. bool SList<T>::Remove(T *element)
  218. {
  219. // if not adding anything then just skip the add.
  220. if (element == NULL || HeadNode == NULL)
  221. return false;
  222. // if the head is the element in question remove it
  223. if (HeadNode->Data() == element) {
  224. return(Remove_Head() != NULL ? true : false);
  225. }
  226. // now we need to walk the list in an attempt to add the
  227. // node. since we are a singlely linked list we need
  228. // to stop one prior to the entry.
  229. SLNode<T> *cur;
  230. for (cur = HeadNode; cur->Next() && cur->Next()->Data() != element; cur=cur->Next()) { }
  231. // Verify that we found the entry as it might not have been in the list.
  232. // Note: Cur will be valid because it wont be assigned unless Next is
  233. // valid.
  234. if (cur->Next() != NULL && cur->Next()->Data() == element) {
  235. SLNode<T> *temp = cur->Next();
  236. cur->Set_Next(temp->Next());
  237. if (temp == TailNode) TailNode = cur;
  238. delete temp;
  239. return true;
  240. }
  241. return(false);
  242. }
  243. /**************************************************************************
  244. * *SList<T>::Remove_Head -- Removes the head of the list *
  245. * *
  246. * INPUT: *
  247. * *
  248. * OUTPUT: *
  249. * *
  250. * WARNINGS: *
  251. * *
  252. * HISTORY: *
  253. * 03/11/1997 PWG : Created. *
  254. *========================================================================*/
  255. template<class T>
  256. T *SList<T>::Remove_Head(void)
  257. {
  258. if (HeadNode == NULL) // Should make an assertion here instead!
  259. return ((T* )NULL);
  260. SLNode<T> *temp = HeadNode;
  261. HeadNode = HeadNode->Next();
  262. if (HeadNode == NULL) // Do we have empty list now?
  263. TailNode = NULL;
  264. T *data = temp->Data();
  265. delete temp;
  266. return data;
  267. }
  268. //
  269. // Removes the tail of the list and returns a data pointer to the
  270. // element removed. Warning! On a singlely linked list it is
  271. // slow as hell to remove a tail! If you need to frequently remove
  272. // tails, then you should consider a doubly linked list.
  273. //
  274. /**************************************************************************
  275. * *SList<T>::Remove_Tail -- Removes the tail element from the list *
  276. * *
  277. * INPUT: none *
  278. * *
  279. * OUTPUT: returns a pointer to the element removed *
  280. * *
  281. * WARNINGS: On a singlely linked list it is slow as hell to remove a *
  282. * tail! If you need to frequently remove tails, then you *
  283. * should consider a doubly linked list. *
  284. * *
  285. * HISTORY: *
  286. * 03/11/1997 PWG : Created. *
  287. *========================================================================*/
  288. template<class T>
  289. T *SList<T>::Remove_Tail(void)
  290. {
  291. if (HeadNode == NULL) // Should make an assertion here instead!
  292. return ((T *)NULL);
  293. T* data = TailNode->Data();
  294. return (Remove(data) ? data : (T*)NULL);
  295. }
  296. /**************************************************************************
  297. * SList<T>::Get_Count -- Returns a count of the entries in the list *
  298. * *
  299. * INPUT: *
  300. * *
  301. * OUTPUT: *
  302. * *
  303. * WARNINGS: *
  304. * *
  305. * HISTORY: *
  306. * 03/11/1997 PWG : Created. *
  307. *========================================================================*/
  308. template<class T>
  309. inline long SList<T>::Get_Count(void) const
  310. {
  311. long count = 0;
  312. for (SLNode<T> *cur = HeadNode; cur; cur = cur->Next())
  313. count++;
  314. return count;
  315. }
  316. /**************************************************************************
  317. * *SList<T>::Head -- Returns the head node of the list *
  318. * *
  319. * INPUT: *
  320. * *
  321. * OUTPUT: *
  322. * *
  323. * WARNINGS: *
  324. * *
  325. * HISTORY: *
  326. * 03/11/1997 PWG : Created. *
  327. *========================================================================*/
  328. template<class T>
  329. inline SLNode<T> *SList<T>::Head(void) const
  330. {
  331. return(HeadNode);
  332. }
  333. /**************************************************************************
  334. * *SList<T>::Tail -- Returns the tail node of the list *
  335. * *
  336. * INPUT: *
  337. * *
  338. * OUTPUT: *
  339. * *
  340. * WARNINGS: *
  341. * *
  342. * HISTORY: *
  343. * 03/11/1997 PWG : Created. *
  344. *========================================================================*/
  345. template<class T>
  346. inline SLNode<T> *SList<T>::Tail(void) const
  347. {
  348. return(TailNode);
  349. }
  350. /**************************************************************************
  351. * SList<T>::Is_Empty -- Returns true if the list is empty *
  352. * *
  353. * INPUT: *
  354. * *
  355. * OUTPUT: *
  356. * *
  357. * WARNINGS: *
  358. * *
  359. * HISTORY: *
  360. * 03/11/1997 PWG : Created. *
  361. *========================================================================*/
  362. template<class T>
  363. inline bool SList<T>::Is_Empty(void) const
  364. {
  365. return( HeadNode == NULL ? true : false);
  366. }
  367. /**************************************************************************
  368. * SList<T>::Add_Head -- Adds a node to the head of the list *
  369. * *
  370. * INPUT: *
  371. * *
  372. * OUTPUT: *
  373. * *
  374. * WARNINGS: *
  375. * *
  376. * HISTORY: *
  377. * 03/11/1997 PWG : Created. *
  378. *========================================================================*/
  379. template<class T>
  380. bool SList<T>::Add_Head(T *data)
  381. {
  382. // we don't deal with lists that point to nothing
  383. if (!data) return false;
  384. SLNode<T> *temp = new SLNode<T>(data);
  385. temp->Set_Next(HeadNode);
  386. HeadNode = temp;
  387. if (!TailNode) TailNode = temp;
  388. return true;
  389. }
  390. /**************************************************************************
  391. * SList<T>::Add_Head -- Adds a list to to the head of the list *
  392. * *
  393. * INPUT: *
  394. * *
  395. * OUTPUT: *
  396. * *
  397. * WARNINGS: *
  398. * *
  399. * HISTORY: *
  400. * 03/11/1997 PWG : Created. *
  401. *========================================================================*/
  402. template<class T>
  403. bool SList<T>::Add_Head(SList<T>& list)
  404. {
  405. if (list.HeadNode == NULL) return false;
  406. // Save point for initial add of element.
  407. SLNode<T> *addpoint = NULL;
  408. // We traverse list backwards so nodes are added in right order.
  409. for (SLNode<T> *cur = list.HeadNode; cur; cur = cur->Next())
  410. if (addpoint) {
  411. SLNode<T> *temp = new SLNode<T>(cur->Data());
  412. temp->Set_Next(addpoint->Next());
  413. addpoint->Set_Next(temp);
  414. addpoint = temp;
  415. } else {
  416. Add_Head(cur->Data());
  417. addpoint = HeadNode;
  418. }
  419. return true;
  420. }
  421. /**************************************************************************
  422. * SList<T>::Add_Tail -- Adds a node to the tail of the list *
  423. * *
  424. * INPUT: *
  425. * *
  426. * OUTPUT: *
  427. * *
  428. * WARNINGS: *
  429. * *
  430. * HISTORY: *
  431. * 03/11/1997 PWG : Created. *
  432. *========================================================================*/
  433. template<class T>
  434. bool SList<T>::Add_Tail(T *data)
  435. {
  436. if (data == NULL) return false;
  437. SLNode<T> *temp = new SLNode<T> (data);
  438. if (HeadNode == NULL) { // empty list
  439. HeadNode = TailNode = temp;
  440. } else { // non-empty list
  441. TailNode->Set_Next(temp);
  442. TailNode = temp;
  443. }
  444. return true;
  445. }
  446. /**************************************************************************
  447. * SList<T>::Add_Tail -- Adds a list to the tail of the list *
  448. * *
  449. * INPUT: *
  450. * *
  451. * OUTPUT: *
  452. * *
  453. * WARNINGS: *
  454. * *
  455. * HISTORY: *
  456. * 03/11/1997 PWG : Created. *
  457. *========================================================================*/
  458. template<class T>
  459. bool SList<T>::Add_Tail(SList<T>& list)
  460. {
  461. if (list.HeadNode == NULL) return false;
  462. for (SLNode<T> *cur = list.HeadNode; cur; cur = cur->Next())
  463. Add_Tail(cur->Data());
  464. return true;
  465. }
  466. /**************************************************************************
  467. * *SList<T>::Find_Node -- returns first node in list matching the input *
  468. * *
  469. * INPUT: *
  470. * *
  471. * OUTPUT: *
  472. * *
  473. * WARNINGS: *
  474. * *
  475. * HISTORY: *
  476. * 08/22/1997 GH : Created. *
  477. *========================================================================*/
  478. template<class T>
  479. inline SLNode<T> *SList<T>::Find_Node(T * data) const
  480. {
  481. SLNode<T> * cur;
  482. for (cur = HeadNode; cur && cur->Data() != data; cur = cur->Next());
  483. return cur;
  484. }
  485. #endif