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