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