This repository has been archived on 2025-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
CnC_Renegade/Code/wwsaveload/pointerremap.cpp

210 lines
7.2 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 : WWSaveLoad *
* *
* $Archive:: /Commando/Code/wwsaveload/pointerremap.cpp $*
* *
* Author:: Greg Hjelstrom *
* *
* $Modtime:: 5/09/01 11:36a $*
* *
* $Revision:: 9 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "pointerremap.h"
#include "refcount.h"
#include "wwdebug.h"
const int POINTER_TABLES_GROWTH_STEP = 4096;
PointerRemapClass::PointerRemapClass(void)
{
PointerPairTable.Set_Growth_Step(POINTER_TABLES_GROWTH_STEP);
PointerRequestTable.Set_Growth_Step(POINTER_TABLES_GROWTH_STEP);
RefCountRequestTable.Set_Growth_Step(POINTER_TABLES_GROWTH_STEP);
}
PointerRemapClass::~PointerRemapClass(void)
{
}
void PointerRemapClass::Reset(void)
{
PointerPairTable.Delete_All();
PointerRequestTable.Delete_All();
RefCountRequestTable.Delete_All();
}
void PointerRemapClass::Process(void)
{
if ( PointerPairTable.Count() > 0 ) {
qsort(&PointerPairTable[0], PointerPairTable.Count(), sizeof(PointerPairTable[0]), ptr_pair_compare_function);
}
if ( PointerRequestTable.Count() > 0 ) {
WWASSERT( PointerPairTable.Count() > 0 );
qsort(&PointerRequestTable[0],PointerRequestTable.Count(), sizeof(PointerRequestTable[0]), ptr_request_compare_function);
Process_Request_Table(PointerRequestTable,false);
}
// remap the ref-counted pointers
if ( RefCountRequestTable.Count() > 0 ) {
WWASSERT( PointerPairTable.Count() > 0 );
qsort(&RefCountRequestTable[0],RefCountRequestTable.Count(), sizeof(RefCountRequestTable[0]), ptr_request_compare_function);
Process_Request_Table(RefCountRequestTable,true);
}
}
void PointerRemapClass::Process_Request_Table(DynamicVectorClass<PtrRemapStruct> & request_table,bool refcount)
{
// Remap the pointers
int pointer_index = 0;
int pair_index = 0;
for (pointer_index = 0; pointer_index < request_table.Count(); pointer_index++) {
void * pointer_to_remap = *(request_table[pointer_index].PointerToRemap);
int pre_search_index = pair_index;
// Find the pair which contains the pointer we are looking for as its "old" pointer
while ( (pair_index < PointerPairTable.Count()) &&
(PointerPairTable[pair_index].OldPointer < pointer_to_remap) )
{
pair_index++;
}
if ((pair_index < PointerPairTable.Count()) && (PointerPairTable[pair_index].OldPointer == pointer_to_remap)) {
// we found the match, plug in the new pointer and add a ref if needed.
*request_table[pointer_index].PointerToRemap = PointerPairTable[pair_index].NewPointer;
if (refcount) {
RefCountClass * refptr = (RefCountClass *)(*request_table[pointer_index].PointerToRemap);
refptr->Add_Ref();
}
} else {
// Failed to re-map the pointer.
// warn the user, set pointer to NULL, reset index to the pre_search_index.
// If this happens, things could be going very wrong. (find out why its happening!)
pair_index = pre_search_index;
*request_table[pointer_index].PointerToRemap = NULL;
#ifdef WWDEBUG
const char * file = request_table[pointer_index].File;
int line = request_table[pointer_index].Line;
WWDEBUG_SAY(("Warning! Failed to re-map pointer! old_ptr = 0x%X file = %s line = %d\r\n",(unsigned int)pointer_to_remap,file,line));
WWASSERT( 0 );
#endif
}
}
}
void PointerRemapClass::Register_Pointer (void *old_pointer, void *new_pointer)
{
PointerPairTable.Add(PtrPairStruct(old_pointer,new_pointer));
}
#ifdef WWDEBUG
void PointerRemapClass::Request_Pointer_Remap(void **pointer_to_convert,const char * file,int line)
{
PtrRemapStruct remap;
remap.PointerToRemap = pointer_to_convert;
remap.File = file;
remap.Line = line;
PointerRequestTable.Add(remap);
}
void PointerRemapClass::Request_Ref_Counted_Pointer_Remap (RefCountClass **pointer_to_convert,const char * file, int line)
{
PtrRemapStruct remap;
remap.PointerToRemap = (void**)pointer_to_convert;
remap.File = file;
remap.Line = line;
RefCountRequestTable.Add(remap);
}
#else
void PointerRemapClass::Request_Pointer_Remap (void **pointer_to_convert)
{
PtrRemapStruct remap;
remap.PointerToRemap = pointer_to_convert;
PointerRequestTable.Add(remap);
}
void PointerRemapClass::Request_Ref_Counted_Pointer_Remap (RefCountClass **pointer_to_convert)
{
PtrRemapStruct remap;
remap.PointerToRemap = (void**)pointer_to_convert;
RefCountRequestTable.Add(remap);
}
#endif
/*
** sort compare function for pointer pair structures
** sorts by the old pointer value
*/
int __cdecl PointerRemapClass::ptr_pair_compare_function(void const * ptr1, void const * ptr2)
{
void * old1 = ((PointerRemapClass::PtrPairStruct const *)ptr1)->OldPointer;
void * old2 = ((PointerRemapClass::PtrPairStruct const *)ptr2)->OldPointer;
if (old1 == old2) {
return(0);
}
if (old1 < old2) {
return(-1);
}
return(1);
}
/*
** sort compare function for pointer remap structures
** sorts by the old pointer value
*/
int __cdecl PointerRemapClass::ptr_request_compare_function(void const * ptr1, void const * ptr2)
{
PtrRemapStruct * remap1 = (PtrRemapStruct *)ptr1;
PtrRemapStruct * remap2 = (PtrRemapStruct *)ptr2;
void * old1 = *(remap1->PointerToRemap);
void * old2 = *(remap2->PointerToRemap);
if (old1 == old2) {
return(0);
}
if (old1 < old2) {
return(-1);
}
return(1);
}