246 lines
7.4 KiB
C++
246 lines
7.4 KiB
C++
|
/*
|
||
|
** 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/>.
|
||
|
*/
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
*** 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 : WWLib *
|
||
|
* *
|
||
|
* $Archive:: /Commando/Code/wwlib/multilist.cpp $*
|
||
|
* *
|
||
|
* Original Author:: Greg Hjelstrom *
|
||
|
* *
|
||
|
* $Author:: Greg_h $*
|
||
|
* *
|
||
|
* $Modtime:: 6/12/01 9:51a $*
|
||
|
* *
|
||
|
* $Revision:: 9 $*
|
||
|
* *
|
||
|
*---------------------------------------------------------------------------------------------*
|
||
|
* Functions: *
|
||
|
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||
|
|
||
|
#include "multilist.h"
|
||
|
#include "wwmemlog.h"
|
||
|
|
||
|
/*
|
||
|
** Delcare the pool for ListNodes
|
||
|
*/
|
||
|
DEFINE_AUTO_POOL(MultiListNodeClass, 256);
|
||
|
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
|
||
|
MultiListObjectClass Implementation.
|
||
|
|
||
|
***********************************************************************************************/
|
||
|
|
||
|
MultiListObjectClass::~MultiListObjectClass(void)
|
||
|
{
|
||
|
while (ListNode) {
|
||
|
ListNode->List->Internal_Remove(this);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************************************
|
||
|
|
||
|
GenericMultiListClass Implementation.
|
||
|
This class has all of the real implementation. Templates are provided in the header file
|
||
|
which create typed lists by simply type-casting the void pointers that GenericMultiList uses.
|
||
|
|
||
|
***********************************************************************************************/
|
||
|
|
||
|
GenericMultiListClass::~GenericMultiListClass(void)
|
||
|
{
|
||
|
assert(Is_Empty());
|
||
|
}
|
||
|
|
||
|
bool GenericMultiListClass::Contains(MultiListObjectClass * obj)
|
||
|
{
|
||
|
assert(obj);
|
||
|
|
||
|
MultiListNodeClass* lnode = obj->Get_List_Node();
|
||
|
while (lnode) {
|
||
|
if (lnode->List == this) return true;
|
||
|
lnode = lnode->NextList;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
int GenericMultiListClass::Count(void)
|
||
|
{
|
||
|
int counter = 0;
|
||
|
GenericMultiListIterator it(this);
|
||
|
for (it.First(); !it.Is_Done(); it.Next()) {
|
||
|
counter++;
|
||
|
}
|
||
|
return counter;
|
||
|
}
|
||
|
|
||
|
bool GenericMultiListClass::Internal_Add(MultiListObjectClass *obj, bool onlyonce)
|
||
|
{
|
||
|
WWMEMLOG(MEM_GAMEDATA);
|
||
|
assert(obj);
|
||
|
|
||
|
if (onlyonce && Is_In_List(obj)) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// allocate a list node for this object
|
||
|
MultiListNodeClass *node = new MultiListNodeClass;
|
||
|
node->Object = obj;
|
||
|
|
||
|
// link the list node into the list of list nodes for the object
|
||
|
node->NextList = obj->Get_List_Node();
|
||
|
obj->Set_List_Node(node);
|
||
|
|
||
|
// link the node to the objects in *this* list
|
||
|
node->Prev = &(Head);
|
||
|
node->Next = Head.Next;
|
||
|
node->Next->Prev = node;
|
||
|
node->Prev->Next = node;
|
||
|
|
||
|
// identify this node as being part of this list
|
||
|
node->List = this;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool GenericMultiListClass::Internal_Add_Tail(MultiListObjectClass * obj,bool onlyonce)
|
||
|
{
|
||
|
WWMEMLOG(MEM_GAMEDATA);
|
||
|
assert(obj);
|
||
|
|
||
|
if (onlyonce && Is_In_List(obj)) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// allocate a list node for this object
|
||
|
MultiListNodeClass *node = new MultiListNodeClass;
|
||
|
node->Object = obj;
|
||
|
|
||
|
// link the list node into the list of list nodes for the object
|
||
|
node->NextList = obj->Get_List_Node();
|
||
|
obj->Set_List_Node(node);
|
||
|
|
||
|
// link the node to the tail of this list (next should be head, prev should be head.Prev)
|
||
|
node->Prev = Head.Prev;
|
||
|
node->Next = &(Head);
|
||
|
node->Next->Prev = node;
|
||
|
node->Prev->Next = node;
|
||
|
|
||
|
// identify this node as being part of this list
|
||
|
node->List = this;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool GenericMultiListClass::Internal_Add_After(MultiListObjectClass * obj,const MultiListObjectClass * existing_list_member,bool onlyonce)
|
||
|
{
|
||
|
WWMEMLOG(MEM_GAMEDATA);
|
||
|
assert(obj);
|
||
|
assert(existing_list_member);
|
||
|
|
||
|
if (onlyonce && Is_In_List(obj)) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// find the node hanging off 'existing_list_member' that corresponds to this list (O(numlists))
|
||
|
MultiListNodeClass * existing_node = existing_list_member->Get_List_Node();
|
||
|
while ((existing_node->List != this) && (existing_node)) {
|
||
|
existing_node = existing_node->NextList;
|
||
|
}
|
||
|
|
||
|
if (existing_node == NULL) {
|
||
|
return false; // he's not in this list!
|
||
|
}
|
||
|
|
||
|
// allocate a node
|
||
|
MultiListNodeClass * node = new MultiListNodeClass;
|
||
|
node->Object = obj;
|
||
|
|
||
|
// link the node into the list of list nodes for the object
|
||
|
node->NextList = obj->Get_List_Node();
|
||
|
obj->Set_List_Node(node);
|
||
|
|
||
|
// now, link the new node after existing_node
|
||
|
node->Prev = existing_node;
|
||
|
node->Next = existing_node->Next;
|
||
|
node->Next->Prev = node;
|
||
|
node->Prev->Next = node;
|
||
|
node->List = this;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool GenericMultiListClass::Internal_Remove(MultiListObjectClass *obj)
|
||
|
{
|
||
|
// find the list node in this object that belongs to this list
|
||
|
MultiListNodeClass * lnode = obj->Get_List_Node();
|
||
|
MultiListNodeClass * prevlnode = 0;
|
||
|
|
||
|
while ((lnode) && (lnode->List != this)) {
|
||
|
prevlnode = lnode;
|
||
|
lnode = lnode->NextList;
|
||
|
}
|
||
|
|
||
|
if (lnode == 0) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// now we've found the node which corresponds to this list,
|
||
|
// unlink from the list of objects
|
||
|
lnode->Prev->Next = lnode->Next;
|
||
|
lnode->Next->Prev = lnode->Prev;
|
||
|
|
||
|
// unlink from the list of list nodes
|
||
|
if (prevlnode) {
|
||
|
prevlnode->NextList = lnode->NextList;
|
||
|
} else {
|
||
|
assert(obj->Get_List_Node() == lnode); // must be first list obj is in...
|
||
|
obj->Set_List_Node(lnode->NextList);
|
||
|
}
|
||
|
|
||
|
// delete the link
|
||
|
delete lnode;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
MultiListObjectClass * GenericMultiListClass::Internal_Remove_List_Head(void)
|
||
|
{
|
||
|
if (Head.Next == &Head) {
|
||
|
return 0; // no more objects
|
||
|
}
|
||
|
|
||
|
MultiListNodeClass * node = Head.Next;
|
||
|
MultiListObjectClass * obj = node->Object;
|
||
|
|
||
|
// remove the object from our list
|
||
|
Internal_Remove(obj);
|
||
|
|
||
|
// here you go.
|
||
|
return obj;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|