| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325 |
- /*
- ** Command & Conquer Generals(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/>.
- */
- /***********************************************************************************************
- *** 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 ***
- ***********************************************************************************************
- * *
- * Project Name : Command & Conquer *
- * *
- * $Archive:: /G/wwlib/listnode.h $*
- * *
- * $Author:: David_m $*
- * *
- * $Modtime:: 4/05/00 12:34p $*
- * *
- * $Revision:: 3 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #if _MSC_VER >= 1000
- #pragma once
- #endif // _MSC_VER >= 1000
- #ifndef LISTNODE_H
- #define LISTNODE_H
- /*
- ** Includes
- */
- #include "assert.h"
- #ifdef __BORLANDC__
- #pragma warn -inl
- #endif
- /*
- ** This is a doubly linked list node. Typical use of this node is to derive
- ** objects from this node. The interface class for this node can be used for
- ** added convenience.
- */
- class GenericList;
- class GenericNode {
- public:
- GenericNode(void) : NextNode(0), PrevNode(0) {}
- virtual ~GenericNode(void) {Unlink();}
- GenericNode(GenericNode & node) {node.Link(this);}
- GenericNode & operator = (GenericNode & node) {
- if (&node != this) {
- node.Link(this);
- }
- return(*this);
- }
- void Unlink(void) {
- // note that this means that the special generic node at the head
- // and tail of the list can not be unlinked. This is done because
- // the user should never unlink them -- it will destroy the list in
- // an evil way.
- if (Is_Valid()) {
- PrevNode->NextNode = NextNode;
- NextNode->PrevNode = PrevNode;
- PrevNode = 0;
- NextNode = 0;
- }
- }
- GenericList * Main_List(void) const {
- GenericNode const * node = this;
- while (node->PrevNode) {
- node = PrevNode;
- }
- return((GenericList *)this);
- }
- void Link(GenericNode * node) {
- assert(node != (GenericNode *)0);
- node->Unlink();
- node->NextNode = NextNode;
- node->PrevNode = this;
- if (NextNode) NextNode->PrevNode = node;
- NextNode = node;
- }
- GenericNode * Next(void) const {return(NextNode);}
- GenericNode * Next_Valid(void) const {
- return ((NextNode && NextNode->NextNode) ? NextNode : (GenericNode *)0);
- }
- GenericNode * Prev(void) const {return(PrevNode);}
- GenericNode * Prev_Valid(void) const {
- return ((PrevNode && PrevNode->PrevNode) ? PrevNode : (GenericNode *)0);
- }
- bool Is_Valid(void) const {return(this != (GenericNode *)0 && NextNode != (GenericNode *)0 && PrevNode != (GenericNode *)0);}
- protected:
- GenericNode * NextNode;
- GenericNode * PrevNode;
- };
- /*
- ** This is a generic list handler. It manages N generic nodes. Use the interface class
- ** to the generic list for added convenience.
- */
- class GenericList {
- public:
- GenericList(void) {
- FirstNode.Link(&LastNode);
- }
-
- virtual ~GenericList(void) {
- while (FirstNode.Next()->Is_Valid()) {
- FirstNode.Next()->Unlink();
- }
- }
- GenericNode * First(void) const {return(FirstNode.Next());}
- GenericNode * First_Valid(void) const
- {
- GenericNode *node = FirstNode.Next();
- return (node->Next() ? node : (GenericNode *)0);
- }
- GenericNode * Last(void) const {return(LastNode.Prev());}
- GenericNode * Last_Valid(void) const
- {
- GenericNode *node = LastNode.Prev();
- return (node->Prev() ? node : (GenericNode *)0);
- }
- bool Is_Empty(void) const {return(!FirstNode.Next()->Is_Valid());}
- void Add_Head(GenericNode * node) {FirstNode.Link(node);}
- void Add_Tail(GenericNode * node) {LastNode.Prev()->Link(node);}
- // void Delete(void) {while (FirstNode.Next()->Is_Valid()) delete FirstNode.Next();}
- int Get_Valid_Count(void) const
- {
- GenericNode * node = First_Valid();
- int counter = 0;
- while(node) {
- counter++;
- node = node->Next_Valid();
- }
- return counter;
- }
- protected:
- GenericNode FirstNode;
- GenericNode LastNode;
- private:
- GenericList(GenericList & list);
- GenericList & operator = (GenericList const &);
- };
- /*
- ** This node class serves only as an "interface class" for the normal node
- ** object. In order to use this interface class you absolutely must be sure
- ** that the node is the root base object of the "class T". If it is true that the
- ** address of the node is the same as the address of the "class T", then this
- ** interface class will work. You can usually ensure this by deriving the
- ** class T object from this node.
- */
- template<class T> class List;
- template<class T>
- class Node : public GenericNode {
- public:
- List<T> * Main_List(void) const {return((List<T> *)GenericNode::Main_List());}
- T Next(void) const {return((T)GenericNode::Next());}
- T Next_Valid(void) const {return((T)GenericNode::Next_Valid());}
- T Prev(void) const {return((T)GenericNode::Prev());}
- T Prev_Valid(void) const {return((T)GenericNode::Prev_Valid());}
- bool Is_Valid(void) const {return(GenericNode::Is_Valid());}
- };
- /*
- ** This is an "interface class" for a list of nodes. The rules for the class T object
- ** are the same as the requirements required of the node class.
- */
- template<class T>
- class List : public GenericList {
- public:
- List(void) {};
- T First(void) const {return((T)GenericList::First());}
- T First_Valid(void) const {return((T)GenericList::First_Valid());}
- T Last(void) const {return((T)GenericList::Last());}
- T Last_Valid(void) const {return((T)GenericList::Last_Valid());}
- void Delete(void) {while (First()->Is_Valid()) delete First();}
- private:
- List(List<T> const & rvalue);
- List<T> operator = (List<T> const & rvalue);
- };
- /*
- The DataNode template class allows you to have a node with a peice of data associated with it.
- Commonly used to maintain a list of objects which are not derived from GenericNode.
- - EHC
- */
- template<class T>
- class DataNode : public GenericNode {
- T Value;
- public:
- DataNode() {};
- DataNode(T value) { Set(value); };
- void Set(T value) { Value = value; };
- T Get() const { return Value; };
- DataNode<T> * Next(void) const { return (DataNode<T> *)GenericNode::Next(); }
- DataNode<T> * Next_Valid(void) const { return (DataNode<T> *)GenericNode::Next_Valid(); }
- DataNode<T> * Prev(void) const { return (DataNode<T> *)GenericNode::Prev(); }
- DataNode<T> * Prev_Valid(void) const { return (DataNode<T> *)GenericNode::Prev_Valid(); }
- };
- /*
- The ContextDataNode template class is an extension of the DataNode class and has an additional
- data value associated with it. Commonly used for tracking the owner of a DataNode.
- - EHC
- */
- template<class C, class D>
- class ContextDataNode : public DataNode<D> {
- C Context;
- public:
- ContextDataNode() {};
- ContextDataNode(C context, D data) { Set_Context(context); Set(data); }
- void Set_Context(C context) { Context = context; };
- C Get_Context() { return Context; };
- };
- /*
- ** A SafeContextDataNode requires the user to supply context and
- ** Data values to the constructor. This eliminates the problem of
- ** uninitialized ContextDataNodes. -DRM
- */
- template<class C, class D>
- class SafeContextDataNode : public ContextDataNode<C,D>
- {
- public:
- SafeContextDataNode(C context, D data) : ContextDataNode<C,D>(context, data) { }
- private:
- // if the compiler complains that it can't access this constructor,
- // you are trying to construct a SafeContextDataNode without providing
- // context and data values. Perhaps you've included a SafeContextDataNode
- // as a member variable, but forgotten to add it to the initializer list
- // in your class constructor.
- // DO NOT change the void constructor to public. That would defeat
- // the purpose of the SafeContextDataNode. -DRM
- SafeContextDataNode();
- };
- /*
- The DoubleNode class has double everything a DataNode has!
- Each DataNode's data member points to the DoubleNode object
- that owns it. This type of object can therefore be in two distinct
- lists, and when it is destroyed it is removed from both of them
- automatically.
- usage example:
- typedef a symbol for the usage of the DoubleNode class as such:
- typedef DoubleNode<int, bool> DOUBLENODE;
- declare the head of the list as a DataNode with type DOUBLENODE
- List<DOUBLENODE *> PrimaryList; // member of object1
- List<DOUBLENODE *> SecondaryList; // member of object2
- Iterate through the list starting at PrimaryList or SecondaryList.
- These two lists are intended to be located in different
- objects, such as an Active list and an Association list as used in G
- Planet mode.
- */
- template<class PRIMARY, class SECONDARY>
- class DoubleNode {
- void Initialize() { Primary.Set(this); Secondary.Set(this); };
- PRIMARY PrimaryValue;
- SECONDARY SecondaryValue;
- public:
- typedef DoubleNode<PRIMARY, SECONDARY> Type;
- DataNode<Type *> Primary;
- DataNode<Type *> Secondary;
- DoubleNode() { Initialize(); };
- DoubleNode(PRIMARY primary, SECONDARY secondary) { Initialize(); Set_Primary(primary); Set_Secondary(secondary); };
- void Set_Primary(PRIMARY value) { PrimaryValue = value; };
- void Set_Secondary(SECONDARY value) { SecondaryValue = value; };
- PRIMARY Get_Primary() { return PrimaryValue; };
- SECONDARY Get_Secondary() { return SecondaryValue; };
- void Unlink() { Primary.Unlink(); Secondary.Unlink(); };
- };
- #endif
|