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.
205 lines
4.9 KiB
205 lines
4.9 KiB
//========= Copyright 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 ); |
|
} |
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////// |
|
// |
|
// CRemoveTracker implementation |
|
// |
|
////////////////////////////////////////////////////////////////////////// |
|
|
|
|
|
void CRemoveTracker::RemoveBytes( void *pos, int length ) |
|
{ |
|
if ( length <= 0 ) |
|
return; |
|
|
|
// -- hint |
|
if ( m_map.Count() ) |
|
{ |
|
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 CRemoveTracker::GetNumBytesRemoved() const |
|
{ |
|
int iRemoved = 0; |
|
|
|
for ( Map::IndexType_t idx = m_map.FirstInorder(); |
|
idx != m_map.InvalidIndex(); idx = m_map.NextInorder( idx ) ) |
|
{ |
|
int numBytes = m_map.Element( idx ); |
|
iRemoved += numBytes; |
|
} |
|
|
|
return iRemoved; |
|
} |
|
|
|
void CRemoveTracker::Finalize() |
|
{ |
|
// Iterate the map and find all the adjacent removal data blocks |
|
// TODO: |
|
} |
|
|
|
void CRemoveTracker::MemMove( void *ptrBase, int &length ) const |
|
{ |
|
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 ); |
|
byte *ptrDest = BYTE_OFF_PTR( ptr, - iRemoved ); |
|
int numBytes = m_map.Element( idx ); |
|
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 CRemoveTracker::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 * CRemoveTracker::ComputePointer( void *ptrNothingRemoved ) const |
|
{ |
|
int iRemoved = 0; |
|
|
|
// Iterate the map and find all the data that would be removed 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 ) |
|
iRemoved += m_map.Element( idx ); |
|
else |
|
break; |
|
} |
|
|
|
return BYTE_OFF_PTR( ptrNothingRemoved, - iRemoved ); |
|
} |
|
|
|
|
|
|