source-engine/mdllib/mdllib_utils.cpp

206 lines
4.9 KiB
C++
Raw Normal View History

2020-04-22 16:56:21 +00:00
//========= 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 );
}