From 88e52d51b9477a048b4ede54098c94052b49fb97 Mon Sep 17 00:00:00 2001 From: Garux Date: Sat, 6 Dec 2025 01:11:05 +0500 Subject: [PATCH] refactor InitDirectory() --- plugins/vfspk3/archive.cpp | 2 +- plugins/vfspk3/vfs.cpp | 174 +++++++----------------------------- tools/quake3/common/vfs.cpp | 4 +- 3 files changed, 37 insertions(+), 143 deletions(-) diff --git a/plugins/vfspk3/archive.cpp b/plugins/vfspk3/archive.cpp index 17b0aa4b..44bf85a4 100644 --- a/plugins/vfspk3/archive.cpp +++ b/plugins/vfspk3/archive.cpp @@ -92,7 +92,7 @@ public: } else if ( const char *ext = path_get_extension( name ); !string_equal( name, "." ) && !string_equal( name, ".." ) - /* skip .pk3dir / .pk4dir / .dpkdir the in root, it is processed as DirectoryArchive */ + /* skip .pk3dir / .pk4dir / .dpkdir / .pakdir / .waddir the in root, they are processed as DirectoryArchive */ && !( string_empty( root ) && string_length( ext ) == 6 && string_equal_nocase( ext + 3, "dir" ) ) ) { path.push_filename( name ); diff --git a/plugins/vfspk3/vfs.cpp b/plugins/vfspk3/vfs.cpp index 61deb14f..f8b4d270 100644 --- a/plugins/vfspk3/vfs.cpp +++ b/plugins/vfspk3/vfs.cpp @@ -59,15 +59,7 @@ ArchiveModules& FileSystemQ3API_getArchiveModules(); #include "os/path.h" #include "moduleobservers.h" #include "filematch.h" - - -#define VFS_MAXDIRS 64 - -#if defined( WIN32 ) -#define PATH_MAX 260 -#endif - -#define gamemode_get GlobalRadiant().getGameMode +#include @@ -83,15 +75,9 @@ struct archive_entry_t bool is_pakfile; }; -#include - using archives_t = std::list; static archives_t g_archives; -static char g_strDirs[VFS_MAXDIRS][PATH_MAX + 1]; -static int g_numDirs; -static char g_strForbiddenDirs[VFS_MAXDIRS][PATH_MAX + 1]; -static int g_numForbiddenDirs = 0; static constexpr bool g_bUsePak = true; ModuleObservers g_observers; @@ -101,34 +87,6 @@ using StrList = std::vector; // ============================================================================= // Static functions -static void AddSlash( char *str ){ - std::size_t n = strlen( str ); - if ( n > 0 ) { - if ( str[n - 1] != '\\' && str[n - 1] != '/' ) { - globalWarningStream() << "WARNING: directory path does not end with separator: " << str << '\n'; - strcat( str, "/" ); - } - } -} - -static void FixDOSName( char *src ){ - if ( src == 0 || strchr( src, '\\' ) == 0 ) { - return; - } - - globalWarningStream() << "WARNING: invalid path separator '\\': " << src << '\n'; - - while ( *src ) - { - if ( *src == '\\' ) { - *src = '/'; - } - src++; - } -} - - - const _QERArchiveTable* GetArchiveTable( ArchiveModules& archiveModules, const char* ext ){ return archiveModules.findModule( StringStream<16>( LowerCase( ext ) ) ); } @@ -237,73 +195,48 @@ typedef std::set Archives; // reads all pak files from a dir void InitDirectory( const char* directory, ArchiveModules& archiveModules ){ - int j; - - g_numForbiddenDirs = 0; + std::vector strForbiddenDirs; StringTokeniser st( GlobalRadiant().getGameDescriptionKeyValue( "forbidden_paths" ), " " ); - for ( j = 0; j < VFS_MAXDIRS; ++j ) + for ( const char *t; !string_empty( t = st.getToken() ); ) { - const char *t = st.getToken(); - if ( string_empty( t ) ) { - break; - } - strncpy( g_strForbiddenDirs[g_numForbiddenDirs], t, PATH_MAX ); - g_strForbiddenDirs[g_numForbiddenDirs][PATH_MAX] = '\0'; - ++g_numForbiddenDirs; + strForbiddenDirs.push_back( t ); } - for ( j = 0; j < g_numForbiddenDirs; ++j ) + const auto path_is_forbidden = [&strForbiddenDirs]( const char *path ){ + return std::ranges::any_of( strForbiddenDirs, [name = path_get_filename_start( path )]( const CopiedString& forbidden ){ + return matchpattern( name, forbidden.c_str(), TRUE ); + } ); + }; + { - char* dbuf = g_strdup( directory ); - if ( *dbuf && dbuf[strlen( dbuf ) - 1] == '/' ) { - dbuf[strlen( dbuf ) - 1] = 0; + StringBuffer buf( directory ); + if ( !buf.empty() && path_separator( buf.back() ) ) // del trailing slash + buf.pop_back(); + if ( path_is_forbidden( buf.c_str() ) ){ + printf( "Directory %s matched by forbidden dirs, removed\n", directory ); + return; } - const char *p = strrchr( dbuf, '/' ); - p = ( p ? ( p + 1 ) : dbuf ); - if ( matchpattern( p, g_strForbiddenDirs[j], TRUE ) ) { - g_free( dbuf ); - break; - } - g_free( dbuf ); - } - if ( j < g_numForbiddenDirs ) { - printf( "Directory %s matched by forbidden dirs, removed\n", directory ); - return; } - if ( g_numDirs == VFS_MAXDIRS ) { - return; - } - strncpy( g_strDirs[g_numDirs], directory, PATH_MAX ); - g_strDirs[g_numDirs][PATH_MAX] = '\0'; - FixDOSName( g_strDirs[g_numDirs] ); - AddSlash( g_strDirs[g_numDirs] ); - - const char* path = g_strDirs[g_numDirs]; - - g_numDirs++; - - g_archives.push_back( archive_entry_t{ path, OpenArchive( path ), false } ); + auto stream = StringStream( DirectoryCleaned( directory ) ); + const char *path = g_archives.emplace_back( archive_entry_t{ stream.c_str(), OpenArchive( stream ), false } ).name.c_str(); if ( g_bUsePak ) { - GDir* dir = g_dir_open( path, 0, 0 ); - - if ( dir != 0 ) { + if ( GDir* dir = g_dir_open( path, 0, 0 ) ) { globalOutputStream() << "vfs directory: " << path << '\n'; const char* ignore_prefix = ""; const char* override_prefix = ""; - { // See if we are in "sp" or "mp" mapping mode - const char* gamemode = gamemode_get(); + const char* gamemode = GlobalRadiant().getGameMode(); - if ( strcmp( gamemode, "sp" ) == 0 ) { + if ( string_equal( gamemode, "sp" ) ) { ignore_prefix = "mp_"; override_prefix = "sp_"; } - else if ( strcmp( gamemode, "mp" ) == 0 ) { + else if ( string_equal( gamemode, "mp" ) ) { ignore_prefix = "sp_"; override_prefix = "mp_"; } @@ -311,37 +244,17 @@ void InitDirectory( const char* directory, ArchiveModules& archiveModules ){ Archives archives; Archives archivesOverride; - for (;; ) + while ( const char* name = g_dir_read_name( dir ) ) { - const char* name = g_dir_read_name( dir ); - if ( name == 0 ) { - break; - } - - for ( j = 0; j < g_numForbiddenDirs; ++j ) - { - const char *p = strrchr( name, '/' ); - p = ( p ? ( p + 1 ) : name ); - if ( matchpattern( p, g_strForbiddenDirs[j], TRUE ) ) { - break; - } - } - if ( j < g_numForbiddenDirs ) { + if ( path_is_forbidden( name ) ) { continue; } const char *ext = path_get_extension( name ); - /* .pk3dir / .pk4dir / .dpkdir */ + /* .pk3dir / .pk4dir / .dpkdir / .pakdir / .waddir */ if ( string_equal_suffix_nocase( ext, "dir" ) && GetArchiveTable( archiveModules, ( const char[] ){ ext[0], ext[1], ext[2], '\0' } ) != nullptr ) { - if ( g_numDirs == VFS_MAXDIRS ) { - continue; - } - std::snprintf( g_strDirs[g_numDirs], PATH_MAX, "%s%s/", path, name ); - FixDOSName( g_strDirs[g_numDirs] ); - AddSlash( g_strDirs[g_numDirs] ); - g_numDirs++; - - g_archives.push_back( archive_entry_t{ g_strDirs[g_numDirs - 1], OpenArchive( g_strDirs[g_numDirs - 1] ), false } ); + stream( path, name, '/' ); + g_archives.push_back( archive_entry_t{ stream.c_str(), OpenArchive( stream ), false } ); } if ( GetArchiveTable( archiveModules, ext ) == nullptr ) { @@ -349,10 +262,10 @@ void InitDirectory( const char* directory, ArchiveModules& archiveModules ){ } // using the same kludge as in engine to ensure consistency - if ( !string_empty( ignore_prefix ) && strncmp( name, ignore_prefix, strlen( ignore_prefix ) ) == 0 ) { + if ( !string_empty( ignore_prefix ) && string_equal_prefix( name, ignore_prefix ) ) { continue; } - if ( !string_empty( override_prefix ) && strncmp( name, override_prefix, strlen( override_prefix ) ) == 0 ) { + if ( !string_empty( override_prefix ) && string_equal_prefix( name, override_prefix ) ) { archivesOverride.insert( name ); continue; } @@ -365,17 +278,11 @@ void InitDirectory( const char* directory, ArchiveModules& archiveModules ){ // add the entries to the vfs for ( const auto& archive : archivesOverride ) { - char filename[PATH_MAX]; - strcpy( filename, path ); - strcat( filename, archive.c_str() ); - InitPakFile( archiveModules, filename ); + InitPakFile( archiveModules, stream( path, archive.c_str() ) ); } for ( const auto& archive : archives ) { - char filename[PATH_MAX]; - strcpy( filename, path ); - strcat( filename, archive.c_str() ); - InitPakFile( archiveModules, filename ); + InitPakFile( archiveModules, stream( path, archive.c_str() ) ); } } else @@ -394,9 +301,6 @@ void Shutdown(){ arch.archive->release(); } g_archives.clear(); - - g_numDirs = 0; - g_numForbiddenDirs = 0; } #define VFS_SEARCH_PAK 0x1 @@ -404,11 +308,7 @@ void Shutdown(){ int GetFileCount( const char *filename, int flag ){ int count = 0; - char fixed[PATH_MAX + 1]; - - strncpy( fixed, filename, PATH_MAX ); - fixed[PATH_MAX] = '\0'; - FixDOSName( fixed ); + const auto fixed = StringStream( PathCleaned( filename ) ); if ( !flag ) { flag = VFS_SEARCH_PAK | VFS_SEARCH_DIR; @@ -455,15 +355,9 @@ ArchiveTextFile* OpenTextFile( const char* filename ){ // NOTE: when loading a file, you have to allocate one extra byte and set it to \0 std::size_t LoadFile( const char *filename, void **bufferptr, int index ){ - char fixed[PATH_MAX + 1]; + const auto fixed = StringStream( PathCleaned( filename ) ); - strncpy( fixed, filename, PATH_MAX ); - fixed[PATH_MAX] = '\0'; - FixDOSName( fixed ); - - ArchiveFile* file = OpenFile( fixed ); - - if ( file != 0 ) { + if ( ArchiveFile* file = OpenFile( fixed ) ) { *bufferptr = malloc( file->size() + 1 ); // we need to end the buffer with a 0 ( (char*) ( *bufferptr ) )[file->size()] = 0; diff --git a/tools/quake3/common/vfs.cpp b/tools/quake3/common/vfs.cpp index b032abe4..ca16e9ab 100644 --- a/tools/quake3/common/vfs.cpp +++ b/tools/quake3/common/vfs.cpp @@ -139,8 +139,8 @@ static void vfsInitPakFile( const char *filename ){ // reads all pak files from a dir void vfsInitDirectory( const char *path, const char *pk3ext, const char *pk3dirext ){ const auto path_is_forbidden = []( const char *path ){ - return std::ranges::any_of( g_strForbiddenDirs, [path]( const CopiedString& forbidden ){ - return matchpattern( path_get_filename_start( path ), forbidden.c_str(), TRUE ); + return std::ranges::any_of( g_strForbiddenDirs, [name = path_get_filename_start( path )]( const CopiedString& forbidden ){ + return matchpattern( name, forbidden.c_str(), TRUE ); } ); };