reduce the use of GSlist

Quake3FileSystem::forEachFile: avoid double extension check, support "*", as advertised
This commit is contained in:
Garux
2021-08-19 12:28:56 +03:00
parent 41c3dfc96e
commit aa4f3a1f72
8 changed files with 117 additions and 195 deletions

View File

@@ -1511,11 +1511,7 @@ IShader *Shader_ForName( const char *name ){
// the list of scripts/*.shader files we need to work with
// those are listed in shaderlist file
GSList *l_shaderfiles = 0;
GSList* Shaders_getShaderFileList(){
return l_shaderfiles;
}
std::vector<CopiedString> l_shaderfiles;
/*
==================
@@ -1526,9 +1522,9 @@ GSList* Shaders_getShaderFileList(){
void IfFound_dumpUnreferencedShader( bool& bFound, const char* filename ){
bool listed = false;
for ( GSList* sh = l_shaderfiles; sh != 0; sh = g_slist_next( sh ) )
for ( const CopiedString& sh : l_shaderfiles )
{
if ( !strcmp( (char*)sh->data, filename ) ) {
if ( !strcmp( sh.c_str(), filename ) ) {
listed = true;
break;
}
@@ -1552,17 +1548,17 @@ void DumpUnreferencedShaders(){
void ShaderList_addShaderFile( const char* dirstring ){
bool found = false;
for ( GSList* tmp = l_shaderfiles; tmp != 0; tmp = tmp->next )
for ( const CopiedString& sh : l_shaderfiles )
{
if ( string_equal_nocase( dirstring, (char*)tmp->data ) ) {
if ( string_equal_nocase( dirstring, sh.c_str() ) ) {
found = true;
globalOutputStream() << "duplicate entry \"" << (char*)tmp->data << "\" in shaderlist.txt\n";
globalOutputStream() << "duplicate entry \"" << sh.c_str() << "\" in shaderlist.txt\n";
break;
}
}
if ( !found ) {
l_shaderfiles = g_slist_append( l_shaderfiles, strdup( dirstring ) );
l_shaderfiles.emplace_back( dirstring );
}
}
@@ -1597,14 +1593,6 @@ void BuildShaderList( TextInputStream& shaderlist ){
tokeniser.release();
}
void FreeShaderList(){
while ( l_shaderfiles != 0 )
{
free( l_shaderfiles->data );
l_shaderfiles = g_slist_remove( l_shaderfiles, l_shaderfiles->data );
}
}
void ShaderList_addFromArchive( const char *archivename ){
const char *shaderpath = GlobalRadiant().getGameDescriptionKeyValue( "shaderpath" );
if ( string_empty( shaderpath ) ) {
@@ -1673,7 +1661,7 @@ void Shaders_Load(){
}
GlobalFileSystem().forEachArchive( AddShaderListFromArchiveCaller(), false, true );
if( l_shaderfiles != nullptr ){
if( !l_shaderfiles.empty() ){
DumpUnreferencedShaders();
}
else{
@@ -1686,14 +1674,12 @@ void Shaders_Load(){
GlobalFileSystem().forEachFile( path.c_str(), g_shadersExtension, AddShaderFileCaller(), 0 );
}
GSList *lst = l_shaderfiles;
StringOutputStream shadername( 256 );
while ( lst )
for( const CopiedString& sh : l_shaderfiles )
{
shadername << path.c_str() << reinterpret_cast<const char*>( lst->data );
shadername << path.c_str() << sh.c_str();
LoadShaderFile( shadername.c_str() );
shadername.clear();
lst = lst->next;
}
}
@@ -1702,7 +1688,7 @@ void Shaders_Load(){
void Shaders_Free(){
FreeShaders();
FreeShaderList();
l_shaderfiles.clear();
g_shaderFilenames.clear();
}

View File

@@ -85,7 +85,7 @@ struct archive_entry_t
#include <list>
typedef std::list<archive_entry_t> archives_t;
using archives_t = std::list<archive_entry_t>;
static archives_t g_archives;
static char g_strDirs[VFS_MAXDIRS][PATH_MAX + 1];
@@ -96,6 +96,8 @@ static constexpr bool g_bUsePak = true;
ModuleObservers g_observers;
using StrList = std::vector<CopiedString>;
// =============================================================================
// Static functions
@@ -146,22 +148,18 @@ static void InitPakFile( ArchiveModules& archiveModules, const char *filename ){
}
}
inline void pathlist_prepend_unique( GSList*& pathlist, char* path ){
if ( g_slist_find_custom( pathlist, path, (GCompareFunc)path_compare ) == 0 ) {
pathlist = g_slist_prepend( pathlist, path );
}
else
{
g_free( path );
}
inline void pathlist_append_unique( StrList& pathlist, CopiedString path ){
if( pathlist.cend() == std::find_if( pathlist.cbegin(), pathlist.cend(),
[&path]( const CopiedString& str ){ return path_compare( str.c_str(), path.c_str() ) == 0; } ) )
pathlist.emplace_back( std::move( path ) );
}
class DirectoryListVisitor : public Archive::Visitor
{
GSList*& m_matches;
StrList& m_matches;
const char* m_directory;
public:
DirectoryListVisitor( GSList*& matches, const char* directory )
DirectoryListVisitor( StrList& matches, const char* directory )
: m_matches( matches ), m_directory( directory )
{}
void visit( const char* name ){
@@ -170,23 +168,22 @@ public:
if ( subname[0] == '/' ) {
++subname;
}
char* dir = g_strdup( subname );
char* last_char = dir + strlen( dir );
if ( last_char != dir && *( --last_char ) == '/' ) {
*last_char = '\0';
const char* last_char = subname + strlen( subname );
if ( last_char != subname && *( last_char - 1 ) == '/' ) {
--last_char;
}
pathlist_prepend_unique( m_matches, dir );
pathlist_append_unique( m_matches, StringRange( subname, last_char ) );
}
}
};
class FileListVisitor : public Archive::Visitor
{
GSList*& m_matches;
StrList& m_matches;
const char* m_directory;
const char* m_extension;
public:
FileListVisitor( GSList*& matches, const char* directory, const char* extension )
FileListVisitor( StrList& matches, const char* directory, const char* extension )
: m_matches( matches ), m_directory( directory ), m_extension( extension )
{}
void visit( const char* name ){
@@ -196,14 +193,14 @@ public:
++subname;
}
if ( m_extension[0] == '*' || extension_equal( path_get_extension( subname ), m_extension ) ) {
pathlist_prepend_unique( m_matches, g_strdup( subname ) );
pathlist_append_unique( m_matches, subname );
}
}
}
};
static GSList* GetListInternal( const char *refdir, const char *ext, bool directories, std::size_t depth ){
GSList* files = 0;
static StrList GetListInternal( const char *refdir, const char *ext, bool directories, std::size_t depth ){
StrList files;
ASSERT_MESSAGE( refdir[strlen( refdir ) - 1] == '/', "search path does not end in '/'" );
@@ -223,8 +220,6 @@ static GSList* GetListInternal( const char *refdir, const char *ext, bool direct
}
}
files = g_slist_reverse( files );
return files;
}
@@ -507,22 +502,14 @@ void FreeFile( void *p ){
free( p );
}
GSList* GetFileList( const char *dir, const char *ext, std::size_t depth ){
StrList GetFileList( const char *dir, const char *ext, std::size_t depth ){
return GetListInternal( dir, ext, false, depth );
}
GSList* GetDirList( const char *dir, std::size_t depth ){
StrList GetDirList( const char *dir, std::size_t depth ){
return GetListInternal( dir, 0, true, depth );
}
void ClearFileDirList( GSList **lst ){
while ( *lst )
{
g_free( ( *lst )->data );
*lst = g_slist_remove( *lst, ( *lst )->data );
}
}
const char* FindFile( const char* relative ){
for ( archives_t::iterator i = g_archives.begin(); i != g_archives.end(); ++i )
{
@@ -582,37 +569,31 @@ public:
}
void forEachDirectory( const char* basedir, const FileNameCallback& callback, std::size_t depth ){
GSList* list = GetDirList( basedir, depth );
StrList list = GetDirList( basedir, depth );
for ( GSList* i = list; i != 0; i = g_slist_next( i ) )
for ( const CopiedString& str : list )
{
callback( reinterpret_cast<const char*>( ( *i ).data ) );
callback( str.c_str() );
}
ClearFileDirList( &list );
}
void forEachFile( const char* basedir, const char* extension, const FileNameCallback& callback, std::size_t depth ){
GSList* list = GetFileList( basedir, extension, depth );
StrList list = GetFileList( basedir, extension, depth );
for ( GSList* i = list; i != 0; i = g_slist_next( i ) )
for ( const CopiedString& str : list )
{
const char* name = reinterpret_cast<const char*>( ( *i ).data );
if ( extension_equal( path_get_extension( name ), extension ) ) {
callback( name );
}
callback( str.c_str() );
}
ClearFileDirList( &list );
}
GSList* getDirList( const char *basedir ){
/// \brief Returns a list containing the relative names of all the directories under \p basedir.
/// \deprecated Deprecated - use \c forEachDirectory.
StrList getDirList( const char *basedir ){
return GetDirList( basedir, 1 );
}
GSList* getFileList( const char *basedir, const char *extension ){
/// \brief Returns a list containing the relative names of the files under \p basedir (\p extension can be "*" for all files).
/// \deprecated Deprecated - use \c forEachFile.
StrList getFileList( const char *basedir, const char *extension ){
return GetFileList( basedir, extension, 1 );
}
void clearFileDirList( GSList **lst ){
ClearFileDirList( lst );
}
const char* findFile( const char *name ){
return FindFile( name );