You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
277 lines
7.4 KiB
277 lines
7.4 KiB
//====== Copyright © 1996-2007, Valve Corporation, All rights reserved. =======
|
|
//
|
|
// Purpose:
|
|
//
|
|
//=============================================================================
|
|
|
|
|
|
#include "mdllib_utils.h"
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CInsertionTracker implementation
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
void CInsertionTracker::InsertBytes( void *pos, int length )
|
|
{
|
|
if ( length <= 0 )
|
|
return;
|
|
|
|
Assert( m_map.InvalidIndex() == m_map.Find( ( byte * ) pos ) );
|
|
m_map.InsertOrReplace( ( byte * ) pos, length );
|
|
}
|
|
|
|
int CInsertionTracker::GetNumBytesInserted() const
|
|
{
|
|
int iInserted = 0;
|
|
|
|
for ( Map::IndexType_t idx = m_map.FirstInorder();
|
|
idx != m_map.InvalidIndex(); idx = m_map.NextInorder( idx ) )
|
|
{
|
|
int numBytes = m_map.Element( idx );
|
|
iInserted += numBytes;
|
|
}
|
|
|
|
return iInserted;
|
|
}
|
|
|
|
void CInsertionTracker::Finalize()
|
|
{
|
|
// Iterate the map and find all the adjacent removal data blocks
|
|
// TODO:
|
|
}
|
|
|
|
void CInsertionTracker::MemMove( void *ptrBase, int &length ) const
|
|
{
|
|
int numBytesInsertReq = GetNumBytesInserted();
|
|
byte *pbBlockEnd = BYTE_OFF_PTR( ptrBase, length );
|
|
length += numBytesInsertReq;
|
|
|
|
for ( Map::IndexType_t idx = m_map.LastInorder();
|
|
idx != m_map.InvalidIndex(); idx = m_map.PrevInorder( idx ) )
|
|
{
|
|
byte *ptr = m_map.Key( idx );
|
|
int numBytes = m_map.Element( idx );
|
|
|
|
// Move [ptr, pbBlockEnd) ->> + numBytesInsertReq
|
|
memmove( BYTE_OFF_PTR( ptr, numBytesInsertReq ), ptr, BYTE_DIFF_PTR( ptr, pbBlockEnd ) );
|
|
|
|
// Inserted data
|
|
memset( BYTE_OFF_PTR( ptr, numBytesInsertReq - numBytes ), 0, numBytes );
|
|
|
|
numBytesInsertReq -= numBytes;
|
|
pbBlockEnd = ptr;
|
|
}
|
|
}
|
|
|
|
int CInsertionTracker::ComputeOffset( void *ptrBase, int off ) const
|
|
{
|
|
void *ptrNewBase = ComputePointer( ptrBase );
|
|
void *ptrNewData = ComputePointer( BYTE_OFF_PTR( ptrBase, off ) );
|
|
return BYTE_DIFF_PTR( ptrNewBase, ptrNewData );
|
|
}
|
|
|
|
void * CInsertionTracker::ComputePointer( void *ptrNothingInserted ) const
|
|
{
|
|
int iInserted = 0;
|
|
|
|
// Iterate the map and find all the data that would be inserted before the given pointer
|
|
for ( Map::IndexType_t idx = m_map.FirstInorder();
|
|
idx != m_map.InvalidIndex(); idx = m_map.NextInorder( idx ) )
|
|
{
|
|
if ( m_map.Key( idx ) < ptrNothingInserted )
|
|
iInserted += m_map.Element( idx );
|
|
else
|
|
break;
|
|
}
|
|
|
|
return BYTE_OFF_PTR( ptrNothingInserted, iInserted );
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CMemoryMovingTracker implementation
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
void CMemoryMovingTracker::RegisterBytes( void *pos, int length )
|
|
{
|
|
if ( length <= 0 && m_ePolicy != MEMORY_MODIFY )
|
|
return;
|
|
|
|
// -- hint
|
|
if ( m_map.Count() && m_ePolicy == MEMORY_REMOVE )
|
|
{
|
|
if ( m_hint.ptr < pos )
|
|
{
|
|
if ( BYTE_OFF_PTR( m_hint.ptr, m_hint.len ) == pos )
|
|
{
|
|
m_hint.len += length;
|
|
m_map.Element( m_hint.idx ) = m_hint.len;
|
|
return;
|
|
}
|
|
}
|
|
else if ( m_hint.ptr > pos )
|
|
{
|
|
if ( BYTE_OFF_PTR( pos, length ) == m_hint.ptr )
|
|
{
|
|
m_hint.len += length;
|
|
m_hint.ptr = BYTE_OFF_PTR( m_hint.ptr, - length );
|
|
m_map.Key( m_hint.idx ) = m_hint.ptr;
|
|
m_map.Element( m_hint.idx ) = m_hint.len;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
// -- end hint
|
|
|
|
// Insert new
|
|
Assert( m_map.InvalidIndex() == m_map.Find( ( byte * ) pos ) );
|
|
Map::IndexType_t idx = m_map.InsertOrReplace( ( byte * ) pos, length );
|
|
|
|
// New hint
|
|
m_hint.idx = idx;
|
|
m_hint.ptr = ( byte * ) pos;
|
|
m_hint.len = length;
|
|
}
|
|
|
|
int CMemoryMovingTracker::GetNumBytesRegistered() const
|
|
{
|
|
int iRegistered = 0;
|
|
|
|
for ( Map::IndexType_t idx = m_map.FirstInorder();
|
|
idx != m_map.InvalidIndex(); idx = m_map.NextInorder( idx ) )
|
|
{
|
|
int numBytes = m_map.Element( idx );
|
|
if ( m_ePolicy == MEMORY_MODIFY && numBytes <= 0 )
|
|
continue;
|
|
iRegistered += numBytes;
|
|
}
|
|
|
|
return iRegistered;
|
|
}
|
|
|
|
void CMemoryMovingTracker::RegisterBaseDelta( void *pOldBase, void *pNewBase )
|
|
{
|
|
for ( Map::IndexType_t idx = m_map.FirstInorder();
|
|
idx != m_map.InvalidIndex(); idx = m_map.NextInorder( idx ) )
|
|
{
|
|
m_map.Key( idx ) = BYTE_OFF_PTR( m_map.Key( idx ), BYTE_DIFF_PTR( pOldBase, pNewBase ) );
|
|
}
|
|
m_hint.ptr = BYTE_OFF_PTR( m_hint.ptr, BYTE_DIFF_PTR( pOldBase, pNewBase ) );
|
|
}
|
|
|
|
void CMemoryMovingTracker::Finalize()
|
|
{
|
|
// Iterate the map and find all the adjacent removal data blocks
|
|
// TODO:
|
|
}
|
|
|
|
void CMemoryMovingTracker::MemMove( void *ptrBase, int &length ) const
|
|
{
|
|
if ( m_ePolicy == MEMORY_REMOVE )
|
|
{
|
|
int iRemoved = 0;
|
|
|
|
for ( Map::IndexType_t idx = m_map.FirstInorder();
|
|
idx != m_map.InvalidIndex(); idx = m_map.NextInorder( idx ) )
|
|
{
|
|
byte *ptr = m_map.Key( idx );
|
|
int numBytes = m_map.Element( idx );
|
|
byte *ptrDest = BYTE_OFF_PTR( ptr, - iRemoved );
|
|
memmove( ptrDest, BYTE_OFF_PTR( ptrDest, numBytes ), BYTE_DIFF_PTR( BYTE_OFF_PTR( ptr, numBytes ), BYTE_OFF_PTR( ptrBase, length ) ) );
|
|
iRemoved += numBytes;
|
|
}
|
|
|
|
length -= iRemoved;
|
|
}
|
|
|
|
if ( m_ePolicy == MEMORY_INSERT )
|
|
{
|
|
for ( Map::IndexType_t idx = m_map.LastInorder();
|
|
idx != m_map.InvalidIndex(); idx = m_map.PrevInorder( idx ) )
|
|
{
|
|
byte *ptr = m_map.Key( idx );
|
|
int numBytes = m_map.Element( idx );
|
|
byte *ptrDest = BYTE_OFF_PTR( ptr, numBytes );
|
|
memmove( ptrDest, ptr, BYTE_DIFF_PTR( ptr, BYTE_OFF_PTR( ptrBase, length ) ) );
|
|
length += numBytes;
|
|
}
|
|
}
|
|
|
|
if ( m_ePolicy == MEMORY_MODIFY )
|
|
{
|
|
// Perform insertions first:
|
|
for ( Map::IndexType_t idx = m_map.LastInorder();
|
|
idx != m_map.InvalidIndex(); idx = m_map.PrevInorder( idx ) )
|
|
{
|
|
byte *ptr = m_map.Key( idx );
|
|
int numBytes = m_map.Element( idx );
|
|
if ( numBytes <= 0 )
|
|
continue; // this is removal
|
|
byte *ptrDest = BYTE_OFF_PTR( ptr, numBytes );
|
|
memmove( ptrDest, ptr, BYTE_DIFF_PTR( ptr, BYTE_OFF_PTR( ptrBase, length ) ) );
|
|
length += numBytes;
|
|
}
|
|
|
|
// Now perform removals accounting for all insertions
|
|
// that has happened up to the moment
|
|
int numInsertedToPoint = 0;
|
|
int iRemoved = 0;
|
|
for ( Map::IndexType_t idx = m_map.FirstInorder();
|
|
idx != m_map.InvalidIndex(); idx = m_map.NextInorder( idx ) )
|
|
{
|
|
byte *ptr = m_map.Key( idx );
|
|
int numBytes = m_map.Element( idx );
|
|
if ( numBytes >= 0 )
|
|
{
|
|
numInsertedToPoint += numBytes;
|
|
continue; // this is insertion that already happened
|
|
}
|
|
numBytes = -numBytes;
|
|
ptr = BYTE_OFF_PTR( ptr, numInsertedToPoint );
|
|
byte *ptrDest = BYTE_OFF_PTR( ptr, - iRemoved );
|
|
memmove( ptrDest, BYTE_OFF_PTR( ptrDest, numBytes ), BYTE_DIFF_PTR( BYTE_OFF_PTR( ptr, numBytes ), BYTE_OFF_PTR( ptrBase, length ) ) );
|
|
iRemoved += numBytes;
|
|
}
|
|
length -= iRemoved;
|
|
}
|
|
}
|
|
|
|
int CMemoryMovingTracker::ComputeOffset( void *ptrBase, int off ) const
|
|
{
|
|
void *ptrNewBase = ComputePointer( ptrBase );
|
|
void *ptrNewData = ComputePointer( BYTE_OFF_PTR( ptrBase, off ) );
|
|
return BYTE_DIFF_PTR( ptrNewBase, ptrNewData );
|
|
}
|
|
|
|
void * CMemoryMovingTracker::ComputePointer( void *ptrNothingRemoved ) const
|
|
{
|
|
int iAffected = 0;
|
|
|
|
// Iterate the map and find all the data that would be removed/inserted before the given pointer
|
|
for ( Map::IndexType_t idx = m_map.FirstInorder();
|
|
idx != m_map.InvalidIndex(); idx = m_map.NextInorder( idx ) )
|
|
{
|
|
if ( m_map.Key( idx ) < ptrNothingRemoved )
|
|
iAffected += m_map.Element( idx );
|
|
else
|
|
break;
|
|
}
|
|
|
|
if ( m_ePolicy == MEMORY_REMOVE )
|
|
return BYTE_OFF_PTR( ptrNothingRemoved, - iAffected );
|
|
|
|
if ( m_ePolicy == MEMORY_INSERT || m_ePolicy == MEMORY_MODIFY )
|
|
return BYTE_OFF_PTR( ptrNothingRemoved, iAffected );
|
|
|
|
return ptrNothingRemoved;
|
|
}
|
|
|
|
|