summaryrefslogtreecommitdiff
path: root/tier2/fileutils.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /tier2/fileutils.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'tier2/fileutils.cpp')
-rw-r--r--tier2/fileutils.cpp304
1 files changed, 304 insertions, 0 deletions
diff --git a/tier2/fileutils.cpp b/tier2/fileutils.cpp
new file mode 100644
index 0000000..2a0ca59
--- /dev/null
+++ b/tier2/fileutils.cpp
@@ -0,0 +1,304 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Helper methods + classes for file access
+//
+//===========================================================================//
+
+#include "tier2/fileutils.h"
+#include "tier2/tier2.h"
+#include "tier1/strtools.h"
+#include "filesystem.h"
+#include "tier0/icommandline.h"
+#include "tier1/utlbuffer.h"
+
+// NOTE: This has to be the last file included!
+#include "tier0/memdbgon.h"
+
+//-----------------------------------------------------------------------------
+// Builds a directory which is a subdirectory of the current mod
+//-----------------------------------------------------------------------------
+void GetModSubdirectory( const char *pSubDir, char *pBuf, int nBufLen )
+{
+ // Compute starting directory
+ Assert( g_pFullFileSystem->GetSearchPath( "MOD_WRITE", false, NULL, 0 ) < nBufLen );
+ if ( g_pFullFileSystem->GetSearchPath( "MOD_WRITE", false, pBuf, nBufLen ) == 0 )
+ {
+ // if we didn't find MOD_WRITE, back to the old MOD
+ Assert( g_pFullFileSystem->GetSearchPath( "MOD", false, NULL, 0 ) < nBufLen );
+ g_pFullFileSystem->GetSearchPath( "MOD", false, pBuf, nBufLen );
+ }
+
+ char *pSemi = strchr( pBuf, ';' );
+ if ( pSemi )
+ {
+ *pSemi = 0;
+ }
+
+ Q_StripTrailingSlash( pBuf );
+ if ( pSubDir )
+ {
+ int nLen = Q_strlen( pSubDir );
+ Q_strncat( pBuf, "\\", nBufLen, 1 );
+ Q_strncat( pBuf, pSubDir, nBufLen, nLen );
+ }
+
+ Q_FixSlashes( pBuf );
+}
+
+
+//-----------------------------------------------------------------------------
+// Builds a directory which is a subdirectory of the current mod's *content*
+//-----------------------------------------------------------------------------
+void GetModContentSubdirectory( const char *pSubDir, char *pBuf, int nBufLen )
+{
+ char pTemp[ MAX_PATH ];
+ GetModSubdirectory( pSubDir, pTemp, sizeof(pTemp) );
+ ComputeModContentFilename( pTemp, pBuf, nBufLen );
+}
+
+
+//-----------------------------------------------------------------------------
+// Generates a filename under the 'game' subdirectory given a subdirectory of 'content'
+//-----------------------------------------------------------------------------
+void ComputeModFilename( const char *pContentFileName, char *pBuf, size_t nBufLen )
+{
+ char pRelativePath[ MAX_PATH ];
+ if ( !g_pFullFileSystem->FullPathToRelativePathEx( pContentFileName, "CONTENTROOT", pRelativePath, sizeof(pRelativePath) ) )
+ {
+ Q_strncpy( pBuf, pContentFileName, (int)nBufLen );
+ return;
+ }
+
+ char pGameRoot[ MAX_PATH ];
+ g_pFullFileSystem->GetSearchPath( "GAMEROOT", false, pGameRoot, sizeof(pGameRoot) );
+ char *pSemi = strchr( pGameRoot, ';' );
+ if ( pSemi )
+ {
+ *pSemi = 0;
+ }
+
+ Q_ComposeFileName( pGameRoot, pRelativePath, pBuf, (int)nBufLen );
+}
+
+
+//-----------------------------------------------------------------------------
+// Generates a filename under the 'content' subdirectory given a subdirectory of 'game'
+//-----------------------------------------------------------------------------
+void ComputeModContentFilename( const char *pGameFileName, char *pBuf, size_t nBufLen )
+{
+ char pRelativePath[ MAX_PATH ];
+ if ( !g_pFullFileSystem->FullPathToRelativePathEx( pGameFileName, "GAMEROOT", pRelativePath, sizeof(pRelativePath) ) )
+ {
+ Q_strncpy( pBuf, pGameFileName, (int)nBufLen );
+ return;
+ }
+
+ char pContentRoot[ MAX_PATH ];
+ g_pFullFileSystem->GetSearchPath( "CONTENTROOT", false, pContentRoot, sizeof(pContentRoot) );
+ char *pSemi = strchr( pContentRoot, ';' );
+ if ( pSemi )
+ {
+ *pSemi = 0;
+ }
+
+ Q_ComposeFileName( pContentRoot, pRelativePath, pBuf, (int)nBufLen );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Generates an Xbox 360 filename from a PC filename
+//-----------------------------------------------------------------------------
+char *CreateX360Filename( const char *pSourceName, char *pTargetName, int targetLen )
+{
+ Q_StripExtension( pSourceName, pTargetName, targetLen );
+ int idx = Q_strlen( pTargetName );
+
+ // restore extension
+ Q_snprintf( pTargetName, targetLen, "%s.360%s", pTargetName, &pSourceName[idx] );
+
+ return pTargetName;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Generates a PC filename from a possible 360 name.
+// Strips the .360. from filename.360.extension.
+// Filenames might have multiple '.', need to be careful and only consider the
+// last true extension. Complex filenames do occur:
+// d:\foo\.\foo.dat
+// d:\zip0.360.zip\foo.360.dat
+// Returns source if no change needs to occur, othwerwise generates and
+// returns target.
+//-----------------------------------------------------------------------------
+char *RestoreFilename( const char *pSourceName, char *pTargetName, int targetLen )
+{
+ // find extension
+ // scan backward for '.', but not past a seperator
+ int end = V_strlen( pSourceName ) - 1;
+ while ( end > 0 && pSourceName[end] != '.' && !( pSourceName[end] == '\\' || pSourceName[end] == '/' ) )
+ {
+ --end;
+ }
+
+ if ( end >= 4 && pSourceName[end] == '.' && !V_strncmp( pSourceName + end - 4 , ".360", 4 ) )
+ {
+ // cull the .360, leave the trailing extension
+ end -= 4;
+ int length = MIN( end + 1, targetLen );
+ V_strncpy( pTargetName, pSourceName, length );
+ V_strncat( pTargetName, pSourceName + end + 4, targetLen );
+
+ return pTargetName;
+ }
+
+ // source filename is as expected
+ return (char *)pSourceName;
+}
+
+//-----------------------------------------------------------------------------
+// Generate an Xbox 360 file if it doesn't exist or is out of date. This function determines
+// the source and target path and whether the file needs to be generated. The caller provides
+// a callback function to do the actual creation of the 360 file. "pExtraData" is for the caller to
+// pass the address of any data that the callback function may need to access. This function
+// is ONLY to be called by caller's who expect to have 360 versions of their file.
+//-----------------------------------------------------------------------------
+int UpdateOrCreate( const char *pSourceName, char *pTargetName, int targetLen, const char *pPathID, CreateCallback_t pfnCreate, bool bForce, void *pExtraData )
+{
+ if ( pTargetName )
+ {
+ // caller could supply source as PC or 360 name, we want the PC filename
+ char szFixedSourceName[MAX_PATH];
+ pSourceName = RestoreFilename( pSourceName, szFixedSourceName, sizeof( szFixedSourceName ) );
+ // caller wants us to provide 360 named version of source
+ CreateX360Filename( pSourceName, pTargetName, targetLen );
+ }
+
+ // no conversion are performed by the game at runtime anymore
+ // SMB access was removed by the XDK for Vista....
+ return UOC_NOT_CREATED;
+}
+
+
+//-----------------------------------------------------------------------------
+// Returns the search path as a list of paths
+//-----------------------------------------------------------------------------
+void GetSearchPath( CUtlVector< CUtlString > &path, const char *pPathID )
+{
+ int nMaxLen = g_pFullFileSystem->GetSearchPath( pPathID, false, NULL, 0 );
+ char *pBuf = (char*)stackalloc( nMaxLen );
+ g_pFullFileSystem->GetSearchPath( pPathID, false, pBuf, nMaxLen );
+
+ char *pSemi;
+ while ( NULL != ( pSemi = strchr( pBuf, ';' ) ) )
+ {
+ *pSemi = 0;
+ path.AddToTail( pBuf );
+ pBuf = pSemi + 1;
+ }
+ path.AddToTail( pBuf );
+}
+
+//-----------------------------------------------------------------------------
+// Given file name in the current dir generate a full path to it.
+//-----------------------------------------------------------------------------
+bool GenerateFullPath( const char *pFileName, char const *pPathID, char *pBuf, int nBufLen )
+{
+ if ( V_IsAbsolutePath( pFileName ) )
+ {
+ V_strncpy( pBuf, pFileName, nBufLen );
+ return true;
+ }
+
+ const char *pFullPath = g_pFullFileSystem->RelativePathToFullPath( pFileName, pPathID, pBuf, nBufLen );
+ if ( pFullPath && Q_IsAbsolutePath( pFullPath ) )
+ return true;
+
+ char pDir[ MAX_PATH ];
+ if ( !g_pFullFileSystem->GetCurrentDirectory( pDir, sizeof( pDir ) ) )
+ return false;
+
+ V_ComposeFileName( pDir, pFileName, pBuf, nBufLen );
+ V_RemoveDotSlashes( pBuf );
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Builds a list of all files under a directory with a particular extension
+//-----------------------------------------------------------------------------
+void AddFilesToList( CUtlVector< CUtlString > &list, const char *pDirectory, const char *pPathID, const char *pExtension )
+{
+ char pSearchString[MAX_PATH];
+ Q_snprintf( pSearchString, MAX_PATH, "%s\\*", pDirectory );
+
+ bool bIsAbsolute = Q_IsAbsolutePath( pDirectory );
+
+ // get the list of files
+ FileFindHandle_t hFind;
+ const char *pFoundFile = g_pFullFileSystem->FindFirstEx( pSearchString, pPathID, &hFind );
+
+ // add all the items
+ CUtlVector< CUtlString > subDirs;
+ for ( ; pFoundFile; pFoundFile = g_pFullFileSystem->FindNext( hFind ) )
+ {
+ char pChildPath[MAX_PATH];
+ Q_snprintf( pChildPath, MAX_PATH, "%s\\%s", pDirectory, pFoundFile );
+
+ if ( g_pFullFileSystem->FindIsDirectory( hFind ) )
+ {
+ if ( Q_strnicmp( pFoundFile, ".", 2 ) && Q_strnicmp( pFoundFile, "..", 3 ) )
+ {
+ subDirs.AddToTail( pChildPath );
+ }
+ continue;
+ }
+
+ // Check the extension matches
+ const char *pExt = Q_GetFileExtension( pFoundFile );
+ if ( !pExt || Q_stricmp( pExt, pExtension ) != 0 )
+ continue;
+
+ char pFullPathBuf[MAX_PATH];
+ char *pFullPath = pFullPathBuf;
+ if ( !bIsAbsolute )
+ {
+ g_pFullFileSystem->RelativePathToFullPath( pChildPath, pPathID, pFullPathBuf, sizeof(pFullPathBuf) );
+ }
+ else
+ {
+ pFullPath = pChildPath;
+ }
+
+ V_strlower( pFullPath );
+ Q_FixSlashes( pFullPath );
+ list.AddToTail( pFullPath );
+ }
+
+ g_pFullFileSystem->FindClose( hFind );
+
+ int nCount = subDirs.Count();
+ for ( int i = 0; i < nCount; ++i )
+ {
+ AddFilesToList( list, subDirs[i], pPathID, pExtension );
+ }
+}
+
+void CBaseFile::ReadLines( CUtlStringList &lineList, int nMaxLineLength )
+{
+ char *pLine = ( char * ) stackalloc( nMaxLineLength );
+ while( ReadLine( pLine, nMaxLineLength ) )
+ {
+ char *pEOL = strchr( pLine, '\n' ); // kill the \n
+ if ( pEOL )
+ *pEOL = 0;
+ lineList.CopyAndAddToTail( pLine );
+ }
+}
+
+void CBaseFile::ReadFile( CUtlBuffer &fileData )
+{
+ int nFileSize = Size();
+ fileData.EnsureCapacity( Size() );
+ int nSize = Read( fileData.Base(), nFileSize );
+ fileData.SeekPut( CUtlBuffer::SEEK_HEAD, nSize );
+}
+
+