HEAP.CPP 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  1. /*
  2. ** Command & Conquer Red Alert(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. /* $Header: /CounterStrike/HEAP.CPP 1 3/03/97 10:24a Joe_bostic $ */
  19. /***********************************************************************************************
  20. *** 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 ***
  21. ***********************************************************************************************
  22. * *
  23. * Project Name : Command & Conquer *
  24. * *
  25. * File Name : HEAP.CPP *
  26. * *
  27. * Programmer : Joe L. Bostic *
  28. * *
  29. * Start Date : 02/18/95 *
  30. * *
  31. * Last Update : May 6, 1996 [JLB] *
  32. * *
  33. *---------------------------------------------------------------------------------------------*
  34. * Functions: *
  35. * FixedHeapClass::Allocate -- Allocate a sub-block from the heap. *
  36. * FixedHeapClass::Clear -- Clears (and frees) the heap manager memory. *
  37. * FixedHeapClass::FixedHeapClass -- Normal constructor for heap management class. *
  38. * FixedHeapClass::Free -- Frees a sub-block in the heap. *
  39. * FixedHeapClass::Free_All -- Frees all objects in the fixed heap. *
  40. * FixedHeapClass::ID -- Converts a pointer to a sub-block index number. *
  41. * FixedHeapClass::Set_Heap -- Assigns a memory block for this heap manager. *
  42. * FixedHeapClass::~FixedHeapClass -- Destructor for the heap manager class. *
  43. * FixedIHeapClass::Allocate -- Allocate an object from the heap. *
  44. * FixedIHeapClass::Clear -- Clears the fixed heap of all entries. *
  45. * FixedIHeapClass::Free -- Frees an object in the heap. *
  46. * FixedIHeapClass::Free_All -- Frees all objects out of the indexed heap. *
  47. * FixedIHeapClass::Logical_ID -- Fetches the logical ID number. *
  48. * FixedIHeapClass::Set_Heap -- Set the heap to the buffer provided. *
  49. * TFixedIHeapClass::Code_Pointers -- codes pointers for every object, to prepare for save *
  50. * TFixedIHeapClass::Decode_Pointers -- Decodes all object pointers, for after loading *
  51. * TFixedIHeapClass::Load -- Loads all active objects *
  52. * TFixedIHeapClass::Save -- Saves all active objects *
  53. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  54. #include "function.h"
  55. #include "heap.h"
  56. #include <mem.h>
  57. #include <stdio.h>
  58. #include <stddef.h>
  59. #include <conio.h>
  60. #include <string.h>
  61. /***********************************************************************************************
  62. * FixedHeapClass::FixedHeapClass -- Normal constructor for heap management class. *
  63. * *
  64. * This is the normal constructor used for the heap manager class. This initializes *
  65. * the class but doesn't yet assign actual heap memory to this manager. That is handled *
  66. * by the Set_Heap() function. *
  67. * *
  68. * INPUT: size -- The size of the individual sub-blocks in this heap. This value is *
  69. * typically the size of some class or structure. *
  70. * *
  71. * OUTPUT: none *
  72. * *
  73. * WARNINGS: The heap must first be assigned a block of memory to manage before it can *
  74. * be used. *
  75. * *
  76. * HISTORY: *
  77. * 02/21/1995 JLB : Created. *
  78. *=============================================================================================*/
  79. FixedHeapClass::FixedHeapClass(int size) :
  80. IsAllocated(false),
  81. Size(size),
  82. TotalCount(0),
  83. ActiveCount(0),
  84. Buffer(0)
  85. {
  86. }
  87. /***********************************************************************************************
  88. * FixedHeapClass::~FixedHeapClass -- Destructor for the heap manager class. *
  89. * *
  90. * This is the default constructor for the heap manager class. It handles freeing the *
  91. * memory assigned to this heap. *
  92. * *
  93. * INPUT: none *
  94. * *
  95. * OUTPUT: none *
  96. * *
  97. * WARNINGS: none *
  98. * *
  99. * HISTORY: *
  100. * 02/21/1995 JLB : Created. *
  101. *=============================================================================================*/
  102. FixedHeapClass::~FixedHeapClass(void)
  103. {
  104. FixedHeapClass::Clear();
  105. }
  106. /***********************************************************************************************
  107. * FixedHeapClass::Set_Heap -- Assigns a memory block for this heap manager. *
  108. * *
  109. * This routine is used to assign a memory heap to this object. A memory heap so assigned *
  110. * will start with all sub-blocks unallocated. After this routine is called, normal *
  111. * allocation and freeing may occur. This routine will allocate necessary memory if the *
  112. * buffer parameter is NULL. *
  113. * *
  114. * INPUT: count -- The number of objects that this heap should manage. *
  115. * *
  116. * buffer -- Pointer to pre-allocated buffer that this manager will use. If this *
  117. * parameter is NULL, then memory will be automatically allocated. *
  118. * *
  119. * OUTPUT: bool; Was the heap successfully initialized? *
  120. * *
  121. * WARNINGS: none *
  122. * *
  123. * HISTORY: *
  124. * 02/21/1995 JLB : Created. *
  125. *=============================================================================================*/
  126. int FixedHeapClass::Set_Heap(int count, void * buffer)
  127. {
  128. /*
  129. ** Clear out the old heap data.
  130. */
  131. Clear();
  132. /*
  133. ** If there is no size to the objects in the heap, then this block memory
  134. ** handler can NEVER function. Return with a failure condition.
  135. */
  136. if (!Size) return(false);
  137. /*
  138. ** If there is no count specified, then this indicates that the heap should
  139. ** be disabled.
  140. */
  141. if (!count) return(true);
  142. /*
  143. ** Initialize the free boolean vector and the buffer for the actual
  144. ** allocation objects.
  145. */
  146. if (FreeFlag.Resize(count)) {
  147. if (!buffer) {
  148. buffer = new char[count * Size];
  149. if (!buffer) {
  150. FreeFlag.Clear();
  151. return(false);
  152. }
  153. IsAllocated = true;
  154. }
  155. Buffer = buffer;
  156. TotalCount = count;
  157. return(true);
  158. }
  159. return(false);
  160. }
  161. /***********************************************************************************************
  162. * FixedHeapClass::Allocate -- Allocate a sub-block from the heap. *
  163. * *
  164. * Finds the first available sub-block in the heap and returns a pointer to it. The sub- *
  165. * block is marked as allocated by this routine. If there are no more sub-blocks *
  166. * available, then this routine will return NULL. *
  167. * *
  168. * INPUT: none *
  169. * *
  170. * OUTPUT: Returns with a pointer to the newly allocated sub-block. *
  171. * *
  172. * WARNINGS: none *
  173. * *
  174. * HISTORY: *
  175. * 02/21/1995 JLB : Created. *
  176. *=============================================================================================*/
  177. void * FixedHeapClass::Allocate(void)
  178. {
  179. if (ActiveCount < TotalCount) {
  180. int index = FreeFlag.First_False();
  181. if (index != -1) {
  182. ActiveCount++;
  183. FreeFlag[index] = true;
  184. return((*this)[index]);
  185. }
  186. }
  187. return(0);
  188. }
  189. /***********************************************************************************************
  190. * FixedHeapClass::Free -- Frees a sub-block in the heap. *
  191. * *
  192. * Use this routine to free a previously allocated sub-block in the heap. *
  193. * *
  194. * INPUT: pointer -- A pointer to the sub-block to free. This is the same pointer that *
  195. * was returned from the Allocate() function. *
  196. * *
  197. * OUTPUT: bool; Was the deallocation successful? Failure could indicate a pointer that *
  198. * doesn't refer to this heap or a null pointer. *
  199. * *
  200. * WARNINGS: none *
  201. * *
  202. * HISTORY: *
  203. * 02/21/1995 JLB : Created. *
  204. *=============================================================================================*/
  205. int FixedHeapClass::Free(void * pointer)
  206. {
  207. if (pointer && ActiveCount) {
  208. int index = ID(pointer);
  209. if ((unsigned)index < TotalCount) {
  210. if (FreeFlag[index]) {
  211. ActiveCount--;
  212. FreeFlag[index] = false;
  213. return(true);
  214. }
  215. }
  216. }
  217. return(false);
  218. }
  219. /***********************************************************************************************
  220. * FixedHeapClass::ID -- Converts a pointer to a sub-block index number. *
  221. * *
  222. * Use this routine to convert a pointer (returned by Allocate) into the sub-block *
  223. * index number. This index number can be used as a form of identifier for the block. *
  224. * *
  225. * INPUT: pointer -- A pointer to the sub-block to convert into an ID number. *
  226. * *
  227. * OUTPUT: Returns with the index (ID) number for the sub-block specified. This number will *
  228. * range between 0 and the sub-block max -1. If -1 is returned, then the pointer *
  229. * was invalid. *
  230. * *
  231. * WARNINGS: none *
  232. * *
  233. * HISTORY: *
  234. * 02/21/1995 JLB : Created. *
  235. *=============================================================================================*/
  236. int FixedHeapClass::ID(void const * pointer) const
  237. {
  238. if (pointer && Size) {
  239. return((int)(((char *)pointer - (char *)Buffer) / Size));
  240. }
  241. return(-1);
  242. }
  243. /***********************************************************************************************
  244. * FixedHeapClass::Clear -- Clears (and frees) the heap manager memory. *
  245. * *
  246. * This routine is used to bring the heap manager back into a non-functioning state. All *
  247. * memory allocated by this manager is freed. Any previous pointers to allocated blocks *
  248. * from this heap are now invalid. *
  249. * *
  250. * INPUT: none *
  251. * *
  252. * OUTPUT: none *
  253. * *
  254. * WARNINGS: none *
  255. * *
  256. * HISTORY: *
  257. * 02/21/1995 JLB : Created. *
  258. *=============================================================================================*/
  259. void FixedHeapClass::Clear(void)
  260. {
  261. /*
  262. ** Free the old buffer (if present).
  263. */
  264. if (Buffer && IsAllocated) {
  265. delete[] Buffer;
  266. }
  267. Buffer = 0;
  268. IsAllocated = false;
  269. ActiveCount = 0;
  270. TotalCount = 0;
  271. FreeFlag.Clear();
  272. }
  273. /***********************************************************************************************
  274. * FixedHeapClass::Free_All -- Frees all objects in the fixed heap. *
  275. * *
  276. * This routine will free all previously allocated objects out of the heap. Use this *
  277. * routine to ensure that the heap is empty. *
  278. * *
  279. * INPUT: none *
  280. * *
  281. * OUTPUT: Was the heap successfully cleared of all objects? *
  282. * *
  283. * WARNINGS: none *
  284. * *
  285. * HISTORY: *
  286. * 05/22/1995 JLB : Created. *
  287. *=============================================================================================*/
  288. int FixedHeapClass::Free_All(void)
  289. {
  290. ActiveCount = 0;
  291. FreeFlag.Reset();
  292. return(true);
  293. }
  294. /////////////////////////////////////////////////////////////////////
  295. /***********************************************************************************************
  296. * FixedIHeapClass::Free_All -- Frees all objects out of the indexed heap. *
  297. * *
  298. * Use this routine to free all previously allocated objects in the heap. This routine will *
  299. * also clear out the allocated object vector as well. *
  300. * *
  301. * INPUT: none *
  302. * *
  303. * OUTPUT: Was the heap successfully cleared of objects? *
  304. * *
  305. * WARNINGS: none *
  306. * *
  307. * HISTORY: *
  308. * 05/22/1995 JLB : Created. *
  309. *=============================================================================================*/
  310. int FixedIHeapClass::Free_All(void)
  311. {
  312. ActivePointers.Delete_All();
  313. return(FixedHeapClass::Free_All());
  314. }
  315. /***********************************************************************************************
  316. * FixedIHeapClass::Clear -- Clears the fixed heap of all entries. *
  317. * *
  318. * This routine will clear the entire heap. All memory that was allocation, will be freed *
  319. * by this routine. After calling this routine, the heap must either be resized or *
  320. * a new heap memory block specifically attached, before it can be used again. *
  321. * *
  322. * INPUT: none *
  323. * *
  324. * OUTPUT: none *
  325. * *
  326. * WARNINGS: none *
  327. * *
  328. * HISTORY: *
  329. * 09/21/1995 JLB : Created. *
  330. *=============================================================================================*/
  331. void FixedIHeapClass::Clear(void)
  332. {
  333. FixedHeapClass::Clear();
  334. ActivePointers.Clear();
  335. }
  336. /***********************************************************************************************
  337. * FixedIHeapClass::Set_Heap -- Set the heap to the buffer provided. *
  338. * *
  339. * This routine will set the heap to use the buffer specified. Use this routine when a *
  340. * pre-allocated buffer is to be used for the heap. A heap that is assigned in this *
  341. * manner cannot be resized. *
  342. * *
  343. * INPUT: count -- The number of objects that the buffer pointer can be used to track. *
  344. * *
  345. * buffer -- Pointer to the buffer to use when keeping track of the objects. *
  346. * *
  347. * OUTPUT: Was the heap assigned successfully? *
  348. * *
  349. * WARNINGS: none *
  350. * *
  351. * HISTORY: *
  352. * 09/21/1995 JLB : Created. *
  353. *=============================================================================================*/
  354. int FixedIHeapClass::Set_Heap(int count, void * buffer)
  355. {
  356. Clear();
  357. if (FixedHeapClass::Set_Heap(count, buffer)) {
  358. ActivePointers.Resize(count);
  359. return(true);
  360. }
  361. return(false);
  362. }
  363. /***********************************************************************************************
  364. * FixedIHeapClass::Allocate -- Allocate an object from the heap. *
  365. * *
  366. * This routine will allocate an object located in the heap. If no free object space *
  367. * could be found, then NULL is returned. *
  368. * *
  369. * INPUT: none *
  370. * *
  371. * OUTPUT: Returns with a pointer to the allocated object memory block. *
  372. * *
  373. * WARNINGS: none *
  374. * *
  375. * HISTORY: *
  376. * 09/21/1995 JLB : Created. *
  377. *=============================================================================================*/
  378. void * FixedIHeapClass::Allocate(void)
  379. {
  380. void * ptr = FixedHeapClass::Allocate();
  381. if (ptr) {
  382. ActivePointers.Add(ptr);
  383. memset (ptr, 0, Size);
  384. }
  385. return(ptr);
  386. }
  387. /***********************************************************************************************
  388. * FixedIHeapClass::Free -- Frees an object in the heap. *
  389. * *
  390. * This routine is used to free an object in the heap. Freeing is accomplished by marking *
  391. * the object's memory as free to be reallocated. The object is also removed from the *
  392. * allocated object pointer vector. *
  393. * *
  394. * INPUT: pointer -- Pointer to the object that is to be removed from the heap. *
  395. * *
  396. * OUTPUT: none *
  397. * *
  398. * WARNINGS: none *
  399. * *
  400. * HISTORY: *
  401. * 02/21/1995 JLB : Created. *
  402. *=============================================================================================*/
  403. int FixedIHeapClass::Free(void * pointer)
  404. {
  405. if (FixedHeapClass::Free(pointer)) {
  406. ActivePointers.Delete(pointer);
  407. }
  408. return(false);
  409. }
  410. /***********************************************************************************************
  411. * FixedIHeapClass::Logical_ID -- Fetches the logical ID number. *
  412. * *
  413. * Ths logical ID number of a memory block is the index number of the block as if the *
  414. * heap consisted only of valid allocated blocks. This knowledge comes in handy when *
  415. * the real index number must be anticipated before a memory block packing process. *
  416. * *
  417. * INPUT: pointer -- Pointer to an allocated block in the heap. *
  418. * *
  419. * OUTPUT: Returns with the logical index number of this block. The number returned must not *
  420. * be used as a regular index into the heap until such time as the heap has been *
  421. * compacted (by some means or another) without modifying the block order. *
  422. * *
  423. * WARNINGS: Runs in linear time. *
  424. * *
  425. * HISTORY: *
  426. * 05/06/1996 JLB : Created. *
  427. *=============================================================================================*/
  428. int FixedIHeapClass::Logical_ID(void const * pointer) const
  429. {
  430. if (pointer != NULL) {
  431. for (int index = 0; index < Count(); index++) {
  432. if (Active_Ptr(index) == pointer) {
  433. return(index);
  434. }
  435. }
  436. }
  437. return(-1);
  438. }
  439. /***********************************************************************************************
  440. * TFixedIHeapClass::Save -- Saves all active objects *
  441. * *
  442. * INPUT: file file to write to *
  443. * *
  444. * OUTPUT: true = OK, false = error *
  445. * *
  446. * WARNINGS: none *
  447. * *
  448. * HISTORY: *
  449. * 03/15/1995 BRR : Created. *
  450. * 03/12/1996 JLB : Uses in-place new operator for virtual table control. *
  451. *=============================================================================================*/
  452. template<class T>
  453. int TFixedIHeapClass<T>::Save(Pipe & file) const
  454. {
  455. /*
  456. ** Save the number of instances of this class
  457. */
  458. file.Put(&ActiveCount, sizeof(ActiveCount));
  459. /*
  460. ** Save each instance of this class
  461. */
  462. for (int i = 0; i < ActiveCount; i++) {
  463. /*
  464. ** Save the array index of the object, so it can be loaded back into the
  465. ** same array location (so TARGET translations will work)
  466. */
  467. int idx = ID(Ptr(i));
  468. file.Put(&idx, sizeof(idx));
  469. /*
  470. ** Save the object itself
  471. */
  472. file.Put(Ptr(i), sizeof(T));
  473. }
  474. return(true);
  475. }
  476. /***********************************************************************************************
  477. * TFixedIHeapClass::Load -- Loads all active objects *
  478. * *
  479. * INPUT: file file to read from *
  480. * *
  481. * OUTPUT: true = OK, false = error *
  482. * *
  483. * WARNINGS: none *
  484. * *
  485. * HISTORY: *
  486. * 03/15/1995 BRR : Created. *
  487. *=============================================================================================*/
  488. template<class T>
  489. int TFixedIHeapClass<T>::Load(Straw & file)
  490. {
  491. int i; // loop counter
  492. int idx; // object index
  493. T * ptr; // object pointer
  494. int a_count;
  495. /*
  496. ** Read the number of instances of this class
  497. */
  498. if (file.Get(&a_count, sizeof(a_count)) != sizeof(a_count)) {
  499. return(false);
  500. }
  501. /*
  502. ** Error if more objects than we can hold
  503. */
  504. if (a_count > TotalCount) {
  505. return(false);
  506. }
  507. /*
  508. ** Read each class instance
  509. */
  510. for (i = 0; i < a_count; i++) {
  511. /*
  512. ** Read the object's array index
  513. */
  514. if (file.Get(&idx, sizeof(idx)) != sizeof(idx)) {
  515. return(false);
  516. }
  517. /*
  518. ** Get a pointer to the object, activate that object
  519. */
  520. ptr = (T *)(*this)[idx];
  521. FreeFlag[idx] = true;
  522. ActiveCount++;
  523. ActivePointers.Add(ptr);
  524. /*
  525. ** Load the object
  526. */
  527. file.Get(ptr, sizeof(T));
  528. new(ptr) T(NoInitClass());
  529. // if (!ptr->Load(file)) {
  530. // return(false);
  531. // }
  532. }
  533. return(true);
  534. }
  535. /***********************************************************************************************
  536. * TFixedIHeapClass::Code_Pointers -- codes pointers for every object, to prepare for save *
  537. * *
  538. * INPUT: file file to read from *
  539. * *
  540. * OUTPUT: true = OK, false = error *
  541. * *
  542. * WARNINGS: none *
  543. * *
  544. * HISTORY: *
  545. * 03/15/1995 BRR : Created. *
  546. *=============================================================================================*/
  547. template<class T>
  548. void TFixedIHeapClass<T>::Code_Pointers(void)
  549. {
  550. int i;
  551. for (i = 0; i < ActiveCount; i++) {
  552. Ptr(i)->Code_Pointers();
  553. }
  554. }
  555. /***********************************************************************************************
  556. * TFixedIHeapClass::Decode_Pointers -- Decodes all object pointers, for after loading *
  557. * *
  558. * INPUT: file file to read from *
  559. * *
  560. * OUTPUT: true = OK, false = error *
  561. * *
  562. * WARNINGS: none *
  563. * *
  564. * HISTORY: *
  565. * 03/15/1995 BRR : Created. *
  566. *=============================================================================================*/
  567. template<class T>
  568. void TFixedIHeapClass<T>::Decode_Pointers(void)
  569. {
  570. int i;
  571. for (i = 0; i < ActiveCount; i++) {
  572. Ptr(i)->Decode_Pointers();
  573. }
  574. }