| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545 |
- /*
- ** Command & Conquer Renegade(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /***************************************************************************
- * *
- * Project Name : G *
- * *
- * File Name : SLIST.H *
- * *
- * Programmer : Philip W. Gorrow *
- * *
- * Start Date : 03/11/97 *
- * *
- * Last Update : March 11, 1997 [PWG] *
- * *
- * The Single List Class is responsible for all management functions that *
- * can be performed on a singular linked list. It uses the SLNode class *
- * to track the links and maintain a pointer to the object being tracked. *
- * *
- * The singlely linked list class is non destructive. That is only *
- * pointers to the actual data being stored in the nodes are kept. The *
- * users is responsible for creating the objects to be added and deleting *
- * the objects once they are removed from the list if they need to be. *
- *-------------------------------------------------------------------------*
- * Functions: *
- * *SList<T>::Remove_Head -- Removes the head of the list *
- * *SList<T>::Remove_Tail -- Removes the tail element from the list *
- * SList<T>::Get_Count -- Returns a count of the entries in the list *
- * *SList<T>::Head -- Returns the head node of the list *
- * *SList<T>::Tail -- Returns the tail node of the list *
- * SList<T>::Is_Empty -- Returns true if the list is empty *
- * SList<T>::Add_Head -- Adds a node to the head of the list *
- * SList<T>::Add_Head -- Adds a list to to the head of the list *
- * SList<T>::Add_Tail -- Adds a node to the tail of the list *
- * SList<T>::Add_Tail -- Adds a list to the tail of the list *
- * *SList<T>::Find_Node -- returns first node in list matching the input *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #if _MSC_VER >= 1000
- #pragma once
- #endif // _MSC_VER >= 1000
- #ifndef __SLIST_H__
- #define __SLIST_H__
- #include "slnode.h"
- #ifndef NULL
- #define NULL 0L
- #endif
- template <class T>
- class SList {
- private:
- SLNode<T> *HeadNode; // Note: Constructor not called for pointer.
- SLNode<T> *TailNode;
- public:
- //
- // This constructor is inlined because G++ will not create the
- // constructor correctly if it is not defined within the class
- // definition.
- //
- SList(void)
- {
- HeadNode = NULL;
- TailNode = NULL;
- };
- virtual ~SList(void) { Remove_All(); };
- //
- // Returns the current head of the list. Used to walk the list.
- //
- SLNode<T> *Head(void) const;
- SLNode<T> *Tail(void) const;
- SLNode<T> *Find_Node(T * data) const;
- virtual bool Add_Head(T *data); // Add object to head of list
- virtual bool Add_Head(SList<T>& list); // Add a list to head of list
- virtual bool Add_Tail(T *data); // Add object to tail of list
- virtual bool Add_Tail(SList<T>& list); // Add a list to tail of list
- virtual T *Remove_Head(void); // Remove head node from list
- virtual T *Remove_Tail(void); // Remove tail node from list
- virtual bool Remove(T *element); // remove an individual element
- virtual void Remove_All(void); // Remove all nodes from list
- // Insert before oldnode, if oldnode is NULL then before head node
- virtual bool Insert_Before(T *newnode, T *oldnode = NULL);
- // Could possibly implement an InsertBefore that operates on a whole list
- // Insert after oldnode, if oldnode is NULL then insert at head
- virtual bool Insert_After(T *newnode, T *oldnode = NULL);
- // Could possibly implement an InsertAfter that operates on a whole list
- virtual bool Is_Empty(void) const; // True if list is empty
- virtual long Get_Count(void) const; // Returns number of nodes in list
- };
- /**************************************************************************
- * SList<T>::Insert_Before -- Inserts entry prior to specified entry *
- * *
- * Inserts an entry prior to the specified entry in the list. If the *
- * specified entry is null, it will add it prior to the head of the *
- * list. Returns true if sucessfully added, false otherwise. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 03/11/1997 PWG : Created. *
- *========================================================================*/
- template<class T>
- bool SList<T>::Insert_Before(T *newnode, T *oldnode)
- {
- // if not adding anything then just skip the add.
- if (newnode == NULL)
- return false;
- // if there is no head to the list then add it to head
- if (oldnode == NULL || HeadNode == NULL || HeadNode->Data() == oldnode) {
- return(Add_Head(newnode));
- }
- // now we need to walk the list in an attempt to add the
- // node. since we are a singlely linked list we need
- // to stop one prior to the entry.
- SLNode<T> *cur;
- for (cur=HeadNode; cur->Next() && cur->Next()->Data() != oldnode; cur=cur->Next()) {}
- // Verify that we found the entry as it might not have been in the list.
- // Note: Cur will be valid because it wont be assigned unless Next is
- // valid.
- if (cur->Next() != NULL && cur->Next()->Data() == oldnode) {
- SLNode<T> *temp = new SLNode<T> (newnode);
- temp->Set_Next(cur->Next());
- cur->Set_Next(temp);
- return(true);
- }
- return(false);
- }
- /**************************************************************************
- * SList<T>::Insert_After -- Inserts an entry after specified entry *
- * *
- * Inserts an entry after to the specified entry in the list. If the *
- * specified entry is null, it will add it prior to the head of the list. *
- * Returns true if sucessfully added, false otherwise. *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 03/11/1997 PWG : Created. *
- *========================================================================*/
- template<class T>
- bool SList<T>::Insert_After(T *newnode, T *oldnode)
- {
- if (newnode == NULL)
- return false;
- if (oldnode == NULL || HeadNode == NULL) {
- return(Add_Head(newnode));
- }
- // Search for oldnode in list
- SLNode<T> *cur;
- for (cur = HeadNode; cur && cur->Data() != oldnode; cur = cur->Next()) {}
- // Did we find the data we want to insert after?
- if (cur != NULL && cur->Data() == oldnode) {
- if (cur == TailNode) { // Inserting after tail
- return(Add_Tail(newnode));
- }
- SLNode<T> *temp = new SLNode<T>(newnode);
- temp->Set_Next(cur->Next());
- cur->Set_Next(temp);
- return true;
- }
- return false;
- }
- /**************************************************************************
- * SList<T>::Remove_All -- Removes all of the entries in the current list *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 03/11/1997 PWG : Created. *
- *========================================================================*/
- template<class T>
- void SList<T>::Remove_All(void)
- {
- SLNode<T> *next;
- for (SLNode<T> *cur = HeadNode; cur; cur = next) {
- next = cur->Next();
- delete cur;
- }
- HeadNode = TailNode = NULL;
- }
- /**************************************************************************
- * SList<T>::Remove -- Removes an element in the list. *
- * *
- * INPUT: *
- * *
- * OUTPUT: true if element could be removed, false if it could not be *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 03/11/1997 PWG : Created. *
- *========================================================================*/
- template<class T>
- bool SList<T>::Remove(T *element)
- {
- // if not adding anything then just skip the add.
- if (element == NULL || HeadNode == NULL)
- return false;
- // if the head is the element in question remove it
- if (HeadNode->Data() == element) {
- return(Remove_Head() != NULL ? true : false);
- }
- // now we need to walk the list in an attempt to add the
- // node. since we are a singlely linked list we need
- // to stop one prior to the entry.
- SLNode<T> *cur;
- for (cur = HeadNode; cur->Next() && cur->Next()->Data() != element; cur=cur->Next()) { }
- // Verify that we found the entry as it might not have been in the list.
- // Note: Cur will be valid because it wont be assigned unless Next is
- // valid.
- if (cur->Next() != NULL && cur->Next()->Data() == element) {
- SLNode<T> *temp = cur->Next();
- cur->Set_Next(temp->Next());
- if (temp == TailNode) TailNode = cur;
- delete temp;
- return true;
- }
- return(false);
- }
- /**************************************************************************
- * *SList<T>::Remove_Head -- Removes the head of the list *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 03/11/1997 PWG : Created. *
- *========================================================================*/
- template<class T>
- T *SList<T>::Remove_Head(void)
- {
- if (HeadNode == NULL) // Should make an assertion here instead!
- return ((T* )NULL);
-
- SLNode<T> *temp = HeadNode;
- HeadNode = HeadNode->Next();
- if (HeadNode == NULL) // Do we have empty list now?
- TailNode = NULL;
- T *data = temp->Data();
- delete temp;
- return data;
- }
- //
- // Removes the tail of the list and returns a data pointer to the
- // element removed. Warning! On a singlely linked list it is
- // slow as hell to remove a tail! If you need to frequently remove
- // tails, then you should consider a doubly linked list.
- //
- /**************************************************************************
- * *SList<T>::Remove_Tail -- Removes the tail element from the list *
- * *
- * INPUT: none *
- * *
- * OUTPUT: returns a pointer to the element removed *
- * *
- * WARNINGS: On a singlely linked list it is slow as hell to remove a *
- * tail! If you need to frequently remove tails, then you *
- * should consider a doubly linked list. *
- * *
- * HISTORY: *
- * 03/11/1997 PWG : Created. *
- *========================================================================*/
- template<class T>
- T *SList<T>::Remove_Tail(void)
- {
- if (HeadNode == NULL) // Should make an assertion here instead!
- return ((T *)NULL);
- T* data = TailNode->Data();
- return (Remove(data) ? data : (T*)NULL);
- }
- /**************************************************************************
- * SList<T>::Get_Count -- Returns a count of the entries in the list *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 03/11/1997 PWG : Created. *
- *========================================================================*/
- template<class T>
- inline long SList<T>::Get_Count(void) const
- {
- long count = 0;
- for (SLNode<T> *cur = HeadNode; cur; cur = cur->Next())
- count++;
- return count;
- }
- /**************************************************************************
- * *SList<T>::Head -- Returns the head node of the list *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 03/11/1997 PWG : Created. *
- *========================================================================*/
- template<class T>
- inline SLNode<T> *SList<T>::Head(void) const
- {
- return(HeadNode);
- }
- /**************************************************************************
- * *SList<T>::Tail -- Returns the tail node of the list *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 03/11/1997 PWG : Created. *
- *========================================================================*/
- template<class T>
- inline SLNode<T> *SList<T>::Tail(void) const
- {
- return(TailNode);
- }
- /**************************************************************************
- * SList<T>::Is_Empty -- Returns true if the list is empty *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 03/11/1997 PWG : Created. *
- *========================================================================*/
- template<class T>
- inline bool SList<T>::Is_Empty(void) const
- {
- return( HeadNode == NULL ? true : false);
- }
- /**************************************************************************
- * SList<T>::Add_Head -- Adds a node to the head of the list *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 03/11/1997 PWG : Created. *
- *========================================================================*/
- template<class T>
- bool SList<T>::Add_Head(T *data)
- {
- // we don't deal with lists that point to nothing
- if (!data) return false;
- SLNode<T> *temp = new SLNode<T>(data);
- temp->Set_Next(HeadNode);
- HeadNode = temp;
- if (!TailNode) TailNode = temp;
- return true;
- }
- /**************************************************************************
- * SList<T>::Add_Head -- Adds a list to to the head of the list *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 03/11/1997 PWG : Created. *
- *========================================================================*/
- template<class T>
- bool SList<T>::Add_Head(SList<T>& list)
- {
- if (list.HeadNode == NULL) return false;
- // Save point for initial add of element.
- SLNode<T> *addpoint = NULL;
- // We traverse list backwards so nodes are added in right order.
- for (SLNode<T> *cur = list.HeadNode; cur; cur = cur->Next())
- if (addpoint) {
- SLNode<T> *temp = new SLNode<T>(cur->Data());
- temp->Set_Next(addpoint->Next());
- addpoint->Set_Next(temp);
- addpoint = temp;
- } else {
- Add_Head(cur->Data());
- addpoint = HeadNode;
- }
- return true;
- }
- /**************************************************************************
- * SList<T>::Add_Tail -- Adds a node to the tail of the list *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 03/11/1997 PWG : Created. *
- *========================================================================*/
- template<class T>
- bool SList<T>::Add_Tail(T *data)
- {
- if (data == NULL) return false;
- SLNode<T> *temp = new SLNode<T> (data);
- if (HeadNode == NULL) { // empty list
- HeadNode = TailNode = temp;
- } else { // non-empty list
- TailNode->Set_Next(temp);
- TailNode = temp;
- }
- return true;
- }
- /**************************************************************************
- * SList<T>::Add_Tail -- Adds a list to the tail of the list *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 03/11/1997 PWG : Created. *
- *========================================================================*/
- template<class T>
- bool SList<T>::Add_Tail(SList<T>& list)
- {
- if (list.HeadNode == NULL) return false;
- for (SLNode<T> *cur = list.HeadNode; cur; cur = cur->Next())
- Add_Tail(cur->Data());
- return true;
- }
-
- /**************************************************************************
- * *SList<T>::Find_Node -- returns first node in list matching the input *
- * *
- * INPUT: *
- * *
- * OUTPUT: *
- * *
- * WARNINGS: *
- * *
- * HISTORY: *
- * 08/22/1997 GH : Created. *
- *========================================================================*/
- template<class T>
- inline SLNode<T> *SList<T>::Find_Node(T * data) const
- {
- SLNode<T> * cur;
- for (cur = HeadNode; cur && cur->Data() != data; cur = cur->Next());
-
- return cur;
- }
- #endif
|