multilist.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  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. *** 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 ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : WWLib *
  23. * *
  24. * $Archive:: /Commando/Code/wwlib/multilist.cpp $*
  25. * *
  26. * Original Author:: Greg Hjelstrom *
  27. * *
  28. * $Author:: Greg_h $*
  29. * *
  30. * $Modtime:: 6/12/01 9:51a $*
  31. * *
  32. * $Revision:: 9 $*
  33. * *
  34. *---------------------------------------------------------------------------------------------*
  35. * Functions: *
  36. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  37. #include "multilist.h"
  38. #include "wwmemlog.h"
  39. /*
  40. ** Delcare the pool for ListNodes
  41. */
  42. DEFINE_AUTO_POOL(MultiListNodeClass, 256);
  43. /***********************************************************************************************
  44. MultiListObjectClass Implementation.
  45. ***********************************************************************************************/
  46. MultiListObjectClass::~MultiListObjectClass(void)
  47. {
  48. while (ListNode) {
  49. ListNode->List->Internal_Remove(this);
  50. }
  51. }
  52. /***********************************************************************************************
  53. GenericMultiListClass Implementation.
  54. This class has all of the real implementation. Templates are provided in the header file
  55. which create typed lists by simply type-casting the void pointers that GenericMultiList uses.
  56. ***********************************************************************************************/
  57. GenericMultiListClass::~GenericMultiListClass(void)
  58. {
  59. assert(Is_Empty());
  60. }
  61. bool GenericMultiListClass::Contains(MultiListObjectClass * obj)
  62. {
  63. assert(obj);
  64. MultiListNodeClass* lnode = obj->Get_List_Node();
  65. while (lnode) {
  66. if (lnode->List == this) return true;
  67. lnode = lnode->NextList;
  68. }
  69. return false;
  70. }
  71. int GenericMultiListClass::Count(void)
  72. {
  73. int counter = 0;
  74. GenericMultiListIterator it(this);
  75. for (it.First(); !it.Is_Done(); it.Next()) {
  76. counter++;
  77. }
  78. return counter;
  79. }
  80. bool GenericMultiListClass::Internal_Add(MultiListObjectClass *obj, bool onlyonce)
  81. {
  82. WWMEMLOG(MEM_GAMEDATA);
  83. assert(obj);
  84. if (onlyonce && Is_In_List(obj)) {
  85. return false;
  86. }
  87. // allocate a list node for this object
  88. MultiListNodeClass *node = new MultiListNodeClass;
  89. node->Object = obj;
  90. // link the list node into the list of list nodes for the object
  91. node->NextList = obj->Get_List_Node();
  92. obj->Set_List_Node(node);
  93. // link the node to the objects in *this* list
  94. node->Prev = &(Head);
  95. node->Next = Head.Next;
  96. node->Next->Prev = node;
  97. node->Prev->Next = node;
  98. // identify this node as being part of this list
  99. node->List = this;
  100. return true;
  101. }
  102. bool GenericMultiListClass::Internal_Add_Tail(MultiListObjectClass * obj,bool onlyonce)
  103. {
  104. WWMEMLOG(MEM_GAMEDATA);
  105. assert(obj);
  106. if (onlyonce && Is_In_List(obj)) {
  107. return false;
  108. }
  109. // allocate a list node for this object
  110. MultiListNodeClass *node = new MultiListNodeClass;
  111. node->Object = obj;
  112. // link the list node into the list of list nodes for the object
  113. node->NextList = obj->Get_List_Node();
  114. obj->Set_List_Node(node);
  115. // link the node to the tail of this list (next should be head, prev should be head.Prev)
  116. node->Prev = Head.Prev;
  117. node->Next = &(Head);
  118. node->Next->Prev = node;
  119. node->Prev->Next = node;
  120. // identify this node as being part of this list
  121. node->List = this;
  122. return true;
  123. }
  124. bool GenericMultiListClass::Internal_Add_After(MultiListObjectClass * obj,const MultiListObjectClass * existing_list_member,bool onlyonce)
  125. {
  126. WWMEMLOG(MEM_GAMEDATA);
  127. assert(obj);
  128. assert(existing_list_member);
  129. if (onlyonce && Is_In_List(obj)) {
  130. return false;
  131. }
  132. // find the node hanging off 'existing_list_member' that corresponds to this list (O(numlists))
  133. MultiListNodeClass * existing_node = existing_list_member->Get_List_Node();
  134. while ((existing_node->List != this) && (existing_node)) {
  135. existing_node = existing_node->NextList;
  136. }
  137. if (existing_node == NULL) {
  138. return false; // he's not in this list!
  139. }
  140. // allocate a node
  141. MultiListNodeClass * node = new MultiListNodeClass;
  142. node->Object = obj;
  143. // link the node into the list of list nodes for the object
  144. node->NextList = obj->Get_List_Node();
  145. obj->Set_List_Node(node);
  146. // now, link the new node after existing_node
  147. node->Prev = existing_node;
  148. node->Next = existing_node->Next;
  149. node->Next->Prev = node;
  150. node->Prev->Next = node;
  151. node->List = this;
  152. return true;
  153. }
  154. bool GenericMultiListClass::Internal_Remove(MultiListObjectClass *obj)
  155. {
  156. // find the list node in this object that belongs to this list
  157. MultiListNodeClass * lnode = obj->Get_List_Node();
  158. MultiListNodeClass * prevlnode = 0;
  159. while ((lnode) && (lnode->List != this)) {
  160. prevlnode = lnode;
  161. lnode = lnode->NextList;
  162. }
  163. if (lnode == 0) {
  164. return false;
  165. }
  166. // now we've found the node which corresponds to this list,
  167. // unlink from the list of objects
  168. lnode->Prev->Next = lnode->Next;
  169. lnode->Next->Prev = lnode->Prev;
  170. // unlink from the list of list nodes
  171. if (prevlnode) {
  172. prevlnode->NextList = lnode->NextList;
  173. } else {
  174. assert(obj->Get_List_Node() == lnode); // must be first list obj is in...
  175. obj->Set_List_Node(lnode->NextList);
  176. }
  177. // delete the link
  178. delete lnode;
  179. return true;
  180. }
  181. MultiListObjectClass * GenericMultiListClass::Internal_Remove_List_Head(void)
  182. {
  183. if (Head.Next == &Head) {
  184. return 0; // no more objects
  185. }
  186. MultiListNodeClass * node = Head.Next;
  187. MultiListObjectClass * obj = node->Object;
  188. // remove the object from our list
  189. Internal_Remove(obj);
  190. // here you go.
  191. return obj;
  192. }