1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-15 11:03:00 +01:00

Remove old file enumerator functions from platform

This commit is contained in:
Ted John
2018-01-06 19:09:04 +00:00
committed by Michael Steenbeek
parent cb720025fa
commit bea500638b
3 changed files with 1 additions and 509 deletions

View File

@@ -104,12 +104,6 @@ bool platform_ensure_directory_exists(const utf8 *path);
bool platform_directory_delete(const utf8 *path);
utf8 * platform_get_absolute_path(const utf8 * relative_path, const utf8 * base_path);
bool platform_lock_single_instance();
sint32 platform_enumerate_files_begin(const utf8 *pattern);
bool platform_enumerate_files_next(sint32 handle, file_info *outFileInfo);
void platform_enumerate_files_end(sint32 handle);
sint32 platform_enumerate_directories_begin(const utf8 *directory);
bool platform_enumerate_directories_next(sint32 handle, utf8 *path);
void platform_enumerate_directories_end(sint32 handle);
bool platform_place_string_on_clipboard(utf8* target);
// Returns the bitmask of the GetLogicalDrives function for windows, 0 for other systems

View File

@@ -302,295 +302,7 @@ bool platform_lock_single_instance()
return true;
}
typedef struct enumerate_file_info {
char active;
char pattern[MAX_PATH];
struct dirent **fileListTemp;
char **paths;
sint32 cnt;
sint32 handle;
void* data;
} enumerate_file_info;
static enumerate_file_info _enumerateFileInfoList[8] = { 0 };
static char *_file_pattern;
static sint32 winfilter(const struct dirent *d)
{
sint32 entry_length = strnlen(d->d_name, MAX_PATH);
char *name_upper = malloc(entry_length + 1);
if (name_upper == NULL)
{
log_error("out of memory");
return 0;
}
for (sint32 i = 0; i < entry_length; i++)
{
name_upper[i] = (char)toupper(d->d_name[i]);
}
name_upper[entry_length] = '\0';
bool match = fnmatch(_file_pattern, name_upper, FNM_PATHNAME) == 0;
//log_verbose("trying matching filename %s, result = %d", name_upper, match);
free(name_upper);
return match;
}
sint32 platform_enumerate_files_begin(const utf8 *pattern)
{
char npattern[MAX_PATH];
platform_utf8_to_multibyte(pattern, npattern, MAX_PATH);
enumerate_file_info *enumFileInfo;
log_verbose("begin file search, pattern: %s", npattern);
char *file_name = strrchr(npattern, *PATH_SEPARATOR);
char *dir_name;
if (file_name != NULL)
{
dir_name = strndup(npattern, file_name - npattern);
file_name = &file_name[1];
} else {
file_name = npattern;
dir_name = strdup(".");
}
sint32 pattern_length = strlen(file_name);
_file_pattern = strndup(file_name, pattern_length);
for (sint32 j = 0; j < pattern_length; j++)
{
_file_pattern[j] = (char)toupper(_file_pattern[j]);
}
log_verbose("looking for file matching %s", _file_pattern);
sint32 cnt;
for (sint32 i = 0; i < countof(_enumerateFileInfoList); i++) {
enumFileInfo = &_enumerateFileInfoList[i];
if (!enumFileInfo->active) {
safe_strcpy(enumFileInfo->pattern, npattern, sizeof(enumFileInfo->pattern));
cnt = scandir(dir_name, &enumFileInfo->fileListTemp, winfilter, alphasort);
if (cnt < 0)
{
break;
}
log_verbose("found %d files matching in dir '%s'", cnt, dir_name);
enumFileInfo->cnt = cnt;
enumFileInfo->paths = malloc(cnt * sizeof(char *));
char **paths = enumFileInfo->paths;
// 256 is size of dirent.d_name
const sint32 dir_name_len = strnlen(dir_name, MAX_PATH);
for (sint32 idx = 0; idx < cnt; idx++)
{
struct dirent *d = enumFileInfo->fileListTemp[idx];
const sint32 entry_len = strnlen(d->d_name, MAX_PATH);
// 1 for separator, 1 for trailing null
size_t path_len = sizeof(char) * min(MAX_PATH, entry_len + dir_name_len + 2);
paths[idx] = malloc(path_len);
log_verbose("dir_name: %s", dir_name);
safe_strcpy(paths[idx], dir_name, path_len);
safe_strcat_path(paths[idx], d->d_name, path_len);
log_verbose("paths[%d] = %s", idx, paths[idx]);
// macOS uses decomposed Unicode strings (e.g. an 'e' and a combining accent) in filenames
// This causes problems with the sprite font, as the font only contains precomposed characters
// The block below converts all filename strings to their precomposed form, preventing mojibake
#ifdef __APPLE__
utf8* precomp_path = macos_str_decomp_to_precomp(paths[idx]);
size_t precomp_len = sizeof(utf8) * min(MAX_PATH, strnlen(precomp_path, MAX_PATH) + 2);
paths[idx] = malloc(precomp_len);
safe_strcpy(paths[idx], precomp_path, precomp_len);
log_verbose("macOS decomp-to-precomp fix - paths[%d] = %s", idx, paths[idx]);
#endif
}
enumFileInfo->handle = 0;
enumFileInfo->active = 1;
free(dir_name);
free(_file_pattern);
_file_pattern = NULL;
return i;
}
}
free(dir_name);
free(_file_pattern);
_file_pattern = NULL;
return -1;
}
bool platform_enumerate_files_next(sint32 handle, file_info *outFileInfo)
{
if (handle < 0)
{
return false;
}
enumerate_file_info *enumFileInfo = &_enumerateFileInfoList[handle];
bool result;
if (enumFileInfo->handle < enumFileInfo->cnt) {
result = true;
} else {
result = false;
}
if (result) {
sint32 entryIdx = enumFileInfo->handle++;
struct stat fileInfo;
log_verbose("trying handle %d", entryIdx);
char *fileName = enumFileInfo->paths[entryIdx];
sint32 statRes;
statRes = stat(fileName, &fileInfo);
if (statRes == -1) {
log_error("failed to stat file '%s'! errno = %i", fileName, errno);
return false;
}
outFileInfo->path = basename(fileName);
outFileInfo->size = fileInfo.st_size;
outFileInfo->last_modified = fileInfo.st_mtime;
return true;
} else {
return false;
}
}
void platform_enumerate_files_end(sint32 handle)
{
if (handle < 0)
{
return;
}
enumerate_file_info *enumFileInfo = &_enumerateFileInfoList[handle];
sint32 cnt = enumFileInfo->cnt;
for (sint32 i = 0; i < cnt; i++) {
free(enumFileInfo->fileListTemp[i]);
free(enumFileInfo->paths[i]);
}
free(enumFileInfo->fileListTemp);
free(enumFileInfo->paths);
// FIXME: this here could have a bug
enumFileInfo->fileListTemp = NULL;
enumFileInfo->handle = 0;
enumFileInfo->active = 0;
}
static sint32 dirfilter(const struct dirent *d)
{
if (d->d_name[0] == '.') {
return 0;
}
#if defined(_DIRENT_HAVE_D_TYPE) || defined(DT_UNKNOWN)
if (d->d_type == DT_DIR || d->d_type == DT_LNK)
{
return 1;
} else {
return 0;
}
#else
#error implement dirfilter!
#endif // defined(_DIRENT_HAVE_D_TYPE) || defined(DT_UNKNOWN)
}
sint32 platform_enumerate_directories_begin(const utf8 *directory)
{
char npattern[MAX_PATH];
sint32 length = platform_utf8_to_multibyte(directory, npattern, MAX_PATH) + 1;
enumerate_file_info *enumFileInfo;
log_verbose("begin directory listing, path: %s", npattern);
// TODO: add some checking for stringness and directoryness
sint32 cnt;
for (sint32 i = 0; i < countof(_enumerateFileInfoList); i++) {
enumFileInfo = &_enumerateFileInfoList[i];
if (!enumFileInfo->active) {
safe_strcpy(enumFileInfo->pattern, npattern, length);
cnt = scandir(npattern, &enumFileInfo->fileListTemp, dirfilter, alphasort);
if (cnt < 0)
{
break;
}
log_verbose("found %d files in dir '%s'", cnt, npattern);
enumFileInfo->cnt = cnt;
enumFileInfo->paths = malloc(cnt * sizeof(char *));
char **paths = enumFileInfo->paths;
// 256 is size of dirent.d_name
const sint32 dir_name_len = strnlen(npattern, MAX_PATH);
for (sint32 idx = 0; idx < cnt; idx++)
{
struct dirent *d = enumFileInfo->fileListTemp[idx];
const sint32 entry_len = strnlen(d->d_name, MAX_PATH);
// 1 for separator, 1 for trailing null
size_t path_len = sizeof(char) * min(MAX_PATH, entry_len + dir_name_len + 2);
paths[idx] = malloc(path_len);
log_verbose("dir_name: %s", npattern);
safe_strcpy(paths[idx], npattern, path_len);
safe_strcat_path(paths[idx], d->d_name, path_len);
log_verbose("paths[%d] = %s", idx, paths[idx]);
}
enumFileInfo->handle = 0;
enumFileInfo->active = 1;
return i;
}
}
return -1;
}
bool platform_enumerate_directories_next(sint32 handle, utf8 *path)
{
if (handle < 0)
{
return false;
}
bool result;
enumerate_file_info *enumFileInfo = &_enumerateFileInfoList[handle];
log_verbose("handle = %d", handle);
if (enumFileInfo->handle < enumFileInfo->cnt) {
result = true;
} else {
result = false;
}
if (result) {
sint32 entryIdx = enumFileInfo->handle++;
struct stat fileInfo;
char *fileName = enumFileInfo->paths[entryIdx];
sint32 statRes;
statRes = stat(fileName, &fileInfo);
if (statRes == -1) {
log_error("failed to stat file '%s'! errno = %i", fileName, errno);
return false;
}
// so very, very wrong
safe_strcpy(path, basename(fileName), MAX_PATH);
path_end_with_separator(path, MAX_PATH);
return true;
} else {
return false;
}
}
void platform_enumerate_directories_end(sint32 handle)
{
if (handle < 0)
{
return;
}
enumerate_file_info *enumFileInfo = &_enumerateFileInfoList[handle];
sint32 cnt = enumFileInfo->cnt;
for (sint32 i = 0; i < cnt; i++) {
free(enumFileInfo->fileListTemp[i]);
free(enumFileInfo->paths[i]);
}
free(enumFileInfo->fileListTemp);
free(enumFileInfo->paths);
// FIXME: this here could have a bug
enumFileInfo->fileListTemp = NULL;
enumFileInfo->handle = 0;
enumFileInfo->active = 0;
}
sint32 platform_get_drives(){
sint32 platform_get_drives() {
// POSIX systems do not know drives. Return 0.
return 0;
}

View File

@@ -167,220 +167,6 @@ bool platform_lock_single_instance()
}
}
typedef struct {
bool active;
wchar_t pattern[MAX_PATH];
HANDLE handle;
WIN32_FIND_DATAW data;
utf8 *outFilename;
} enumerate_file_info;
static enumerate_file_info _enumerateFileInfoList[8] = { 0 };
sint32 platform_enumerate_files_begin(const utf8 *pattern)
{
sint32 i;
enumerate_file_info *enumFileInfo;
wchar_t *wPattern = utf8_to_widechar(pattern);
for (i = 0; i < countof(_enumerateFileInfoList); i++) {
enumFileInfo = &_enumerateFileInfoList[i];
if (!enumFileInfo->active) {
wcsncpy(enumFileInfo->pattern, wPattern, MAX_PATH);
enumFileInfo->handle = NULL;
enumFileInfo->active = true;
enumFileInfo->outFilename = NULL;
free(wPattern);
return i;
}
}
free(wPattern);
return INVALID_HANDLE;
}
/**
* Due to FindFirstFile / FindNextFile searching for DOS names as well, *.doc also matches *.docx which isn't what the pattern
* specified. This will verify if a filename does indeed match the pattern we asked for.
* @remarks Based on algorithm (http://xoomer.virgilio.it/acantato/dev/wildcard/wildmatch.html)
*/
static bool match_wildcard(const wchar_t *fileName, const wchar_t *pattern)
{
while (*fileName != '\0') {
switch (*pattern) {
case '?':
if (*fileName == '.') {
return false;
}
break;
case '*':
do {
pattern++;
} while (*pattern == '*');
if (*pattern == '\0') {
return false;
}
while (*fileName != '\0') {
if (match_wildcard(fileName++, pattern)) {
return true;
}
}
return false;
default:
if (toupper(*fileName) != toupper(*pattern)) {
return false;
}
break;
}
pattern++;
fileName++;
}
while (*pattern == '*') {
++fileName;
}
return *pattern == '\0';
}
bool platform_enumerate_files_next(sint32 handle, file_info *outFileInfo)
{
bool result;
enumerate_file_info *enumFileInfo;
HANDLE findFileHandle;
enumFileInfo = &_enumerateFileInfoList[handle];
// Get pattern (just filename part)
const wchar_t *patternWithoutDirectory = wcsrchr(enumFileInfo->pattern, '\\');
if (patternWithoutDirectory == NULL) {
patternWithoutDirectory = enumFileInfo->pattern;
} else {
patternWithoutDirectory++;
}
do {
if (enumFileInfo->handle == NULL) {
findFileHandle = FindFirstFileW(enumFileInfo->pattern, &enumFileInfo->data);
if (findFileHandle != INVALID_HANDLE_VALUE) {
enumFileInfo->handle = findFileHandle;
result = true;
} else {
result = false;
}
} else {
result = FindNextFileW(enumFileInfo->handle, &enumFileInfo->data);
}
} while (result && !match_wildcard(enumFileInfo->data.cFileName, patternWithoutDirectory));
if (result) {
outFileInfo->path = enumFileInfo->outFilename = widechar_to_utf8(enumFileInfo->data.cFileName);
outFileInfo->size = ((uint64)enumFileInfo->data.nFileSizeHigh << 32ULL) | (uint64)enumFileInfo->data.nFileSizeLow;
outFileInfo->last_modified = ((uint64)enumFileInfo->data.ftLastWriteTime.dwHighDateTime << 32ULL) | (uint64)enumFileInfo->data.ftLastWriteTime.dwLowDateTime;
return true;
} else {
return false;
}
}
void platform_enumerate_files_end(sint32 handle)
{
enumerate_file_info *enumFileInfo;
enumFileInfo = &_enumerateFileInfoList[handle];
if (enumFileInfo->handle != NULL) {
FindClose(enumFileInfo->handle);
enumFileInfo->handle = NULL;
}
enumFileInfo->active = false;
SafeFree(enumFileInfo->outFilename);
}
sint32 platform_enumerate_directories_begin(const utf8 *directory)
{
sint32 i;
enumerate_file_info *enumFileInfo;
wchar_t *wDirectory = utf8_to_widechar(directory);
if (wcslen(wDirectory) + 3 >= MAX_PATH) {
free(wDirectory);
return INVALID_HANDLE;
}
for (i = 0; i < countof(_enumerateFileInfoList); i++) {
enumFileInfo = &_enumerateFileInfoList[i];
if (!enumFileInfo->active) {
wcsncpy(enumFileInfo->pattern, wDirectory, MAX_PATH);
// Ensure pattern ends with a slash
sint32 patternLength = lstrlenW(enumFileInfo->pattern);
wchar_t lastChar = enumFileInfo->pattern[patternLength - 1];
if (lastChar != '\\' && lastChar != '/') {
wcsncat(enumFileInfo->pattern, L"\\", MAX_PATH);
}
wcsncat(enumFileInfo->pattern, L"*", MAX_PATH);
enumFileInfo->handle = NULL;
enumFileInfo->active = true;
enumFileInfo->outFilename = NULL;
free(wDirectory);
return i;
}
}
free(wDirectory);
return INVALID_HANDLE;
}
bool platform_enumerate_directories_next(sint32 handle, utf8 *path)
{
enumerate_file_info *enumFileInfo;
HANDLE fileHandle;
enumFileInfo = &_enumerateFileInfoList[handle];
if (enumFileInfo->handle == NULL) {
fileHandle = FindFirstFileW(enumFileInfo->pattern, &enumFileInfo->data);
if (fileHandle != INVALID_HANDLE_VALUE) {
enumFileInfo->handle = fileHandle;
} else {
return false;
}
} else {
if (!FindNextFileW(enumFileInfo->handle, &enumFileInfo->data)) {
return false;
}
}
while (
(enumFileInfo->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0 ||
wcschr(enumFileInfo->data.cFileName, '.') != NULL
) {
if (!FindNextFileW(enumFileInfo->handle, &enumFileInfo->data)) {
return false;
}
}
utf8 *filename = widechar_to_utf8(enumFileInfo->data.cFileName);
safe_strcpy(path, filename, MAX_PATH);
path_end_with_separator(path, MAX_PATH);
free(filename);
return true;
}
void platform_enumerate_directories_end(sint32 handle)
{
enumerate_file_info *enumFileInfo;
enumFileInfo = &_enumerateFileInfoList[handle];
if (enumFileInfo->handle != NULL) {
FindClose(enumFileInfo->handle);
enumFileInfo->handle = NULL;
}
enumFileInfo->active = false;
}
sint32 platform_get_drives()
{
return GetLogicalDrives();