- use ScanDirectory in all places where the findfile API was used.

This allows to completely hide its implementation details from the rest of the code which only gets a list of file names now.
This commit is contained in:
Christoph Oelckers 2023-08-19 12:18:35 +02:00
commit 5f3d25ef44
15 changed files with 262 additions and 675 deletions

View file

@ -38,160 +38,8 @@
#include "printf.h"
#include "configfile.h"
#include "i_system.h"
#include "fs_findfile.h"
#ifndef _WIN32
#include <unistd.h>
#include <fnmatch.h>
#include <sys/stat.h>
#include "cmdlib.h"
static const char *pattern;
static int matchfile(const struct dirent *ent)
{
return fnmatch(pattern, ent->d_name, FNM_NOESCAPE) == 0;
}
void *I_FindFirst(const char *const filespec, findstate_t *const fileinfo)
{
FString dir;
const char *const slash = strrchr(filespec, '/');
if (slash)
{
pattern = slash + 1;
dir = FString(filespec, slash - filespec + 1);
fileinfo->path = dir;
}
else
{
pattern = filespec;
dir = ".";
}
fileinfo->current = 0;
fileinfo->count = scandir(dir.GetChars(), &fileinfo->namelist, matchfile, alphasort);
if (fileinfo->count > 0)
{
return fileinfo;
}
return (void *)-1;
}
int I_FindNext(void *const handle, findstate_t *const fileinfo)
{
findstate_t *const state = static_cast<findstate_t *>(handle);
if (state->current < fileinfo->count)
{
return ++state->current < fileinfo->count ? 0 : -1;
}
return -1;
}
int I_FindClose(void *const handle)
{
findstate_t *const state = static_cast<findstate_t *>(handle);
if (handle != (void *)-1 && state->count > 0)
{
for (int i = 0; i < state->count; ++i)
{
free(state->namelist[i]);
}
free(state->namelist);
state->namelist = nullptr;
state->count = 0;
}
return 0;
}
int I_FindAttr(findstate_t *const fileinfo)
{
dirent *const ent = fileinfo->namelist[fileinfo->current];
const FString path = fileinfo->path + ent->d_name;
bool isdir;
if (DirEntryExists(path, &isdir))
{
return isdir ? FA_DIREC : 0;
}
return 0;
}
#else
#include <windows.h>
#include <direct.h>
//==========================================================================
//
// I_FindFirst
//
// Start a pattern matching sequence.
//
//==========================================================================
void *I_FindFirst(const char *filespec, findstate_t *fileinfo)
{
static_assert(sizeof(WIN32_FIND_DATAW) == sizeof(fileinfo->FindData), "FindData size mismatch");
auto widespec = WideString(filespec);
fileinfo->UTF8Name = "";
return FindFirstFileW(widespec.c_str(), (LPWIN32_FIND_DATAW)&fileinfo->FindData);
}
//==========================================================================
//
// I_FindNext
//
// Return the next file in a pattern matching sequence.
//
//==========================================================================
int I_FindNext(void *handle, findstate_t *fileinfo)
{
fileinfo->UTF8Name = "";
return !FindNextFileW((HANDLE)handle, (LPWIN32_FIND_DATAW)&fileinfo->FindData);
}
//==========================================================================
//
// I_FindClose
//
// Finish a pattern matching sequence.
//
//==========================================================================
int I_FindClose(void *handle)
{
return FindClose((HANDLE)handle);
}
//==========================================================================
//
// I_FindName
//
// Returns the name for an entry
//
//==========================================================================
const char *I_FindName(findstate_t *fileinfo)
{
if (fileinfo->UTF8Name.IsEmpty()) fileinfo->UTF8Name = fileinfo->FindData.Name;
return fileinfo->UTF8Name.GetChars();
}
#endif
//==========================================================================
//
@ -288,45 +136,20 @@ void D_AddWildFile(TArray<FString>& wadfiles, const char* value, const char *ext
{
D_AddFile(wadfiles, wadfile, true, -1, config);
}
else
{ // Try pattern matching
findstate_t findstate;
char path[ZPATH_MAX];
char* sep;
void* handle = I_FindFirst(value, &findstate);
strcpy(path, value);
sep = strrchr(path, '/');
if (sep == nullptr)
{
sep = strrchr(path, '\\');
#ifdef _WIN32
if (sep == nullptr && path[1] == ':')
else
{
// Try pattern matching
FileList list;
auto path = ExtractFilePath(value);
auto name = ExtractFileBase(value, true);
if (path.IsEmpty()) path = ".";
if (ScanDirectory(list, path, name, true))
{
for(auto& entry : list)
{
sep = path + 1;
D_AddFile(wadfiles, entry.FilePath.c_str(), true, -1, config);
}
#endif
}
if (handle != ((void*)-1))
{
do
{
if (!(I_FindAttr(&findstate) & FA_DIREC))
{
if (sep == nullptr)
{
D_AddFile(wadfiles, I_FindName(&findstate), true, -1, config);
}
else
{
strcpy(sep + 1, I_FindName(&findstate));
D_AddFile(wadfiles, path, true, -1, config);
}
}
} while (I_FindNext(handle, &findstate) == 0);
}
I_FindClose(handle);
}
}
@ -370,40 +193,16 @@ void D_AddConfigFiles(TArray<FString>& wadfiles, const char* section, const char
void D_AddDirectory(TArray<FString>& wadfiles, const char* dir, const char *filespec, FConfigFile* config)
{
FString curdir = I_GetCWD();
if (curdir.IsNotEmpty())
FileList list;
if (ScanDirectory(list, dir, "*.wad", true))
{
char skindir[ZPATH_MAX];
findstate_t findstate;
void* handle;
size_t stuffstart;
stuffstart = strlen(dir);
memcpy(skindir, dir, stuffstart * sizeof(*dir));
skindir[stuffstart] = 0;
if (skindir[stuffstart - 1] == '/')
for (auto& entry : list)
{
skindir[--stuffstart] = 0;
}
if (I_ChDir(skindir))
{
skindir[stuffstart++] = '/';
if ((handle = I_FindFirst(filespec, &findstate)) != (void*)-1)
if (!entry.isDirectory)
{
do
{
if (!(I_FindAttr(&findstate) & FA_DIREC))
{
strcpy(skindir + stuffstart, I_FindName(&findstate));
D_AddFile(wadfiles, skindir, true, -1, config);
}
} while (I_FindNext(handle, &findstate) == 0);
I_FindClose(handle);
D_AddFile(wadfiles, entry.FilePath.c_str(), true, -1, config);
}
}
I_ChDir(curdir);
}
}