|
|
//====== 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; }
|