source-engine/utils/vmpi/vmpi_filesystem.cpp

367 lines
8.0 KiB
C++
Raw Normal View History

2020-04-22 16:56:21 +00:00
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#include "vmpi_filesystem_internal.h"
#include "tier1/utlbuffer.h"
bool g_bDisableFileAccess = false;
CBaseVMPIFileSystem *g_pBaseVMPIFileSystem = NULL;
IFileSystem *g_pOriginalPassThruFileSystem = NULL;
void* GetVMPIFileSystem()
{
return (IBaseFileSystem*)g_pBaseVMPIFileSystem;
}
EXPOSE_INTERFACE_FN( GetVMPIFileSystem, IBaseFileSystem, BASEFILESYSTEM_INTERFACE_VERSION )
IFileSystem* VMPI_FileSystem_Init( int maxMemoryUsage, IFileSystem *pPassThru )
{
Assert( g_bUseMPI );
Assert( !g_pBaseVMPIFileSystem );
g_pOriginalPassThruFileSystem = pPassThru;
if ( g_bMPIMaster )
{
extern CBaseVMPIFileSystem* CreateMasterVMPIFileSystem( int maxMemoryUsage, IFileSystem *pPassThru );
CreateMasterVMPIFileSystem( maxMemoryUsage, pPassThru );
}
else
{
extern CBaseVMPIFileSystem* CreateWorkerVMPIFileSystem();
CreateWorkerVMPIFileSystem();
}
// The Create function should have set this. Normally, we'd set g_pBaseVMPIFileSystem right here, but
// the create functions may want to receive some messages, in which case they need to set g_pBaseVMPIFileSystem
// so the packets get routed appropriately.
Assert( g_pBaseVMPIFileSystem );
return g_pBaseVMPIFileSystem;
}
IFileSystem* VMPI_FileSystem_Term()
{
if ( g_pBaseVMPIFileSystem )
{
g_pBaseVMPIFileSystem->Release();
g_pBaseVMPIFileSystem = NULL;
if ( g_iVMPIVerboseLevel >= 1 )
{
if ( g_bMPIMaster )
Msg( "Multicast send: %dk\n", (g_nMulticastBytesSent + 511) / 1024 );
else
Msg( "Multicast recv: %dk\n", (g_nMulticastBytesReceived + 511) / 1024 );
}
}
IFileSystem *pRet = g_pOriginalPassThruFileSystem;
g_pOriginalPassThruFileSystem = NULL;
return pRet;
}
void VMPI_FileSystem_DisableFileAccess()
{
g_bDisableFileAccess = true;
}
CreateInterfaceFn VMPI_FileSystem_GetFactory()
{
return Sys_GetFactoryThis();
}
void VMPI_FileSystem_CreateVirtualFile( const char *pFilename, const void *pData, unsigned long fileLength )
{
g_pBaseVMPIFileSystem->CreateVirtualFile( pFilename, pData, fileLength );
}
// Register our packet ID.
bool FileSystemRecv( MessageBuffer *pBuf, int iSource, int iPacketID )
{
if ( g_pBaseVMPIFileSystem )
return g_pBaseVMPIFileSystem->HandleFileSystemPacket( pBuf, iSource, iPacketID );
else
return false;
}
CDispatchReg g_DispatchReg_FileSystem( VMPI_PACKETID_FILESYSTEM, FileSystemRecv );
// ------------------------------------------------------------------------------------------------------------------------ //
// CVMPIFile_Memory implementation.
// ------------------------------------------------------------------------------------------------------------------------ //
void CVMPIFile_Memory::Init( const char *pData, long len, char chMode /* = 'b' */ )
{
m_pData = pData;
m_DataLen = len;
m_iCurPos = 0;
m_chMode = chMode;
}
void CVMPIFile_Memory::Close()
{
delete this;
}
void CVMPIFile_Memory::Seek( int pos, FileSystemSeek_t seekType )
{
if ( seekType == FILESYSTEM_SEEK_HEAD )
m_iCurPos = pos;
else if ( seekType == FILESYSTEM_SEEK_CURRENT )
m_iCurPos += pos;
else
m_iCurPos = m_DataLen - pos;
}
unsigned int CVMPIFile_Memory::Tell()
{
return m_iCurPos;
}
unsigned int CVMPIFile_Memory::Size()
{
return m_DataLen;
}
void CVMPIFile_Memory::Flush()
{
}
int CVMPIFile_Memory::Read( void* pOutput, int size )
{
Assert( m_iCurPos >= 0 );
int nToRead = min( (int)(m_DataLen - m_iCurPos), size );
if ( m_chMode != 't' )
{
memcpy( pOutput, &m_pData[m_iCurPos], nToRead );
m_iCurPos += nToRead;
return nToRead;
}
else
{
int iRead = 0;
const char *pData = m_pData + m_iCurPos;
int len = m_DataLen - m_iCurPos;
// Perform crlf translation
while ( const char *crlf = ( const char * ) memchr( pData, '\r', len ) )
{
int canCopy = min( size, crlf - pData );
memcpy( pOutput, pData, canCopy );
m_iCurPos += canCopy;
pData += canCopy;
len -= canCopy;
iRead += canCopy;
( char * & ) pOutput += canCopy;
size -= canCopy;
if ( size && len )
{
if ( ( len > 1 ) && ( pData[1] == '\n' ) )
{
++ m_iCurPos;
++ pData;
-- len;
}
* ( char * & ) pOutput = *pData;
++ m_iCurPos;
++ pData;
-- len;
++ iRead;
++ ( char * & ) pOutput;
-- size;
}
else
break;
}
if ( size && len )
{
// No crlf characters left
int canCopy = min( size, len );
memcpy( pOutput, pData, canCopy );
m_iCurPos += canCopy;
pData += canCopy;
len -= canCopy;
iRead += canCopy;
( char * & ) pOutput += canCopy;
size -= canCopy;
}
return iRead;
}
}
int CVMPIFile_Memory::Write( void const* pInput, int size )
{
Assert( false ); return 0;
}
// ------------------------------------------------------------------------------------------------------------------------ //
// CBaseVMPIFileSystem implementation.
// ------------------------------------------------------------------------------------------------------------------------ //
CBaseVMPIFileSystem::~CBaseVMPIFileSystem()
{
}
void CBaseVMPIFileSystem::Release()
{
delete this;
}
void CBaseVMPIFileSystem::Close( FileHandle_t file )
{
if ( file )
((IVMPIFile*)file)->Close();
}
int CBaseVMPIFileSystem::Read( void* pOutput, int size, FileHandle_t file )
{
return ((IVMPIFile*)file)->Read( pOutput, size );
}
int CBaseVMPIFileSystem::Write( void const* pInput, int size, FileHandle_t file )
{
return ((IVMPIFile*)file)->Write( pInput, size );
}
void CBaseVMPIFileSystem::Seek( FileHandle_t file, int pos, FileSystemSeek_t seekType )
{
((IVMPIFile*)file)->Seek( pos, seekType );
}
unsigned int CBaseVMPIFileSystem::Tell( FileHandle_t file )
{
return ((IVMPIFile*)file)->Tell();
}
unsigned int CBaseVMPIFileSystem::Size( FileHandle_t file )
{
return ((IVMPIFile*)file)->Size();
}
unsigned int CBaseVMPIFileSystem::Size( const char *pFilename, const char *pathID = 0 )
{
FileHandle_t hFile = Open( pFilename, "rb", NULL );
if ( hFile == FILESYSTEM_INVALID_HANDLE )
{
return 0;
}
else
{
unsigned int ret = Size( hFile );
Close( hFile );
return ret;
}
}
bool CBaseVMPIFileSystem::FileExists( const char *pFileName, const char *pPathID )
{
FileHandle_t hFile = Open( pFileName, "rb", NULL );
if ( hFile )
{
Close( hFile );
return true;
}
else
{
return false;
}
}
void CBaseVMPIFileSystem::Flush( FileHandle_t file )
{
((IVMPIFile*)file)->Flush();
}
bool CBaseVMPIFileSystem::Precache( const char* pFileName, const char *pPathID )
{
return false;
}
//-----------------------------------------------------------------------------
// NOTE: This is an exact copy of code in BaseFileSystem.cpp which
// has to be here because they want to call
// the implementation of Open/Size/Read/Write in CBaseVMPIFileSystem
//-----------------------------------------------------------------------------
bool CBaseVMPIFileSystem::ReadFile( const char *pFileName, const char *pPath, CUtlBuffer &buf, int nMaxBytes, int nStartingByte, FSAllocFunc_t pfnAlloc )
{
const char *pReadFlags = "rb";
if ( buf.IsText() && !buf.ContainsCRLF() )
{
pReadFlags = "rt";
}
FileHandle_t fp = Open( pFileName, buf.IsText() ? "rt" : "rb", pPath );
if ( !fp )
return false;
int nBytesToRead = Size( fp );
if ( nMaxBytes > 0 )
{
nBytesToRead = min( nMaxBytes, nBytesToRead );
}
buf.EnsureCapacity( nBytesToRead + buf.TellPut() );
if ( nStartingByte != 0 )
{
Seek( fp, nStartingByte, FILESYSTEM_SEEK_HEAD );
}
int nBytesRead = Read( buf.PeekPut(), nBytesToRead, fp );
buf.SeekPut( CUtlBuffer::SEEK_CURRENT, nBytesRead );
Close( fp );
return (nBytesRead != 0);
}
bool CBaseVMPIFileSystem::WriteFile( const char *pFileName, const char *pPath, CUtlBuffer &buf )
{
const char *pWriteFlags = "wb";
if ( buf.IsText() && !buf.ContainsCRLF() )
{
pWriteFlags = "wt";
}
FileHandle_t fp = Open( pFileName, buf.IsText() ? "wt" : "wb", pPath );
if ( !fp )
return false;
int nBytesWritten = Write( buf.Base(), buf.TellPut(), fp );
Close( fp );
return (nBytesWritten != 0);
}