This commit is contained in:
libretroadmin 2023-11-01 19:10:49 +01:00
parent 01c6122931
commit fce57fdfb7
5 changed files with 178 additions and 133 deletions

View file

@ -291,6 +291,7 @@ enum retro_language
RETRO_LANGUAGE_CATALAN = 29,
RETRO_LANGUAGE_BRITISH_ENGLISH = 30,
RETRO_LANGUAGE_HUNGARIAN = 31,
RETRO_LANGUAGE_BELARUSIAN = 32,
RETRO_LANGUAGE_LAST,
/* Ensure sizeof(enum) == sizeof(int) */

View file

@ -85,6 +85,15 @@ bool dir_list_initialize(struct string_list *list,
**/
void dir_list_sort(struct string_list *list, bool dir_first);
/**
* dir_list_sort_ignore_ext:
* @list : pointer to the directory listing.
* @dir_first : move the directories in the listing to the top?
*
* Sorts a directory listing. File extensions are ignored.
**/
void dir_list_sort_ignore_ext(struct string_list *list, bool dir_first);
/**
* dir_list_free:
* @list : pointer to the directory listing

View file

@ -46,6 +46,22 @@ static int qstrcmp_plain(const void *a_, const void *b_)
return strcasecmp(a->data, b->data);
}
static int qstrcmp_plain_noext(const void *a_, const void *b_)
{
const struct string_list_elem *a = (const struct string_list_elem*)a_;
const struct string_list_elem *b = (const struct string_list_elem*)b_;
const char *ext_a = path_get_extension(a->data);
size_t l_a = string_is_empty(ext_a) ? strlen(a->data) : (ext_a - a->data - 1);
const char *ext_b = path_get_extension(b->data);
size_t l_b = string_is_empty(ext_b) ? strlen(b->data) : (ext_b - b->data - 1);
int rv = strncasecmp(a->data, b->data, MIN(l_a, l_b));
if (rv == 0 && l_a != l_b)
return (int)(l_a - l_b);
return rv;
}
static int qstrcmp_dir(const void *a_, const void *b_)
{
const struct string_list_elem *a = (const struct string_list_elem*)a_;
@ -59,6 +75,19 @@ static int qstrcmp_dir(const void *a_, const void *b_)
return strcasecmp(a->data, b->data);
}
static int qstrcmp_dir_noext(const void *a_, const void *b_)
{
const struct string_list_elem *a = (const struct string_list_elem*)a_;
const struct string_list_elem *b = (const struct string_list_elem*)b_;
int a_type = a->attr.i;
int b_type = b->attr.i;
/* Sort directories before files. */
if (a_type != b_type)
return b_type - a_type;
return qstrcmp_plain_noext(a, b);
}
/**
* dir_list_sort:
* @list : pointer to the directory listing.
@ -73,6 +102,20 @@ void dir_list_sort(struct string_list *list, bool dir_first)
dir_first ? qstrcmp_dir : qstrcmp_plain);
}
/**
* dir_list_sort_ignore_ext:
* @list : pointer to the directory listing.
* @dir_first : move the directories in the listing to the top?
*
* Sorts a directory listing. File extensions are ignored.
**/
void dir_list_sort_ignore_ext(struct string_list *list, bool dir_first)
{
if (list)
qsort(list->elems, list->size, sizeof(struct string_list_elem),
dir_first ? qstrcmp_dir_noext : qstrcmp_plain_noext);
}
/**
* dir_list_free:
* @list : pointer to the directory listing
@ -141,6 +184,11 @@ static int dir_list_read(const char *dir,
if (retro_dirent_is_dir(entry, NULL))
{
/* Exclude this frequent hidden dir on platforms which can not handle hidden attribute */
#ifndef _WIN32
if (!include_hidden && strcmp(name, "System Volume Information") == 0)
continue;
#endif
if (recursive)
dir_list_read(file_path, list, ext_list, include_dirs,
include_hidden, include_compressed, recursive);

View file

@ -258,7 +258,7 @@ void tpool_wait(tpool_t *tp)
/* working_cond is dual use. It signals when we're not stopping but the
* working_cnt is 0 indicating there isn't any work processing. If we
* are stopping it will trigger when there aren't any threads running. */
if ((!tp->stop && (tp->working_cnt != 0 || tm->work_first != NULL)) || (tp->stop && tp->thread_cnt != 0))
if ((!tp->stop && tp->working_cnt != 0) || (tp->stop && tp->thread_cnt != 0))
scond_wait(tp->working_cond, tp->work_mutex);
else
break;

View file

@ -301,7 +301,7 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(
{
int flags = 0;
const char *mode_str = NULL;
libretro_vfs_implementation_file *stream =
libretro_vfs_implementation_file *stream =
(libretro_vfs_implementation_file*)
malloc(sizeof(*stream));
@ -452,14 +452,14 @@ libretro_vfs_implementation_file *retro_vfs_file_open_impl(
*
* https://www.freebsd.org/cgi/man.cgi?query=setvbuf&apropos=0&sektion=0&manpath=FreeBSD+11.1-RELEASE&arch=default&format=html
*
* If the size argument is not zero but buf is NULL,
* If the size argument is not zero but buf is NULL,
* a buffer of the given size will be allocated immediately, and
* released on close. This is an extension to ANSI C.
*
* Since C89 does not support specifying a NULL buffer
* Since C89 does not support specifying a NULL buffer
* with a non-zero size, we create and track our own buffer for it.
*/
/* TODO: this is only useful for a few platforms,
/* TODO: this is only useful for a few platforms,
* find which and add ifdef */
#if defined(_3DS)
if (stream->scheme != VFS_SCHEME_CDROM)
@ -648,7 +648,7 @@ int64_t retro_vfs_file_tell_impl(libretro_vfs_implementation_file *stream)
#ifdef HAVE_MMAP
/* Need to check stream->mapped because this function
* is called in filestream_open() */
if (stream->mapped && stream->hints &
if (stream->mapped && stream->hints &
RETRO_VFS_FILE_ACCESS_HINT_FREQUENT_ACCESS)
return stream->mappos;
#endif
@ -738,39 +738,40 @@ int retro_vfs_file_flush_impl(libretro_vfs_implementation_file *stream)
int retro_vfs_file_remove_impl(const char *path)
{
if (path && *path)
{
int ret = -1;
#if defined(_WIN32) && !defined(_XBOX)
/* Win32 (no Xbox) */
/* Win32 (no Xbox) */
#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0500
char *path_local = NULL;
char *path_local = NULL;
if ((path_local = utf8_to_local_string_alloc(path)))
{
/* We need to check if path is a directory */
if ((retro_vfs_stat_impl(path, NULL) & RETRO_VFS_STAT_IS_DIRECTORY) != 0)
ret = _rmdir(path_local);
else
ret = remove(path_local);
free(path_local);
}
#else
wchar_t *path_wide = NULL;
wchar_t *path_wide = NULL;
if ((path_wide = utf8_to_utf16_string_alloc(path)))
{
/* We need to check if path is a directory */
if ((retro_vfs_stat_impl(path, NULL) & RETRO_VFS_STAT_IS_DIRECTORY) != 0)
ret = _wrmdir(path_wide);
else
ret = _wremove(path_wide);
free(path_wide);
}
#endif
#else
ret = remove(path);
#endif
if (!path || !*path)
return -1;
#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0500
if ((path_local = utf8_to_local_string_alloc(path)))
{
int ret = remove(path_local);
free(path_local);
if (ret == 0)
return 0;
}
#else
if ((path_wide = utf8_to_utf16_string_alloc(path)))
{
int ret = _wremove(path_wide);
free(path_wide);
if (ret == 0)
return 0;
}
#endif
#else
if (remove(path) == 0)
return 0;
#endif
return -1;
}
@ -842,132 +843,118 @@ const char *retro_vfs_file_get_path_impl(
int retro_vfs_stat_impl(const char *path, int32_t *size)
{
bool is_dir = false;
bool is_character_special = false;
int ret = RETRO_VFS_STAT_IS_VALID;
if (!path || !*path)
return 0;
{
#if defined(VITA)
/* Vita / PSP */
SceIoStat buf;
int dir_ret;
char *tmp = NULL;
size_t len = 0;
/* Vita / PSP */
SceIoStat stat_buf;
int dir_ret;
char *tmp = strdup(path);
size_t len = strlen(tmp);
if (tmp[len-1] == '/')
tmp[len-1] = '\0';
if (!path || !*path)
return 0;
dir_ret = sceIoGetstat(tmp, &stat_buf);
free(tmp);
if (dir_ret < 0)
return 0;
tmp = strdup(path);
len = strlen(tmp);
if (tmp[len-1] == '/')
tmp[len-1] = '\0';
if (size)
*size = (int32_t)stat_buf.st_size;
dir_ret = sceIoGetstat(tmp, &buf);
free(tmp);
if (dir_ret < 0)
return 0;
if (size)
*size = (int32_t)buf.st_size;
is_dir = FIO_S_ISDIR(buf.st_mode);
if (FIO_S_ISDIR(stat_buf.st_mode))
ret |= RETRO_VFS_STAT_IS_DIRECTORY;
#elif defined(__PSL1GHT__) || defined(__PS3__)
/* Lowlevel Lv2 */
sysFSStat buf;
/* Lowlevel Lv2 */
sysFSStat stat_buf;
if (!path || !*path)
return 0;
if (sysFsStat(path, &buf) < 0)
return 0;
if (sysFsStat(path, &stat_buf) < 0)
return 0;
if (size)
*size = (int32_t)buf.st_size;
if (size)
*size = (int32_t)stat_buf.st_size;
is_dir = ((buf.st_mode & S_IFMT) == S_IFDIR);
if ((stat_buf.st_mode & S_IFMT) == S_IFDIR)
ret |= RETRO_VFS_STAT_IS_DIRECTORY;
#elif defined(_WIN32)
/* Windows */
DWORD file_info;
struct _stat buf;
/* Windows */
struct _stat stat_buf;
#if defined(LEGACY_WIN32)
char *path_local = NULL;
char *path_local = utf8_to_local_string_alloc(path);
DWORD file_info = GetFileAttributes(path_local);
if (!string_is_empty(path_local))
_stat(path_local, &stat_buf);
if (path_local)
free(path_local);
#else
wchar_t *path_wide = NULL;
wchar_t *path_wide = utf8_to_utf16_string_alloc(path);
DWORD file_info = GetFileAttributesW(path_wide);
_wstat(path_wide, &stat_buf);
if (path_wide)
free(path_wide);
#endif
if (file_info == INVALID_FILE_ATTRIBUTES)
return 0;
if (!path || !*path)
return 0;
#if defined(LEGACY_WIN32)
path_local = utf8_to_local_string_alloc(path);
file_info = GetFileAttributes(path_local);
if (!string_is_empty(path_local))
_stat(path_local, &buf);
if (path_local)
free(path_local);
#else
path_wide = utf8_to_utf16_string_alloc(path);
file_info = GetFileAttributesW(path_wide);
_wstat(path_wide, &buf);
if (path_wide)
free(path_wide);
#endif
if (file_info == INVALID_FILE_ATTRIBUTES)
return 0;
if (size)
*size = (int32_t)buf.st_size;
is_dir = (file_info & FILE_ATTRIBUTE_DIRECTORY);
if (size)
*size = (int32_t)stat_buf.st_size;
if (file_info & FILE_ATTRIBUTE_DIRECTORY)
ret |= RETRO_VFS_STAT_IS_DIRECTORY;
#elif defined(GEKKO)
/* On GEKKO platforms, paths cannot have
* trailing slashes - we must therefore
* remove them */
char *path_buf = NULL;
int stat_ret = -1;
struct stat stat_buf;
size_t len;
/* On GEKKO platforms, paths cannot have
* trailing slashes - we must therefore
* remove them */
size_t len;
char *path_buf = NULL;
struct stat stat_buf;
if (string_is_empty(path))
return 0;
if (!(path_buf = strdup(path)))
return 0;
if (!(path_buf = strdup(path)))
return 0;
if ((len = strlen(path_buf)) > 0)
if (path_buf[len - 1] == '/')
path_buf[len - 1] = '\0';
if ((len = strlen(path_buf)) > 0)
if (path_buf[len - 1] == '/')
path_buf[len - 1] = '\0';
if (stat(path_buf, &stat_buf) < 0)
{
free(path_buf);
return 0;
}
stat_ret = stat(path_buf, &stat_buf);
free(path_buf);
if (stat_ret < 0)
return 0;
if (size)
*size = (int32_t)stat_buf.st_size;
is_dir = S_ISDIR(stat_buf.st_mode);
is_character_special = S_ISCHR(stat_buf.st_mode);
free(path_buf);
if (size)
*size = (int32_t)stat_buf.st_size;
if (S_ISDIR(stat_buf.st_mode))
ret |= RETRO_VFS_STAT_IS_DIRECTORY;
if (S_ISCHR(stat_buf.st_mode))
ret |= RETRO_VFS_STAT_IS_CHARACTER_SPECIAL;
#else
/* Every other platform */
struct stat buf;
/* Every other platform */
struct stat stat_buf;
if (!path || !*path)
return 0;
if (stat(path, &buf) < 0)
return 0;
if (stat(path, &stat_buf) < 0)
return 0;
if (size)
*size = (int32_t)buf.st_size;
if (size)
*size = (int32_t)stat_buf.st_size;
is_dir = S_ISDIR(buf.st_mode);
is_character_special = S_ISCHR(buf.st_mode);
if (S_ISDIR(stat_buf.st_mode))
ret |= RETRO_VFS_STAT_IS_DIRECTORY;
if (S_ISCHR(stat_buf.st_mode))
ret |= RETRO_VFS_STAT_IS_CHARACTER_SPECIAL;
#endif
return RETRO_VFS_STAT_IS_VALID | (is_dir ? RETRO_VFS_STAT_IS_DIRECTORY : 0) | (is_character_special ? RETRO_VFS_STAT_IS_CHARACTER_SPECIAL : 0);
}
return ret;
}
#if defined(VITA)