Revert "Update VFS implementation to current libretro-common (#354)" (#356)

This reverts commit 89d2c907eb.
This commit is contained in:
LibretroAdmin 2024-06-28 20:35:26 -05:00 committed by GitHub
parent 6c72b774cc
commit 5355eae2e1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
61 changed files with 2838 additions and 5624 deletions

View File

@ -840,6 +840,12 @@ LIBRETRO_CFLAGS += $(BPP_DEFINES) \
-DHAVE_OPLL_CORE \
-DMAXROMSIZE=$(MAX_ROM_SIZE)
ifneq (,$(findstring msvc,$(platform)))
LIBRETRO_CFLAGS += -DINLINE="static _inline"
else
LIBRETRO_CFLAGS += -DINLINE="static inline"
endif
OBJOUT = -o
LINKOUT = -o

View File

@ -42,12 +42,8 @@
* If you define INLINE in makefile or osd.h, it will override this value.
* NOTE: not enabling inline functions will SEVERELY slow down emulation.
*/
#ifndef INLINE
#if defined(_MSC_VER)
#define INLINE static _inline
#else
#define INLINE static __inline__
#endif
#ifndef INLINE
#define INLINE static __inline__
#endif /* INLINE */
/* Alignment macros for cross compiler compatibility */

View File

@ -72,8 +72,7 @@ endif
ifeq ($(HAVE_CDROM), 1)
SOURCES_C += \
$(LIBRETRO_COMM_DIR)/cdrom/cdrom.c \
$(LIBRETRO_COMM_DIR)/vfs/vfs_implementation_cdrom.c \
$(LIBRETRO_COMM_DIR)/time/rtime.c
$(LIBRETRO_COMM_DIR)/vfs/vfs_implementation_cdrom.c
endif
SOURCES_C += \
$(LIBRETRO_DEPS_DIR)/zlib-1.2.11/adler32.c \

View File

@ -16,14 +16,6 @@
#include <stdint.h>
#include <libchdr/chdconfig.h>
#ifndef INLINE
#if defined(_MSC_VER)
#define INLINE static _inline
#else
#define INLINE static __inline__
#endif
#endif /* INLINE */
/***************************************************************************
CONSTANTS
***************************************************************************/

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2019 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (cdrom.c).
@ -29,7 +29,6 @@
#include <stdio.h>
#include <string.h>
#include <compat/strl.h>
#include <compat/strcasestr.h>
#include <retro_math.h>
#include <retro_timers.h>
#include <streams/file_stream.h>
@ -97,7 +96,6 @@ void increment_msf(unsigned char *min, unsigned char *sec, unsigned char *frame)
*frame = (*frame < 74) ? (*frame + 1) : 0;
}
#ifdef CDROM_DEBUG
static void cdrom_print_sense_data(const unsigned char *sense, size_t len)
{
unsigned i;
@ -177,7 +175,7 @@ static void cdrom_print_sense_data(const unsigned char *sense, size_t len)
break;
}
printf("[CDROM] Sense Key: %02X (%s)\n", key, sense_key_text ? sense_key_text : "null");
printf("[CDROM] Sense Key: %02X (%s)\n", key, sense_key_text);
printf("[CDROM] ASC: %02X\n", asc);
printf("[CDROM] ASCQ: %02X\n", ascq);
@ -254,7 +252,6 @@ static void cdrom_print_sense_data(const unsigned char *sense, size_t len)
fflush(stdout);
}
#endif
#if defined(_WIN32) && !defined(_XBOX)
static int cdrom_send_command_win32(const libretro_vfs_implementation_file *stream, CDROM_CMD_Direction dir, void *buf, size_t len, unsigned char *cmd, size_t cmd_len, unsigned char *sense, size_t sense_len)
@ -522,9 +519,7 @@ retry:
}
else
{
#ifdef CDROM_DEBUG
cdrom_print_sense_data(sense, sizeof(sense));
#endif
/* INQUIRY/TEST/SENSE should never fail, don't retry. */
/* READ ATIP seems to fail outright on some drives with pressed discs, skip retries. */
@ -677,9 +672,7 @@ int cdrom_get_sense(libretro_vfs_implementation_file *stream, unsigned char *sen
if (rv)
return 1;
#ifdef CDROM_DEBUG
cdrom_print_sense_data(buf, sizeof(buf));
#endif
return 0;
}
@ -938,23 +931,23 @@ int cdrom_read_subq(libretro_vfs_implementation_file *stream, unsigned char *buf
if (/*(control == 4 || control == 6) && */adr == 1 && tno == 0 && point >= 1 && point <= 99)
{
printf("[CDROM] - Session#: %d TNO %d POINT %d ", session_num, tno, point);
printf("Track start time: (aMSF %02u:%02u:%02u) ", (unsigned)pmin, (unsigned)psec, (unsigned)pframe);
printf("[CDROM] Track start time: (MSF %02u:%02u:%02u) ", (unsigned)pmin, (unsigned)psec, (unsigned)pframe);
}
else if (/*(control == 4 || control == 6) && */adr == 1 && tno == 0 && point == 0xA0)
{
printf("[CDROM] - Session#: %d TNO %d POINT %d ", session_num, tno, point);
printf("First Track Number: %d ", pmin);
printf("Disc Type: %d ", psec);
printf("[CDROM] First Track Number: %d ", pmin);
printf("[CDROM] Disc Type: %d ", psec);
}
else if (/*(control == 4 || control == 6) && */adr == 1 && tno == 0 && point == 0xA1)
{
printf("[CDROM] - Session#: %d TNO %d POINT %d ", session_num, tno, point);
printf("Last Track Number: %d ", pmin);
printf("[CDROM] Last Track Number: %d ", pmin);
}
else if (/*(control == 4 || control == 6) && */adr == 1 && tno == 0 && point == 0xA2)
{
printf("[CDROM] - Session#: %d TNO %d POINT %d ", session_num, tno, point);
printf("Lead-out start time: (aMSF %02u:%02u:%02u) ", (unsigned)pmin, (unsigned)psec, (unsigned)pframe);
printf("[CDROM] Lead-out runtime: (MSF %02u:%02u:%02u) ", (unsigned)pmin, (unsigned)psec, (unsigned)pframe);
}
printf("\n");
@ -999,10 +992,10 @@ static int cdrom_read_track_info(libretro_vfs_implementation_file *stream, unsig
#ifdef CDROM_DEBUG
printf("[CDROM] Track %d Info: ", track);
printf("Copy: %d ", (buf[5] & 0x10) > 0);
printf("Data Mode: %d ", toc->track[track - 1].mode);
printf("LBA Start: %d (%d) ", lba, toc->track[track - 1].lba);
printf("Track Size: %d\n", track_size);
printf("[CDROM] Copy: %d ", (buf[5] & 0x10) > 0);
printf("[CDROM] Data Mode: %d ", toc->track[track - 1].mode);
printf("[CDROM] LBA Start: %d (%d) ", lba, toc->track[track - 1].lba);
printf("[CDROM] Track Size: %d\n", track_size);
fflush(stdout);
#endif
@ -1012,7 +1005,7 @@ static int cdrom_read_track_info(libretro_vfs_implementation_file *stream, unsig
int cdrom_set_read_speed(libretro_vfs_implementation_file *stream, unsigned speed)
{
/* MMC Command: SET CD SPEED */
unsigned char cmd[] = {0xBB, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char cmd[] = {0xBB, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
cmd[2] = (speed >> 24) & 0xFF;
cmd[3] = (speed >> 16) & 0xFF;
@ -1336,35 +1329,24 @@ struct string_list* cdrom_get_available_drives(void)
#if defined(__linux__) && !defined(ANDROID)
struct string_list *dir_list = dir_list_new("/dev", NULL, false, false, false, false);
int i;
bool found = false;
if (!dir_list)
return list;
for (i = 0; i < (int)dir_list->size; i++)
{
if (string_starts_with_size(dir_list->elems[i].data, "/dev/sg",
STRLEN_CONST("/dev/sg")))
if (strstr(dir_list->elems[i].data, "/dev/sg"))
{
char drive_string[33];
libretro_vfs_implementation_file *stream;
char drive_model[32] = {0};
char drive_model[32] = {0};
char drive_string[33] = {0};
union string_list_elem_attr attr = {0};
int dev_index = 0;
RFILE *file = filestream_open(
dir_list->elems[i].data, RETRO_VFS_FILE_ACCESS_READ, 0);
bool is_cdrom = false;
found = true;
int dev_index = 0;
RFILE *file = filestream_open(dir_list->elems[i].data, RETRO_VFS_FILE_ACCESS_READ, 0);
libretro_vfs_implementation_file *stream;
bool is_cdrom = false;
if (!file)
{
#ifdef CDROM_DEBUG
printf("[CDROM] Could not open %s, please check permissions.\n", dir_list->elems[i].data);
fflush(stdout);
#endif
continue;
}
stream = filestream_get_vfs_handle(file);
cdrom_get_inquiry(stream, drive_model, sizeof(drive_model), &is_cdrom);
@ -1373,86 +1355,33 @@ struct string_list* cdrom_get_available_drives(void)
if (!is_cdrom)
continue;
sscanf(dir_list->elems[i].data + STRLEN_CONST("/dev/sg"),
"%d", &dev_index);
sscanf(dir_list->elems[i].data + strlen("/dev/sg"), "%d", &dev_index);
dev_index = '0' + dev_index;
attr.i = dev_index;
attr.i = dev_index;
if (!string_is_empty(drive_model))
strlcpy(drive_string, drive_model, sizeof(drive_string));
strlcat(drive_string, drive_model, sizeof(drive_string));
else
strlcpy(drive_string, "Unknown Drive", sizeof(drive_string));
strlcat(drive_string, "Unknown Drive", sizeof(drive_string));
string_list_append(list, drive_string, attr);
}
}
if (!found)
{
char *buf = NULL;
int64_t len = 0;
if (filestream_read_file("/proc/modules", (void**)&buf, &len))
{
#ifdef CDROM_DEBUG
bool found = false;
#endif
struct string_list mods = {0};
string_list_initialize(&mods);
if (string_split_noalloc(&mods, buf, "\n"))
{
for (i = 0; i < (int)mods.size; i++)
{
if (strcasestr(mods.elems[i].data, "sg "))
{
#ifdef CDROM_DEBUG
found = true;
#endif
break;
}
}
}
string_list_deinitialize(&mods);
free(buf);
#ifdef CDROM_DEBUG
if (found)
{
printf("[CDROM] No sg devices found but kernel module is loaded.\n");
fflush(stdout);
}
else
{
printf("[CDROM] No sg devices found and sg kernel module is not loaded.\n");
fflush(stdout);
}
#endif
}
#ifdef CDROM_DEBUG
else
{
printf("[CDROM] No sg devices found, could not check if sg kernel module is loaded.\n");
fflush(stdout);
}
#endif
}
string_list_free(dir_list);
#endif
#if defined(_WIN32) && !defined(_XBOX)
DWORD drive_mask = GetLogicalDrives();
int i;
for (i = 0; i < (int)(sizeof(DWORD) * 8); i++)
for (i = 0; i < sizeof(DWORD) * 8; i++)
{
char path[] = {"a:\\"};
char path[] = {"a:\\"};
char cdrom_path[] = {"cdrom://a:/drive-track01.bin"};
path[0] += i;
cdrom_path[8] += i;
path[0] += i;
cdrom_path[8] += i;
/* this drive letter doesn't exist */
if (!(drive_mask & (1 << i)))
@ -1460,14 +1389,15 @@ struct string_list* cdrom_get_available_drives(void)
if (GetDriveType(path) != DRIVE_CDROM)
continue;
else
{
char drive_string[33];
libretro_vfs_implementation_file *stream;
bool is_cdrom = false;
char drive_model[32] = {0};
char drive_model[32] = {0};
char drive_string[33] = {0};
union string_list_elem_attr attr = {0};
RFILE *file = filestream_open(cdrom_path, RETRO_VFS_FILE_ACCESS_READ, 0);
libretro_vfs_implementation_file *stream;
bool is_cdrom = false;
if (!file)
continue;
@ -1481,9 +1411,9 @@ struct string_list* cdrom_get_available_drives(void)
attr.i = path[0];
if (!string_is_empty(drive_model))
strlcpy(drive_string, drive_model, sizeof(drive_string));
strlcat(drive_string, drive_model, sizeof(drive_string));
else
strlcpy(drive_string, "Unknown Drive", sizeof(drive_string));
strlcat(drive_string, "Unknown Drive", sizeof(drive_string));
string_list_append(list, drive_string, attr);
}
@ -1514,7 +1444,9 @@ bool cdrom_is_media_inserted(libretro_vfs_implementation_file *stream)
bool cdrom_drive_has_media(const char drive)
{
RFILE *file;
char cdrom_path_bin[256] = {0};
char cdrom_path_bin[256];
cdrom_path_bin[0] = '\0';
cdrom_device_fillpath(cdrom_path_bin, sizeof(cdrom_path_bin), drive, 1, false);
@ -1523,7 +1455,9 @@ bool cdrom_drive_has_media(const char drive)
if (file)
{
libretro_vfs_implementation_file *stream = filestream_get_vfs_handle(file);
bool has_media = cdrom_is_media_inserted(stream);
bool has_media = false;
has_media = cdrom_is_media_inserted(stream);
filestream_close(file);
@ -1535,14 +1469,14 @@ bool cdrom_drive_has_media(const char drive)
bool cdrom_set_read_cache(libretro_vfs_implementation_file *stream, bool enabled)
{
int i;
/* MMC Command: MODE SENSE (10) and MODE SELECT (10) */
unsigned char cdb_sense_changeable[] = {0x5A, 0, 0x48, 0, 0, 0, 0, 0, 0x14, 0};
unsigned char cdb_sense[] = {0x5A, 0, 0x8, 0, 0, 0, 0, 0, 0x14, 0};
unsigned char cdb_select[] = {0x55, 0x10, 0, 0, 0, 0, 0, 0, 0x14, 0};
unsigned char buf[20] = {0};
int rv = cdrom_send_command(stream, DIRECTION_IN, buf, sizeof(buf),
cdb_sense_changeable, sizeof(cdb_sense_changeable), 0);
unsigned char cdb_sense[] = {0x5A, 0, 0x8, 0, 0, 0, 0, 0, 0x14, 0};
unsigned char cdb_select[] = {0x55, 0x10, 0, 0, 0, 0, 0, 0, 0x14, 0};
unsigned char buf[20] = {0};
int rv, i;
rv = cdrom_send_command(stream, DIRECTION_IN, buf, sizeof(buf), cdb_sense_changeable, sizeof(cdb_sense_changeable), 0);
#ifdef CDROM_DEBUG
printf("[CDROM] mode sense changeable status code %d\n", rv);
@ -1578,7 +1512,9 @@ bool cdrom_set_read_cache(libretro_vfs_implementation_file *stream, bool enabled
printf("Mode sense data for caching mode page: ");
for (i = 0; i < (int)sizeof(buf); i++)
{
printf("%02X ", buf[i]);
}
printf("\n");
fflush(stdout);
@ -1591,7 +1527,7 @@ bool cdrom_set_read_cache(libretro_vfs_implementation_file *stream, bool enabled
if (enabled)
buf[10] &= ~1;
else
buf[10] |= 1;
buf[10] |= 1;
rv = cdrom_send_command(stream, DIRECTION_OUT, buf, sizeof(buf), cdb_select, sizeof(cdb_select), 0);
@ -1640,7 +1576,9 @@ bool cdrom_get_timeouts(libretro_vfs_implementation_file *stream, cdrom_group_ti
printf("Mode sense data for timeout groups: ");
for (i = 0; i < (int)sizeof(buf); i++)
{
printf("%02X ", buf[i]);
}
printf("\n");
@ -1662,8 +1600,8 @@ bool cdrom_get_timeouts(libretro_vfs_implementation_file *stream, cdrom_group_ti
bool cdrom_has_atip(libretro_vfs_implementation_file *stream)
{
/* MMC Command: READ TOC/PMA/ATIP */
unsigned char cdb[] = {0x43, 0x2, 0x4, 0, 0, 0, 0, 0x9, 0x30, 0};
unsigned char buf[32] = {0};
unsigned char cdb[] = {0x43, 0x2, 0x4, 0, 0, 0, 0, 0x9, 0x30, 0};
unsigned char buf[32] = {0};
unsigned short atip_len = 0;
int rv = cdrom_send_command(stream, DIRECTION_IN, buf, sizeof(buf), cdb, sizeof(cdb), 0);
@ -1673,10 +1611,7 @@ bool cdrom_has_atip(libretro_vfs_implementation_file *stream)
atip_len = buf[0] << 8 | buf[1];
#ifdef CDROM_DEBUG
printf("ATIP Length %d, Disc Type %d, Disc Sub-Type %d\n",
atip_len,
(buf[6] >> 6) & 0x1,
((buf[6] >> 5) & 0x1) << 2 | ((buf[6] >> 4) & 0x1) << 1 | ((buf[6] >> 3) & 0x1) << 0);
printf("ATIP Length %d, Disc Type %d, Disc Sub-Type %d\n", atip_len, (buf[6] >> 6) & 0x1, ((buf[6] >> 5) & 0x1) << 2 | ((buf[6] >> 4) & 0x1) << 1 | ((buf[6] >> 3) & 0x1) << 0);
#endif
if (atip_len < 5)
@ -1687,23 +1622,27 @@ bool cdrom_has_atip(libretro_vfs_implementation_file *stream)
void cdrom_device_fillpath(char *path, size_t len, char drive, unsigned char track, bool is_cue)
{
size_t pos = 0;
if (!path || len == 0)
return;
if (is_cue)
{
#ifdef _WIN32
size_t pos = strlcpy(path, "cdrom://", len);
pos = strlcpy(path, "cdrom://", len);
if (len > pos)
path[pos++] = drive;
pos = strlcat(path, ":/drive.cue", len);
#else
#ifdef __linux__
size_t pos = strlcpy(path, "cdrom://drive", len);
if (len > pos + 1)
{
pos = strlcpy(path, "cdrom://drive", len);
if (len > pos)
path[pos++] = drive;
path[pos] = '\0';
}
pos = strlcat(path, ".cue", len);
#endif
#endif
@ -1711,18 +1650,19 @@ void cdrom_device_fillpath(char *path, size_t len, char drive, unsigned char tra
else
{
#ifdef _WIN32
size_t pos = strlcpy(path, "cdrom://", len);
if (len > pos + 1)
{
pos = strlcpy(path, "cdrom://", len);
if (len > pos)
path[pos++] = drive;
path[pos] = '\0';
}
pos += snprintf(path + pos, len - pos, ":/drive-track%02d.bin", track);
#else
#ifdef __linux__
size_t pos = strlcpy(path, "cdrom://drive", len);
pos = strlcpy(path, "cdrom://drive", len);
if (len > pos)
path[pos++] = drive;
pos += snprintf(path + pos, len - pos, "-track%02d.bin", track);
#endif
#endif

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (compat_posix_string.c).

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (compat_snprintf.c).
@ -33,12 +33,12 @@
#if _MSC_VER < 1300
#define _vscprintf c89_vscprintf_retro__
static int c89_vscprintf_retro__(const char *fmt, va_list pargs)
static int c89_vscprintf_retro__(const char *format, va_list pargs)
{
int retval;
va_list argcopy;
va_copy(argcopy, pargs);
retval = vsnprintf(NULL, 0, fmt, argcopy);
retval = vsnprintf(NULL, 0, format, argcopy);
va_end(argcopy);
return retval;
}
@ -46,36 +46,38 @@ static int c89_vscprintf_retro__(const char *fmt, va_list pargs)
/* http://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010 */
int c99_vsnprintf_retro__(char *s, size_t len, const char *fmt, va_list ap)
int c99_vsnprintf_retro__(char *outBuf, size_t size, const char *format, va_list ap)
{
int count = -1;
if (len != 0)
if (size != 0)
{
#if (_MSC_VER <= 1310)
count = _vsnprintf(s, len - 1, fmt, ap);
count = _vsnprintf(outBuf, size - 1, format, ap);
#else
count = _vsnprintf_s(s, len, len - 1, fmt, ap);
count = _vsnprintf_s(outBuf, size, size - 1, format, ap);
#endif
}
if (count == -1)
count = _vscprintf(fmt, ap);
count = _vscprintf(format, ap);
/* there was no room for a NULL, so truncate the last character */
if (count == len && len)
s[len - 1] = '\0';
if (count == size)
{
/* there was no room for a NULL, so truncate the last character */
outBuf[size - 1] = '\0';
}
return count;
}
int c99_snprintf_retro__(char *s, size_t len, const char *fmt, ...)
int c99_snprintf_retro__(char *outBuf, size_t size, const char *format, ...)
{
int count;
va_list ap;
va_start(ap, fmt);
count = c99_vsnprintf_retro__(s, len, fmt, ap);
va_start(ap, format);
count = c99_vsnprintf_retro__(outBuf, size, format, ap);
va_end(ap);
return count;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (compat_strcasestr.c).

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (compat_strl.c).
@ -60,3 +60,10 @@ size_t strlcat(char *dest, const char *source, size_t size)
return len + strlcpy(dest, source, size);
}
#endif
char *strldup(const char *s, size_t n)
{
char *dst = (char*)malloc(sizeof(char) * (n + 1));
strlcpy(dst, s, n);
return dst;
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (fopen_utf8.c).
@ -36,29 +36,25 @@
void *fopen_utf8(const char * filename, const char * mode)
{
#if defined(LEGACY_WIN32)
#if defined(_XBOX)
return fopen(filename, mode);
#elif defined(LEGACY_WIN32)
FILE *ret = NULL;
char * filename_local = utf8_to_local_string_alloc(filename);
if (!filename_local)
return NULL;
ret = fopen(filename_local, mode);
if (filename_local)
{
FILE *ret = fopen(filename_local, mode);
free(filename_local);
return ret;
}
return ret;
#else
wchar_t * filename_w = utf8_to_utf16_string_alloc(filename);
if (filename_w)
{
FILE *ret = NULL;
wchar_t *mode_w = utf8_to_utf16_string_alloc(mode);
if (mode_w)
{
ret = _wfopen(filename_w, mode_w);
free(mode_w);
}
free(filename_w);
return ret;
}
wchar_t * filename_w = utf8_to_utf16_string_alloc(filename);
wchar_t * mode_w = utf8_to_utf16_string_alloc(mode);
FILE* ret = _wfopen(filename_w, mode_w);
free(filename_w);
free(mode_w);
return ret;
#endif
return NULL;
}
#endif

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (encoding_utf.c).
@ -37,8 +37,6 @@
#include <xtl.h>
#endif
#define UTF8_WALKBYTE(string) (*((*(string))++))
static unsigned leading_ones(uint8_t c)
{
unsigned ones = 0;
@ -51,12 +49,9 @@ static unsigned leading_ones(uint8_t c)
return ones;
}
/**
* utf8_conv_utf32:
*
* Simple implementation. Assumes the sequence is
* properly synchronized and terminated.
**/
/* Simple implementation. Assumes the sequence is
* properly synchronized and terminated. */
size_t utf8_conv_utf32(uint32_t *out, size_t out_chars,
const char *in, size_t in_size)
{
@ -82,7 +77,7 @@ size_t utf8_conv_utf32(uint32_t *out, size_t out_chars,
for (i = 0; i < extra; i++, in++, shift -= 6)
c |= (*in & 0x3f) << shift;
*out++ = c;
*out++ = c;
in_size -= 1 + extra;
out_chars--;
ret++;
@ -91,22 +86,16 @@ size_t utf8_conv_utf32(uint32_t *out, size_t out_chars,
return ret;
}
/**
* utf16_conv_utf8:
*
* Leaf function.
**/
bool utf16_conv_utf8(uint8_t *out, size_t *out_chars,
const uint16_t *in, size_t in_size)
{
size_t out_pos = 0;
size_t in_pos = 0;
static const
uint8_t utf8_limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
static uint8_t kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
size_t out_pos = 0;
size_t in_pos = 0;
for (;;)
{
unsigned num_adds;
unsigned numAdds;
uint32_t value;
if (in_pos == in_size)
@ -135,41 +124,37 @@ bool utf16_conv_utf8(uint8_t *out, size_t *out_chars,
value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000;
}
for (num_adds = 1; num_adds < 5; num_adds++)
if (value < (((uint32_t)1) << (num_adds * 5 + 6)))
for (numAdds = 1; numAdds < 5; numAdds++)
if (value < (((uint32_t)1) << (numAdds * 5 + 6)))
break;
if (out)
out[out_pos] = (char)(utf8_limits[num_adds - 1]
+ (value >> (6 * num_adds)));
out[out_pos] = (char)(kUtf8Limits[numAdds - 1]
+ (value >> (6 * numAdds)));
out_pos++;
do
{
num_adds--;
numAdds--;
if (out)
out[out_pos] = (char)(0x80
+ ((value >> (6 * num_adds)) & 0x3F));
+ ((value >> (6 * numAdds)) & 0x3F));
out_pos++;
}while (num_adds != 0);
}while (numAdds != 0);
}
*out_chars = out_pos;
return false;
}
/**
* utf8cpy:
*
* Acts mostly like strlcpy.
/* Acts mostly like strlcpy.
*
* Copies the given number of UTF-8 characters,
* but at most @d_len bytes.
* but at most d_len bytes.
*
* Always NULL terminates. Does not copy half a character.
* @s is assumed valid UTF-8.
* Use only if @chars is considerably less than @d_len.
* Always NULL terminates.
* Does not copy half a character.
*
* @return Number of bytes.
**/
* Returns number of bytes. 's' is assumed valid UTF-8.
* Use only if 'chars' is considerably less than 'd_len'. */
size_t utf8cpy(char *d, size_t d_len, const char *s, size_t chars)
{
const uint8_t *sb = (const uint8_t*)s;
@ -181,15 +166,13 @@ size_t utf8cpy(char *d, size_t d_len, const char *s, size_t chars)
while (*sb && chars-- > 0)
{
sb++;
while ((*sb & 0xC0) == 0x80)
sb++;
while ((*sb & 0xC0) == 0x80) sb++;
}
if ((size_t)(sb - sb_org) > d_len-1 /* NUL */)
{
sb = sb_org + d_len-1;
while ((*sb & 0xC0) == 0x80)
sb--;
while ((*sb & 0xC0) == 0x80) sb--;
}
memcpy(d, sb_org, sb-sb_org);
@ -198,34 +181,20 @@ size_t utf8cpy(char *d, size_t d_len, const char *s, size_t chars)
return sb-sb_org;
}
/**
* utf8skip:
*
* Leaf function
**/
const char *utf8skip(const char *str, size_t chars)
{
const uint8_t *strb = (const uint8_t*)str;
if (!chars)
return str;
do
{
strb++;
while ((*strb & 0xC0)==0x80)
strb++;
while ((*strb & 0xC0)==0x80) strb++;
chars--;
}while (chars);
} while(chars);
return (const char*)strb;
}
/**
* utf8len:
*
* Leaf function.
**/
size_t utf8len(const char *string)
{
size_t ret = 0;
@ -242,35 +211,30 @@ size_t utf8len(const char *string)
return ret;
}
/**
* utf8_walk:
*
* Does not validate the input.
*
* Leaf function.
*
* @return Returns garbage if it's not UTF-8.
**/
static uint8_t utf8_walkbyte(const char **string)
{
return *((*string)++);
}
/* Does not validate the input, returns garbage if it's not UTF-8. */
uint32_t utf8_walk(const char **string)
{
uint8_t first = UTF8_WALKBYTE(string);
uint8_t first = utf8_walkbyte(string);
uint32_t ret = 0;
if (first < 128)
return first;
ret = (ret << 6) | (UTF8_WALKBYTE(string) & 0x3F);
ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F);
if (first >= 0xE0)
{
ret = (ret << 6) | (UTF8_WALKBYTE(string) & 0x3F);
if (first >= 0xF0)
{
ret = (ret << 6) | (UTF8_WALKBYTE(string) & 0x3F);
return ret | (first & 7) << 18;
}
return ret | (first & 15) << 12;
}
ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F);
if (first >= 0xF0)
ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F);
if (first >= 0xF0)
return ret | (first & 7) << 18;
if (first >= 0xE0)
return ret | (first & 15) << 12;
return ret | (first & 31) << 6;
}
@ -278,23 +242,24 @@ static bool utf16_to_char(uint8_t **utf_data,
size_t *dest_len, const uint16_t *in)
{
unsigned len = 0;
while (in[len] != '\0')
len++;
utf16_conv_utf8(NULL, dest_len, in, len);
*dest_len += 1;
if ((*utf_data = (uint8_t*)malloc(*dest_len)) != 0)
return utf16_conv_utf8(*utf_data, dest_len, in, len);
return false;
*utf_data = (uint8_t*)malloc(*dest_len);
if (*utf_data == 0)
return false;
return utf16_conv_utf8(*utf_data, dest_len, in, len);
}
/**
* utf16_to_char_string:
**/
bool utf16_to_char_string(const uint16_t *in, char *s, size_t len)
{
size_t dest_len = 0;
uint8_t *utf16_data = NULL;
bool ret = utf16_to_char(&utf16_data, &dest_len, in);
size_t dest_len = 0;
uint8_t *utf16_data = NULL;
bool ret = utf16_to_char(&utf16_data, &dest_len, in);
if (ret)
{
@ -303,228 +268,247 @@ bool utf16_to_char_string(const uint16_t *in, char *s, size_t len)
}
free(utf16_data);
utf16_data = NULL;
utf16_data = NULL;
return ret;
}
#if defined(_WIN32) && !defined(_XBOX) && !defined(UNICODE)
/**
* mb_to_mb_string_alloc:
*
* @return Returned pointer MUST be freed by the caller if non-NULL.
**/
static char *mb_to_mb_string_alloc(const char *str,
/* Returned pointer MUST be freed by the caller if non-NULL. */
static char* mb_to_mb_string_alloc(const char *str,
enum CodePage cp_in, enum CodePage cp_out)
{
char *path_buf = NULL;
wchar_t *path_buf_wide = NULL;
int path_buf_wide_len = MultiByteToWideChar(cp_in, 0, str, -1, NULL, 0);
/* Windows 95 will return 0 from these functions with
* a UTF8 codepage set without MSLU.
*
* From an unknown MSDN version (others omit this info):
* - CP_UTF8 Windows 98/Me, Windows NT 4.0 and later:
* Translate using UTF-8. When this is set, dwFlags must be zero.
* - Windows 95: Under the Microsoft Layer for Unicode,
* MultiByteToWideChar also supports CP_UTF7 and CP_UTF8.
*/
if (!path_buf_wide_len)
return strdup(str);
if ((path_buf_wide = (wchar_t*)
calloc(path_buf_wide_len + sizeof(wchar_t), sizeof(wchar_t))))
{
MultiByteToWideChar(cp_in, 0,
str, -1, path_buf_wide, path_buf_wide_len);
if (*path_buf_wide)
{
int path_buf_len = WideCharToMultiByte(cp_out, 0,
path_buf_wide, -1, NULL, 0, NULL, NULL);
if (path_buf_len)
{
char *path_buf = (char*)
calloc(path_buf_len + sizeof(char), sizeof(char));
if (path_buf)
{
WideCharToMultiByte(cp_out, 0,
path_buf_wide, -1, path_buf,
path_buf_len, NULL, NULL);
free(path_buf_wide);
if (*path_buf)
return path_buf;
free(path_buf);
return NULL;
}
}
else
{
free(path_buf_wide);
return strdup(str);
}
}
free(path_buf_wide);
}
return NULL;
}
#endif
/**
* utf8_to_local_string_alloc:
*
* @return Returned pointer MUST be freed by the caller if non-NULL.
**/
char* utf8_to_local_string_alloc(const char *str)
{
if (str && *str)
#if defined(_WIN32) && !defined(_XBOX) && !defined(UNICODE)
return mb_to_mb_string_alloc(str, CODEPAGE_UTF8, CODEPAGE_LOCAL);
#else
return strdup(str); /* Assume string needs no modification if not on Windows */
#endif
return NULL;
}
/**
* local_to_utf8_string_alloc:
*
* @return Returned pointer MUST be freed by the caller if non-NULL.
**/
char *local_to_utf8_string_alloc(const char *str)
{
if (str && *str)
#if defined(_WIN32) && !defined(_XBOX) && !defined(UNICODE)
return mb_to_mb_string_alloc(str, CODEPAGE_LOCAL, CODEPAGE_UTF8);
#else
return strdup(str); /* Assume string needs no modification if not on Windows */
#endif
return NULL;
}
/**
* utf8_to_utf16_string_alloc:
*
* @return Returned pointer MUST be freed by the caller if non-NULL.
**/
wchar_t* utf8_to_utf16_string_alloc(const char *str)
{
#ifdef _WIN32
int len = 0;
#else
size_t len = 0;
#endif
wchar_t *buf = NULL;
int path_buf_len = 0;
int path_buf_wide_len = 0;
if (!str || !*str)
return NULL;
#ifdef _WIN32
if ((len = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0)))
{
if (!(buf = (wchar_t*)calloc(len, sizeof(wchar_t))))
return NULL;
(void)path_buf;
(void)path_buf_wide;
(void)path_buf_len;
(void)path_buf_wide_len;
if ((MultiByteToWideChar(CP_UTF8, 0, str, -1, buf, len)) < 0)
#if !defined(_WIN32) || defined(_XBOX)
/* assume string needs no modification if not on Windows */
return strdup(str);
#else
#ifdef UNICODE
/* TODO/FIXME: Not implemented. */
return strdup(str);
#else
/* Windows 95 will return 0 from these functions with a UTF8 codepage set without MSLU. From an unknown MSDN version (others omit this info):
* - CP_UTF8 Windows 98/Me, Windows NT 4.0 and later: Translate using UTF-8. When this is set, dwFlags must be zero.
* - Windows 95: Under the Microsoft Layer for Unicode, MultiByteToWideChar also supports CP_UTF7 and CP_UTF8.
*/
path_buf_wide_len = MultiByteToWideChar(cp_in, 0, str, -1, NULL, 0);
if (path_buf_wide_len)
{
path_buf_wide = (wchar_t*)
calloc(path_buf_wide_len + sizeof(wchar_t), sizeof(wchar_t));
if (path_buf_wide)
{
free(buf);
return NULL;
MultiByteToWideChar(cp_in, 0,
str, -1, path_buf_wide, path_buf_wide_len);
if (*path_buf_wide)
{
path_buf_len = WideCharToMultiByte(cp_out, 0,
path_buf_wide, -1, NULL, 0, NULL, NULL);
if (path_buf_len)
{
path_buf = (char*)
calloc(path_buf_len + sizeof(char), sizeof(char));
if (path_buf)
{
WideCharToMultiByte(cp_out, 0,
path_buf_wide, -1, path_buf,
path_buf_len, NULL, NULL);
free(path_buf_wide);
if (*path_buf)
return path_buf;
free(path_buf);
return NULL;
}
}
else
{
free(path_buf_wide);
return strdup(str);
}
}
}
}
else
{
/* Fallback to ANSI codepage instead */
if ((len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0)))
{
if (!(buf = (wchar_t*)calloc(len, sizeof(wchar_t))))
return NULL;
return strdup(str);
if ((MultiByteToWideChar(CP_ACP, 0, str, -1, buf, len)) < 0)
{
free(buf);
return NULL;
}
}
}
#else
/* NOTE: For now, assume non-Windows platforms' locale is already UTF-8. */
if ((len = mbstowcs(NULL, str, 0) + 1))
{
if (!(buf = (wchar_t*)calloc(len, sizeof(wchar_t))))
return NULL;
if (path_buf_wide)
free(path_buf_wide);
if ((mbstowcs(buf, str, len)) == (size_t)-1)
{
free(buf);
return NULL;
}
}
return NULL;
#endif
#endif
return buf;
}
/**
* utf16_to_utf8_string_alloc:
*
* @return Returned pointer MUST be freed by the caller if non-NULL.
**/
char* utf16_to_utf8_string_alloc(const wchar_t *str)
/* Returned pointer MUST be freed by the caller if non-NULL. */
char* utf8_to_local_string_alloc(const char *str)
{
return mb_to_mb_string_alloc(str, CODEPAGE_UTF8, CODEPAGE_LOCAL);
}
/* Returned pointer MUST be freed by the caller if non-NULL. */
char* local_to_utf8_string_alloc(const char *str)
{
return mb_to_mb_string_alloc(str, CODEPAGE_LOCAL, CODEPAGE_UTF8);
}
/* Returned pointer MUST be freed by the caller if non-NULL. */
wchar_t* utf8_to_utf16_string_alloc(const char *str)
{
#ifdef _WIN32
int len = 0;
int len = 0;
int out_len = 0;
#else
size_t len = 0;
size_t len = 0;
size_t out_len = 0;
#endif
char *buf = NULL;
wchar_t *buf = NULL;
if (!str || !*str)
return NULL;
#ifdef _WIN32
len = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
if (len)
{
UINT code_page = CP_UTF8;
buf = (wchar_t*)calloc(len, sizeof(wchar_t));
if (!buf)
return NULL;
out_len = MultiByteToWideChar(CP_UTF8, 0, str, -1, buf, len);
}
else
{
/* fallback to ANSI codepage instead */
if (!(len = WideCharToMultiByte(code_page,
0, str, -1, NULL, 0, NULL, NULL)))
{
code_page = CP_ACP;
len = WideCharToMultiByte(code_page,
0, str, -1, NULL, 0, NULL, NULL);
}
len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
if (!(buf = (char*)calloc(len, sizeof(char))))
return NULL;
if (WideCharToMultiByte(code_page,
0, str, -1, buf, len, NULL, NULL) < 0)
if (len)
{
free(buf);
return NULL;
buf = (wchar_t*)calloc(len, sizeof(wchar_t));
if (!buf)
return NULL;
out_len = MultiByteToWideChar(CP_ACP, 0, str, -1, buf, len);
}
}
#else
/* NOTE: For now, assume non-Windows platforms'
* locale is already UTF-8. */
if ((len = wcstombs(NULL, str, 0) + 1))
if (out_len < 0)
{
if (!(buf = (char*)calloc(len, sizeof(char))))
free(buf);
return NULL;
}
#else
/* NOTE: For now, assume non-Windows platforms' locale is already UTF-8. */
len = mbstowcs(NULL, str, 0) + 1;
if (len)
{
buf = (wchar_t*)calloc(len, sizeof(wchar_t));
if (!buf)
return NULL;
if (wcstombs(buf, str, len) == (size_t)-1)
{
free(buf);
return NULL;
}
out_len = mbstowcs(buf, str, len);
}
if (out_len == (size_t)-1)
{
free(buf);
return NULL;
}
#endif
return buf;
}
/* Returned pointer MUST be freed by the caller if non-NULL. */
char* utf16_to_utf8_string_alloc(const wchar_t *str)
{
#ifdef _WIN32
int len = 0;
int out_len = 0;
#else
size_t len = 0;
size_t out_len = 0;
#endif
char *buf = NULL;
if (!str || !*str)
return NULL;
#ifdef _WIN32
len = WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL);
if (len)
{
buf = (char*)calloc(len, sizeof(char));
if (!buf)
return NULL;
out_len = WideCharToMultiByte(CP_UTF8, 0, str, -1, buf, len, NULL, NULL);
}
else
{
/* fallback to ANSI codepage instead */
len = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL);
if (len)
{
buf = (char*)calloc(len, sizeof(char));
if (!buf)
return NULL;
out_len = WideCharToMultiByte(CP_ACP, 0, str, -1, buf, len, NULL, NULL);
}
}
if (out_len < 0)
{
free(buf);
return NULL;
}
#else
/* NOTE: For now, assume non-Windows platforms' locale is already UTF-8. */
len = wcstombs(NULL, str, 0) + 1;
if (len)
{
buf = (char*)calloc(len, sizeof(char));
if (!buf)
return NULL;
out_len = wcstombs(buf, str, len);
}
if (out_len == (size_t)-1)
{
free(buf);
return NULL;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2019 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_dirent.c).
@ -31,41 +31,37 @@
#define VFS_FRONTEND
#include <vfs/vfs_implementation.h>
/* TODO/FIXME - static globals */
static retro_vfs_opendir_t dirent_opendir_cb = NULL;
static retro_vfs_readdir_t dirent_readdir_cb = NULL;
static retro_vfs_opendir_t dirent_opendir_cb = NULL;
static retro_vfs_readdir_t dirent_readdir_cb = NULL;
static retro_vfs_dirent_get_name_t dirent_dirent_get_name_cb = NULL;
static retro_vfs_dirent_is_dir_t dirent_dirent_is_dir_cb = NULL;
static retro_vfs_closedir_t dirent_closedir_cb = NULL;
static retro_vfs_dirent_is_dir_t dirent_dirent_is_dir_cb = NULL;
static retro_vfs_closedir_t dirent_closedir_cb = NULL;
void dirent_vfs_init(const struct retro_vfs_interface_info* vfs_info)
{
const struct retro_vfs_interface* vfs_iface;
dirent_opendir_cb = NULL;
dirent_readdir_cb = NULL;
dirent_opendir_cb = NULL;
dirent_readdir_cb = NULL;
dirent_dirent_get_name_cb = NULL;
dirent_dirent_is_dir_cb = NULL;
dirent_closedir_cb = NULL;
dirent_dirent_is_dir_cb = NULL;
dirent_closedir_cb = NULL;
vfs_iface = vfs_info->iface;
vfs_iface = vfs_info->iface;
if (
vfs_info->required_interface_version < DIRENT_REQUIRED_VFS_VERSION ||
!vfs_iface)
if (vfs_info->required_interface_version < DIRENT_REQUIRED_VFS_VERSION || !vfs_iface)
return;
dirent_opendir_cb = vfs_iface->opendir;
dirent_readdir_cb = vfs_iface->readdir;
dirent_opendir_cb = vfs_iface->opendir;
dirent_readdir_cb = vfs_iface->readdir;
dirent_dirent_get_name_cb = vfs_iface->dirent_get_name;
dirent_dirent_is_dir_cb = vfs_iface->dirent_is_dir;
dirent_closedir_cb = vfs_iface->closedir;
dirent_dirent_is_dir_cb = vfs_iface->dirent_is_dir;
dirent_closedir_cb = vfs_iface->closedir;
}
struct RDIR *retro_opendir_include_hidden(
const char *name, bool include_hidden)
struct RDIR *retro_opendir_include_hidden(const char *name, bool include_hidden)
{
if (dirent_opendir_cb)
if (dirent_opendir_cb != NULL)
return (struct RDIR *)dirent_opendir_cb(name, include_hidden);
return (struct RDIR *)retro_vfs_opendir_impl(name, include_hidden);
}
@ -83,14 +79,14 @@ bool retro_dirent_error(struct RDIR *rdir)
int retro_readdir(struct RDIR *rdir)
{
if (dirent_readdir_cb)
if (dirent_readdir_cb != NULL)
return dirent_readdir_cb((struct retro_vfs_dir_handle *)rdir);
return retro_vfs_readdir_impl((struct retro_vfs_dir_handle *)rdir);
}
const char *retro_dirent_get_name(struct RDIR *rdir)
{
if (dirent_dirent_get_name_cb)
if (dirent_dirent_get_name_cb != NULL)
return dirent_dirent_get_name_cb((struct retro_vfs_dir_handle *)rdir);
return retro_vfs_dirent_get_name_impl((struct retro_vfs_dir_handle *)rdir);
}
@ -108,14 +104,14 @@ const char *retro_dirent_get_name(struct RDIR *rdir)
*/
bool retro_dirent_is_dir(struct RDIR *rdir, const char *unused)
{
if (dirent_dirent_is_dir_cb)
if (dirent_dirent_is_dir_cb != NULL)
return dirent_dirent_is_dir_cb((struct retro_vfs_dir_handle *)rdir);
return retro_vfs_dirent_is_dir_impl((struct retro_vfs_dir_handle *)rdir);
}
void retro_closedir(struct RDIR *rdir)
{
if (dirent_closedir_cb)
if (dirent_closedir_cb != NULL)
dirent_closedir_cb((struct retro_vfs_dir_handle *)rdir);
else
retro_vfs_closedir_impl((struct retro_vfs_dir_handle *)rdir);

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (boolean.h).

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2019 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (cdrom.h).
@ -62,10 +62,10 @@ typedef struct
typedef struct
{
cdrom_track_t track[99]; /* unsigned alignment */
cdrom_group_timeouts_t timeouts; /* unsigned short alignment */
unsigned char num_tracks;
char drive;
unsigned char num_tracks;
cdrom_group_timeouts_t timeouts;
cdrom_track_t track[99];
} cdrom_toc_t;
void cdrom_lba_to_msf(unsigned lba, unsigned char *min, unsigned char *sec, unsigned char *frame);

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (apple_compat.h).

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (fnmatch.h).

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (fopen_utf8.h).

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (getopt.h).
@ -72,3 +72,4 @@ RETRO_END_DECLS
/* pragma once */
#endif

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (intrinsics.h).
@ -41,7 +41,7 @@ RETRO_BEGIN_DECLS
/* Count Leading Zero, unsigned 16bit input value */
static INLINE unsigned compat_clz_u16(uint16_t val)
{
#if defined(__GNUC__)
#ifdef __GNUC__
return __builtin_clz(val << 16 | 0x8000);
#else
unsigned ret = 0;
@ -61,36 +61,22 @@ static INLINE int compat_ctz(unsigned x)
{
#if defined(__GNUC__) && !defined(RARCH_CONSOLE)
return __builtin_ctz(x);
#elif _MSC_VER >= 1400 && !defined(_XBOX) && !defined(__WINRT__)
#elif _MSC_VER >= 1400 && !defined(_XBOX)
unsigned long r = 0;
_BitScanForward((unsigned long*)&r, x);
_BitScanReverse((unsigned long*)&r, x);
return (int)r;
#else
int count = 0;
if (!(x & 0xffff))
{
x >>= 16;
count |= 16;
}
if (!(x & 0xff))
{
x >>= 8;
count |= 8;
}
if (!(x & 0xf))
{
x >>= 4;
count |= 4;
}
if (!(x & 0x3))
{
x >>= 2;
count |= 2;
}
if (!(x & 0x1))
count |= 1;
return count;
/* Only checks at nibble granularity,
* because that's what we need. */
if (x & 0x000f)
return 0;
if (x & 0x00f0)
return 4;
if (x & 0x0f00)
return 8;
if (x & 0xf000)
return 12;
return 16;
#endif
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (msvc.h).
@ -29,17 +29,20 @@
extern "C" {
#endif
/* Pre-MSVC 2015 compilers don't implement snprintf, vsnprintf in a cross-platform manner. */
/* Pre-MSVC 2015 compilers don't implement snprintf in a cross-platform manner. */
#if _MSC_VER < 1900
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#ifndef snprintf
#define snprintf c99_snprintf_retro__
#endif
int c99_snprintf_retro__(char *outBuf, size_t size, const char *format, ...);
int c99_snprintf_retro__(char *outBuf, size_t size, const char *format, ...);
#endif
/* Pre-MSVC 2010 compilers don't implement vsnprintf in a cross-platform manner? Not sure about this one. */
#if _MSC_VER < 1600
#include <stdarg.h>
#include <stdlib.h>
#ifndef vsnprintf
#define vsnprintf c99_vsnprintf_retro__
#endif
@ -53,8 +56,6 @@ extern "C" {
#undef UNICODE /* Do not bother with UNICODE at this time. */
#include <direct.h>
#include <stddef.h>
#define _USE_MATH_DEFINES
#include <math.h>
/* Python headers defines ssize_t and sets HAVE_SSIZE_T.
@ -124,3 +125,4 @@ typedef int ssize_t;
#endif
#endif

View File

@ -67,6 +67,7 @@ extern "C" {
# endif
#endif
/* 7.18.1 Integer types. */
/* 7.18.1.1 Exact-width integer types. */
@ -93,6 +94,7 @@ extern "C" {
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
/* 7.18.1.2 Minimum-width integer types. */
typedef int8_t int_least8_t;
typedef int16_t int_least16_t;
@ -253,3 +255,4 @@ typedef uint64_t uintmax_t;
#endif
#endif

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (posix_string.h).
@ -29,6 +29,10 @@
#include <compat/msvc.h>
#endif
#if defined(PS2)
#include <compat_ctype.h>
#endif
RETRO_BEGIN_DECLS
#ifdef _WIN32

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (strcasestr.h).
@ -25,6 +25,10 @@
#include <string.h>
#if defined(PS2)
#include <compat_ctype.h>
#endif
#if defined(RARCH_INTERNAL) && defined(HAVE_CONFIG_H)
#include "../../../config.h"
#endif

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (strl.h).
@ -57,3 +57,4 @@ char *strldup(const char *s, size_t n);
RETRO_END_DECLS
#endif

View File

@ -31,6 +31,7 @@
Jean-loup Gailly Mark Adler
jloup@gzip.org madler@alumni.caltech.edu
The data format used by the zlib library is described by RFCs (Request for
Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950
(zlib format), rfc1951 (deflate format) and rfc1952 (gzip format).
@ -219,6 +220,7 @@ typedef gz_header FAR *gz_headerp;
#define zlib_version zlibVersion()
/* for compatibility with versions < 1.0.2 */
/* basic functions */
const char * zlibVersion (void);
@ -250,6 +252,7 @@ typedef gz_header FAR *gz_headerp;
this will be done by deflate().
*/
int deflate (z_streamp strm, int flush);
/*
deflate compresses as much data as possible, and stops when the input
@ -356,6 +359,7 @@ typedef gz_header FAR *gz_headerp;
space to continue compressing.
*/
int deflateEnd (z_streamp strm);
/*
All dynamically allocated data structures for this stream are freed.
@ -369,6 +373,7 @@ typedef gz_header FAR *gz_headerp;
deallocated).
*/
/*
int inflateInit (z_streamp strm);
@ -393,6 +398,7 @@ typedef gz_header FAR *gz_headerp;
until inflate() is called.
*/
int inflate (z_streamp strm, int flush);
/*
inflate decompresses as much data as possible, and stops when the input
@ -508,6 +514,7 @@ typedef gz_header FAR *gz_headerp;
recovery of the data is desired.
*/
int inflateEnd (z_streamp strm);
/*
All dynamically allocated data structures for this stream are freed.
@ -519,6 +526,7 @@ typedef gz_header FAR *gz_headerp;
static string (which must not be deallocated).
*/
/* Advanced functions */
/*
@ -1196,8 +1204,8 @@ typedef int (*out_func) (void FAR *, unsigned char FAR *, unsigned);
compress() or compress2() call to allocate the destination buffer.
*/
int uncompress (Bytef *dest, uLongf *destLen,
const Bytef *source, uLongf sourceLen);
int uncompress (unsigned char *dest, uint32_t *destLen,
const unsigned char *source, uint32_t sourceLen);
/*
Decompresses the source buffer into the destination buffer. sourceLen is
the byte length of the source buffer. Upon entry, destLen is the total size
@ -1626,6 +1634,7 @@ uint32_t adler32 (uint32_t adler, const uint8_t *buf, size_t len);
len2.
*/
/* various hacks, don't look :) */
/* deflateInit and inflateInit are macros to allow checking the zlib version
@ -1742,9 +1751,8 @@ uint32_t adler32 (uint32_t adler, const uint8_t *buf, size_t len);
const char * zError (int);
int inflateSyncPoint (z_streamp);
const uint32_t * get_crc_table(void);
const uint32_t * get_crc_table(void);
int inflateUndermine (z_streamp, int);
int inflateValidate (z_streamp, int);
int inflateResetKeep (z_streamp);
int deflateResetKeep (z_streamp);
#if defined(_WIN32) && !defined(Z_SOLO)

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (utf.h).
@ -35,102 +35,32 @@ RETRO_BEGIN_DECLS
enum CodePage
{
CODEPAGE_LOCAL = 0, /* CP_ACP */
CODEPAGE_UTF8 = 65001 /* CP_UTF8 */
CODEPAGE_UTF8 = 65001 /* CP_UTF8 */
};
/**
* utf8_conv_utf32:
*
* Simple implementation. Assumes the sequence is
* properly synchronized and terminated.
**/
size_t utf8_conv_utf32(uint32_t *out, size_t out_chars,
const char *in, size_t in_size);
/**
* utf16_conv_utf8:
*
* Leaf function.
**/
bool utf16_conv_utf8(uint8_t *out, size_t *out_chars,
const uint16_t *in, size_t in_size);
/**
* utf8len:
*
* Leaf function.
**/
size_t utf8len(const char *string);
/**
* utf8cpy:
*
* Acts mostly like strlcpy.
*
* Copies the given number of UTF-8 characters,
* but at most @d_len bytes.
*
* Always NULL terminates. Does not copy half a character.
* @s is assumed valid UTF-8.
* Use only if @chars is considerably less than @d_len.
*
* Hidden non-leaf function cost:
* - Calls memcpy
*
* @return Number of bytes.
**/
size_t utf8cpy(char *d, size_t d_len, const char *s, size_t chars);
/**
* utf8skip:
*
* Leaf function
**/
const char *utf8skip(const char *str, size_t chars);
/**
* utf8_walk:
*
* Does not validate the input.
*
* Leaf function.
*
* @return Returns garbage if it's not UTF-8.
**/
uint32_t utf8_walk(const char **string);
/**
* utf16_to_char_string:
**/
bool utf16_to_char_string(const uint16_t *in, char *s, size_t len);
/**
* utf8_to_local_string_alloc:
*
* @return Returned pointer MUST be freed by the caller if non-NULL.
**/
char *utf8_to_local_string_alloc(const char *str);
char* utf8_to_local_string_alloc(const char *str);
/**
* local_to_utf8_string_alloc:
*
* @return Returned pointer MUST be freed by the caller if non-NULL.
**/
char *local_to_utf8_string_alloc(const char *str);
char* local_to_utf8_string_alloc(const char *str);
/**
* utf8_to_utf16_string_alloc:
*
* @return Returned pointer MUST be freed by the caller if non-NULL.
**/
wchar_t *utf8_to_utf16_string_alloc(const char *str);
wchar_t* utf8_to_utf16_string_alloc(const char *str);
/**
* utf16_to_utf8_string_alloc:
*
* @return Returned pointer MUST be freed by the caller if non-NULL.
**/
char *utf16_to_utf8_string_alloc(const wchar_t *str);
char* utf16_to_utf8_string_alloc(const wchar_t *str);
RETRO_END_DECLS

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2019 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (file_path.h).
@ -51,28 +51,6 @@ enum
RARCH_FILE_UNSUPPORTED
};
struct path_linked_list
{
char *path;
struct path_linked_list *next;
};
/**
* Create a new linked list with one item in it
* The path on this item will be set to NULL
**/
struct path_linked_list* path_linked_list_new(void);
/* Free the entire linked list */
void path_linked_list_free(struct path_linked_list *in_path_linked_list);
/**
* Add a node to the linked list with this path
* If the first node's path if it's not yet set,
* set this instead
**/
void path_linked_list_add_path(struct path_linked_list *in_path_linked_list, char *path);
/**
* path_is_compressed_file:
* @path : path
@ -103,12 +81,12 @@ bool path_is_compressed_file(const char *path);
* path_get_archive_delim:
* @path : path
*
* Find delimiter of an archive file. Only the first '#'
* Gets delimiter of an archive file. Only the first '#'
* after a compression extension is considered.
*
* @return pointer to the delimiter in the path if it contains
* a path inside a compressed file, otherwise NULL.
**/
* Returns: pointer to the delimiter in the path if it contains
* a compressed file, otherwise NULL.
*/
const char *path_get_archive_delim(const char *path);
/**
@ -118,28 +96,10 @@ const char *path_get_archive_delim(const char *path);
* Gets extension of file. Only '.'s
* after the last slash are considered.
*
* Hidden non-leaf function cost:
* - calls string_is_empty()
* - calls strrchr
*
* @return extension part from the path.
**/
* Returns: extension part from the path.
*/
const char *path_get_extension(const char *path);
/**
* path_get_extension_mutable:
* @path : path
*
* Specialized version of path_get_extension(). Return
* value is mutable.
*
* Gets extension of file. Only '.'s
* after the last slash are considered.
*
* @return extension part from the path.
**/
char *path_get_extension_mutable(const char *path);
/**
* path_remove_extension:
* @path : path
@ -148,10 +108,7 @@ char *path_get_extension_mutable(const char *path);
* text after and including the last '.'.
* Only '.'s after the last slash are considered.
*
* Hidden non-leaf function cost:
* - calls strrchr
*
* @return
* Returns:
* 1) If path has an extension, returns path with the
* extension removed.
* 2) If there is no extension, returns NULL.
@ -165,28 +122,10 @@ char *path_remove_extension(char *path);
*
* Get basename from @path.
*
* Hidden non-leaf function cost:
* - Calls path_get_archive_delim()
* - can call find_last_slash() once if it returns NULL
*
* @return basename from path.
* Returns: basename from path.
**/
const char *path_basename(const char *path);
/**
* path_basename_nocompression:
* @path : path
*
* Specialized version of path_basename().
* Get basename from @path.
*
* Hidden non-leaf function cost:
* - Calls find_last_slash()
*
* @return basename from path.
**/
const char *path_basename_nocompression(const char *path);
/**
* path_basedir:
* @path : path
@ -199,32 +138,23 @@ void path_basedir(char *path);
/**
* path_parent_dir:
* @path : path
* @len : length of @path
*
* Extracts parent directory by mutating path.
* Assumes that path is a directory. Keeps trailing '/'.
* If the path was already at the root directory, returns empty string
**/
void path_parent_dir(char *path, size_t len);
void path_parent_dir(char *path);
/**
* path_resolve_realpath:
* @buf : input and output buffer for path
* @buf : buffer for path
* @size : size of buffer
* @resolve_symlinks : whether to resolve symlinks or not
*
* Resolves use of ".", "..", multiple slashes etc in absolute paths.
*
* Relative paths are rebased on the current working dir.
*
* @return @buf if successful, NULL otherwise.
* Note: Not implemented on consoles
* Note: Symlinks are only resolved on Unix-likes
* Note: The current working dir might not be what you expect,
* e.g. on Android it is "/"
* Use of fill_pathname_resolve_relative() should be prefered
* Turns relative paths into absolute paths and
* resolves use of "." and ".." in absolute paths.
* If relative, rebases on current working dir.
**/
char *path_resolve_realpath(char *buf, size_t size, bool resolve_symlinks);
void path_resolve_realpath(char *buf, size_t size);
/**
* path_relative_to:
@ -239,11 +169,8 @@ char *path_resolve_realpath(char *buf, size_t size, bool resolve_symlinks);
* Both @path and @base are assumed to be absolute paths without "." or "..".
*
* E.g. path /a/b/e/f.cgp with base /a/b/c/d/ turns into ../../e/f.cgp
*
* @return Length of the string copied into @out
**/
size_t path_relative_to(char *out, const char *path, const char *base,
size_t size);
void path_relative_to(char *out, const char *path, const char *base, size_t size);
/**
* path_is_absolute:
@ -251,7 +178,7 @@ size_t path_relative_to(char *out, const char *path, const char *base,
*
* Checks if @path is an absolute path or a relative path.
*
* @return true if path is absolute, false if path is relative.
* Returns: true if path is absolute, false if path is relative.
**/
bool path_is_absolute(const char *path);
@ -275,15 +202,8 @@ bool path_is_absolute(const char *path);
* out_path = "/foo/bar/baz/boo.asm"
* E.g.: in_path = "/foo/bar/baz/boo.c", replace = "" =>
* out_path = "/foo/bar/baz/boo"
*
* Hidden non-leaf function cost:
* - calls strlcpy 2x
* - calls strrchr
* - calls strlcat
*
* @return Length of the string copied into @out
*/
size_t fill_pathname(char *out_path, const char *in_path,
void fill_pathname(char *out_path, const char *in_path,
const char *replace, size_t size);
/**
@ -297,14 +217,8 @@ size_t fill_pathname(char *out_path, const char *in_path,
*
* E.g.:
* out_filename = "RetroArch-{month}{day}-{Hours}{Minutes}.{@ext}"
*
* Hidden non-leaf function cost:
* - Calls rtime_localtime()
* - Calls strftime
* - Calls strlcat
*
**/
size_t fill_dated_filename(char *out_filename,
void fill_dated_filename(char *out_filename,
const char *ext, size_t size);
/**
@ -319,33 +233,34 @@ size_t fill_dated_filename(char *out_filename,
*
* E.g.:
* out_filename = "RetroArch-{year}{month}{day}-{Hour}{Minute}{Second}.{@ext}"
*
* Hidden non-leaf function cost:
* - Calls time
* - Calls rtime_localtime()
* - Calls strlcpy 2x
* - Calls string_is_empty()
* - Calls strftime
* - Calls strlcat
*
* @return Length of the string copied into @out_path
**/
size_t fill_str_dated_filename(char *out_filename,
void fill_str_dated_filename(char *out_filename,
const char *in_str, const char *ext, size_t size);
/**
* find_last_slash:
* @str : path
* @size : size of path
* fill_pathname_noext:
* @out_path : output path
* @in_path : input path
* @replace : what to replace
* @size : buffer size of output path
*
* Find last slash in path. Tries to find
* a backslash on Windows too which takes precedence
* over regular slash.
* Appends a filename extension 'replace' to 'in_path', and outputs
* result in 'out_path'.
*
* Assumes in_path has no extension. If an extension is still
* present in 'in_path', it will be ignored.
*
*/
void fill_pathname_noext(char *out_path, const char *in_path,
const char *replace, size_t size);
* Hidden non-leaf function cost:
* - calls strrchr
/**
* find_last_slash:
* @str : input path
*
* @return pointer to last slash/backslash found in @str.
* Gets a pointer to the last slash in the input path.
*
* Returns: a pointer to the last slash in the input path.
**/
char *find_last_slash(const char *str);
@ -365,13 +280,8 @@ char *find_last_slash(const char *str);
*
* E.g..: in_dir = "/tmp/some_dir", in_basename = "/some_content/foo.c",
* replace = ".asm" => in_dir = "/tmp/some_dir/foo.c.asm"
*
* Hidden non-leaf function cost:
* - Calls fill_pathname_slash()
* - Calls path_basename()
* - Calls strlcpy 2x
**/
size_t fill_pathname_dir(char *in_dir, const char *in_basename,
void fill_pathname_dir(char *in_dir, const char *in_basename,
const char *replace, size_t size);
/**
@ -381,14 +291,15 @@ size_t fill_pathname_dir(char *in_dir, const char *in_basename,
* @size : size of output path
*
* Copies basename of @in_path into @out_path.
*
* Hidden non-leaf function cost:
* - Calls path_basename()
* - Calls strlcpy
*
* @return length of the string copied into @out
**/
size_t fill_pathname_base(char *out_path, const char *in_path, size_t size);
void fill_pathname_base(char *out_path, const char *in_path, size_t size);
void fill_pathname_base_noext(char *out_dir,
const char *in_path, size_t size);
void fill_pathname_base_ext(char *out,
const char *in_path, const char *ext,
size_t size);
/**
* fill_pathname_basedir:
@ -399,13 +310,12 @@ size_t fill_pathname_base(char *out_path, const char *in_path, size_t size);
* Copies base directory of @in_path into @out_path.
* If in_path is a path without any slashes (relative current directory),
* @out_path will get path "./".
*
* Hidden non-leaf function cost:
* - Calls strlcpy
* - Calls path_basedir()
**/
void fill_pathname_basedir(char *out_path, const char *in_path, size_t size);
void fill_pathname_basedir_noext(char *out_dir,
const char *in_path, size_t size);
/**
* fill_pathname_parent_dir_name:
* @out_dir : output directory
@ -414,13 +324,7 @@ void fill_pathname_basedir(char *out_path, const char *in_path, size_t size);
*
* Copies only the parent directory name of @in_dir into @out_dir.
* The two buffers must not overlap. Removes trailing '/'.
*
* Hidden non-leaf function cost:
* - Calls strdup
* - Calls find_last_slash() x times
* - Can call strlcpy
*
* @return true on success, false if a slash was not found in the path.
* Returns true on success, false if a slash was not found in the path.
**/
bool fill_pathname_parent_dir_name(char *out_dir,
const char *in_dir, size_t size);
@ -434,11 +338,6 @@ bool fill_pathname_parent_dir_name(char *out_dir,
* Copies parent directory of @in_dir into @out_dir.
* Assumes @in_dir is a directory. Keeps trailing '/'.
* If the path was already at the root directory, @out_dir will be an empty string.
*
* Hidden non-leaf function cost:
* - Can call strlcpy if (@out_dir != @in_dir)
* - Calls strlen if (@out_dir == @in_dir)
* - Calls path_parent_dir()
**/
void fill_pathname_parent_dir(char *out_dir,
const char *in_dir, size_t size);
@ -466,51 +365,31 @@ void fill_pathname_resolve_relative(char *out_path, const char *in_refpath,
* @size : size of output path
*
* Joins a directory (@dir) and path (@path) together.
* Makes sure not to get two consecutive slashes
* Makes sure not to get two consecutive slashes
* between directory and path.
*
* Hidden non-leaf function cost:
* - calls strlcpy at least once
* - calls fill_pathname_slash()
*
* Deprecated. Use fill_pathname_join_special() instead
* if you can ensure @dir != @out_path
*
* @return Length of the string copied into @out_path
**/
size_t fill_pathname_join(char *out_path, const char *dir,
const char *path, size_t size);
/**
* fill_pathname_join_special:
* @out_path : output path
* @dir : directory. Cannot be identical to @out_path
* @path : path
* @size : size of output path
*
*
* Specialized version of fill_pathname_join.
* Unlike fill_pathname_join(),
* @dir and @out_path CANNOT be identical.
*
* Joins a directory (@dir) and path (@path) together.
* Makes sure not to get two consecutive slashes
* between directory and path.
*
* Hidden non-leaf function cost:
* - calls strlcpy 2x
* - calls find_last_slash()
*
* @return Length of the string copied into @out_path
**/
size_t fill_pathname_join_special(char *out_path,
const char *dir, const char *path, size_t size);
size_t fill_pathname_join_special_ext(char *out_path,
void fill_pathname_join_special_ext(char *out_path,
const char *dir, const char *path,
const char *last, const char *ext,
size_t size);
void fill_pathname_join_concat_noext(
char *out_path,
const char *dir, const char *path,
const char *concat,
size_t size);
void fill_pathname_join_concat(char *out_path,
const char *dir, const char *path,
const char *concat,
size_t size);
void fill_pathname_join_noext(char *out_path,
const char *dir, const char *path, size_t size);
/**
* fill_pathname_join_delim:
* @out_path : output path
@ -521,58 +400,40 @@ size_t fill_pathname_join_special_ext(char *out_path,
*
* Joins a directory (@dir) and path (@path) together
* using the given delimiter (@delim).
*
* Hidden non-leaf function cost:
* - can call strlen
* - can call strlcpy
* - can call strlcat
**/
size_t fill_pathname_join_delim(char *out_path, const char *dir,
void fill_pathname_join_delim(char *out_path, const char *dir,
const char *path, const char delim, size_t size);
size_t fill_pathname_expand_special(char *out_path,
void fill_pathname_join_delim_concat(char *out_path, const char *dir,
const char *path, const char delim, const char *concat,
size_t size);
/**
* fill_short_pathname_representation:
* @out_rep : output representation
* @in_path : input path
* @size : size of output representation
*
* Generates a short representation of path. It should only
* be used for displaying the result; the output representation is not
* binding in any meaningful way (for a normal path, this is the same as basename)
* In case of more complex URLs, this should cut everything except for
* the main image file.
*
* E.g.: "/path/to/game.img" -> game.img
* "/path/to/myarchive.7z#folder/to/game.img" -> game.img
*/
void fill_short_pathname_representation(char* out_rep,
const char *in_path, size_t size);
size_t fill_pathname_abbreviate_special(char *out_path,
void fill_short_pathname_representation_noext(char* out_rep,
const char *in_path, size_t size);
/**
* fill_pathname_abbreviated_or_relative:
*
* Fills the supplied path with either the abbreviated path or
* the relative path, which ever one has less depth / number of slashes
*
* If lengths of abbreviated and relative paths are the same,
* the relative path will be used
* @in_path can be an absolute, relative or abbreviated path
*
* @return Length of the string copied into @out_path
**/
size_t fill_pathname_abbreviated_or_relative(char *out_path,
const char *in_refpath, const char *in_path, size_t size);
void fill_pathname_expand_special(char *out_path,
const char *in_path, size_t size);
/**
* pathname_conform_slashes_to_os:
*
* @path : path
*
* Leaf function.
*
* Changes the slashes to the correct kind for the os
* So forward slash on linux and backslash on Windows
**/
void pathname_conform_slashes_to_os(char *path);
/**
* pathname_make_slashes_portable:
* @path : path
*
* Leaf function.
*
* Change all slashes to forward so they are more
* portable between Windows and Linux
**/
void pathname_make_slashes_portable(char *path);
void fill_pathname_abbreviate_special(char *out_path,
const char *in_path, size_t size);
/**
* path_basedir:
@ -589,12 +450,12 @@ void path_basedir_wrapper(char *path);
*
* Checks if character (@c) is a slash.
*
* @return true if character is a slash, otherwise false.
**/
* Returns: true (1) if character is a slash, otherwise false (0).
*/
#ifdef _WIN32
#define PATH_CHAR_IS_SLASH(c) (((c) == '/') || ((c) == '\\'))
#define path_char_is_slash(c) (((c) == '/') || ((c) == '\\'))
#else
#define PATH_CHAR_IS_SLASH(c) ((c) == '/')
#define path_char_is_slash(c) ((c) == '/')
#endif
/**
@ -602,14 +463,14 @@ void path_basedir_wrapper(char *path);
*
* Gets the default slash separator.
*
* @return default slash separator.
**/
* Returns: default slash separator.
*/
#ifdef _WIN32
#define PATH_DEFAULT_SLASH() "\\"
#define PATH_DEFAULT_SLASH_C() '\\'
#define path_default_slash() "\\"
#define path_default_slash_c() '\\'
#else
#define PATH_DEFAULT_SLASH() "/"
#define PATH_DEFAULT_SLASH_C() '/'
#define path_default_slash() "/"
#define path_default_slash_c() '/'
#endif
/**
@ -619,13 +480,8 @@ void path_basedir_wrapper(char *path);
*
* Assumes path is a directory. Appends a slash
* if not already there.
* Hidden non-leaf function cost:
* - calls find_last_slash()
* - can call strlcat once if it returns false
* - calls strlen
**/
size_t fill_pathname_slash(char *path, size_t size);
void fill_pathname_slash(char *path, size_t size);
#if !defined(RARCH_CONSOLE) && defined(RARCH_INTERNAL)
void fill_pathname_application_path(char *buf, size_t size);
@ -639,16 +495,7 @@ void fill_pathname_home_dir(char *buf, size_t size);
*
* Create directory on filesystem.
*
* Recursive function.
*
* Hidden non-leaf function cost:
* - Calls strdup
* - Calls path_parent_dir()
* - Calls strcmp
* - Calls path_is_directory()
* - Calls path_mkdir()
*
* @return true if directory could be created, otherwise false.
* Returns: true (1) if directory could be created, otherwise false (0).
**/
bool path_mkdir(const char *dir);
@ -658,15 +505,10 @@ bool path_mkdir(const char *dir);
*
* Checks if path is a directory.
*
* @return true if path is a directory, otherwise false.
* Returns: true (1) if path is a directory, otherwise false (0).
*/
bool path_is_directory(const char *path);
/* Time format strings with AM-PM designation require special
* handling due to platform dependence */
void strftime_am_pm(char *s, size_t len, const char* format,
const void* timeptr);
bool path_is_character_special(const char *path);
int path_stat(const char *path);

View File

@ -291,7 +291,6 @@ 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) */
@ -929,6 +928,8 @@ enum retro_mod
* anything else.
* It is recommended to expose all relevant pointers through
* retro_get_memory_* as well.
*
* Can be called from retro_init and retro_load_game.
*/
#define RETRO_ENVIRONMENT_SET_GEOMETRY 37
/* const struct retro_game_geometry * --
@ -1766,90 +1767,6 @@ enum retro_mod
* (see enum retro_savestate_context)
*/
#define RETRO_ENVIRONMENT_GET_HW_RENDER_CONTEXT_NEGOTIATION_INTERFACE_SUPPORT (73 | RETRO_ENVIRONMENT_EXPERIMENTAL)
/* struct retro_hw_render_context_negotiation_interface * --
* Before calling SET_HW_RNEDER_CONTEXT_NEGOTIATION_INTERFACE, a core can query
* which version of the interface is supported.
*
* Frontend looks at interface_type and returns the maximum supported
* context negotiation interface version.
* If the interface_type is not supported or recognized by the frontend, a version of 0
* must be returned in interface_version and true is returned by frontend.
*
* If this environment call returns true with interface_version greater than 0,
* a core can always use a negotiation interface version larger than what the frontend returns, but only
* earlier versions of the interface will be used by the frontend.
* A frontend must not reject a negotiation interface version that is larger than
* what the frontend supports. Instead, the frontend will use the older entry points that it recognizes.
* If this is incompatible with a particular core's requirements, it can error out early.
*
* Backwards compatibility note:
* This environment call was introduced after Vulkan v1 context negotiation.
* If this environment call is not supported by frontend - i.e. the environment call returns false -
* only Vulkan v1 context negotiation is supported (if Vulkan HW rendering is supported at all).
* If a core uses Vulkan negotiation interface with version > 1, negotiation may fail unexpectedly.
* All future updates to the context negotiation interface implies that frontend must support
* this environment call to query support.
*/
#define RETRO_ENVIRONMENT_GET_JIT_CAPABLE 74
/* bool * --
* Result is set to true if the frontend has already verified JIT can be
* used, mainly for use iOS/tvOS. On other platforms the result is true.
*/
#define RETRO_ENVIRONMENT_GET_MICROPHONE_INTERFACE (75 | RETRO_ENVIRONMENT_EXPERIMENTAL)
/* struct retro_microphone_interface * --
* Returns an interface that can be used to receive input from the microphone driver.
*
* Returns true if microphone support is available,
* even if no microphones are plugged in.
* Returns false if mic support is disabled or unavailable.
*
* This callback can be invoked at any time,
* even before the microphone driver is ready.
*/
#define RETRO_ENVIRONMENT_SET_NETPACKET_INTERFACE 76
/* const struct retro_netpacket_callback * --
* When set, a core gains control over network packets sent and
* received during a multiplayer session. This can be used to
* emulate multiplayer games that were originally played on two
* or more separate consoles or computers connected together.
*
* The frontend will take care of connecting players together,
* and the core only needs to send the actual data as needed for
* the emulation, while handshake and connection management happen
* in the background.
*
* When two or more players are connected and this interface has
* been set, time manipulation features (such as pausing, slow motion,
* fast forward, rewinding, save state loading, etc.) are disabled to
* avoid interrupting communication.
*
* Should be set in either retro_init or retro_load_game, but not both.
*
* When not set, a frontend may use state serialization-based
* multiplayer, where a deterministic core supporting multiple
* input devices does not need to take any action on its own.
*/
#define RETRO_ENVIRONMENT_GET_DEVICE_POWER (77 | RETRO_ENVIRONMENT_EXPERIMENTAL)
/* struct retro_device_power * --
* Returns the device's current power state as reported by the frontend.
* This is useful for emulating the battery level in handheld consoles,
* or for reducing power consumption when on battery power.
*
* The return value indicates whether the frontend can provide this information,
* even if the parameter is NULL.
*
* If the frontend does not support this functionality,
* then the provided argument will remain unchanged.
*
* Note that this environment call describes the power state for the entire device,
* not for individual peripherals like controllers.
*/
/* VFS functionality */
/* File paths:
@ -2024,13 +1941,13 @@ struct retro_vfs_interface_info
enum retro_hw_render_interface_type
{
RETRO_HW_RENDER_INTERFACE_VULKAN = 0,
RETRO_HW_RENDER_INTERFACE_D3D9 = 1,
RETRO_HW_RENDER_INTERFACE_D3D10 = 2,
RETRO_HW_RENDER_INTERFACE_D3D11 = 3,
RETRO_HW_RENDER_INTERFACE_D3D12 = 4,
RETRO_HW_RENDER_INTERFACE_VULKAN = 0,
RETRO_HW_RENDER_INTERFACE_D3D9 = 1,
RETRO_HW_RENDER_INTERFACE_D3D10 = 2,
RETRO_HW_RENDER_INTERFACE_D3D11 = 3,
RETRO_HW_RENDER_INTERFACE_D3D12 = 4,
RETRO_HW_RENDER_INTERFACE_GSKIT_PS2 = 5,
RETRO_HW_RENDER_INTERFACE_DUMMY = INT_MAX
RETRO_HW_RENDER_INTERFACE_DUMMY = INT_MAX
};
/* Base struct. All retro_hw_render_interface_* types
@ -2806,17 +2723,9 @@ enum retro_hw_context_type
/* Vulkan, see RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE. */
RETRO_HW_CONTEXT_VULKAN = 6,
/* Direct3D11, see RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE */
RETRO_HW_CONTEXT_D3D11 = 7,
/* Direct3D10, see RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE */
RETRO_HW_CONTEXT_D3D10 = 8,
/* Direct3D12, see RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE */
RETRO_HW_CONTEXT_D3D12 = 9,
/* Direct3D9, see RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE */
RETRO_HW_CONTEXT_D3D9 = 10,
/* Direct3D, set version_major to select the type of interface
* returned by RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE */
RETRO_HW_CONTEXT_DIRECT3D = 7,
RETRO_HW_CONTEXT_DUMMY = INT_MAX
};
@ -3071,100 +2980,6 @@ struct retro_disk_control_ext_callback
retro_get_image_label_t get_image_label; /* Optional - may be NULL */
};
/* Definitions for RETRO_ENVIRONMENT_SET_NETPACKET_INTERFACE.
* A core can set it if sending and receiving custom network packets
* during a multiplayer session is desired.
*/
/* Netpacket flags for retro_netpacket_send_t */
#define RETRO_NETPACKET_UNRELIABLE 0 /* Packet to be sent unreliable, depending on network quality it might not arrive. */
#define RETRO_NETPACKET_RELIABLE (1 << 0) /* Reliable packets are guaranteed to arrive at the target in the order they were send. */
#define RETRO_NETPACKET_UNSEQUENCED (1 << 1) /* Packet will not be sequenced with other packets and may arrive out of order. Cannot be set on reliable packets. */
/* Used by the core to send a packet to one or more connected players.
* A single packet sent via this interface can contain up to 64 KB of data.
*
* The broadcast flag can be set to true to send to multiple connected clients.
* In a broadcast, the client_id argument indicates 1 client NOT to send the
* packet to (pass 0xFFFF to send to everyone). Otherwise, the client_id
* argument indicates a single client to send the packet to.
*
* A frontend must support sending reliable packets (RETRO_NETPACKET_RELIABLE).
* Unreliable packets might not be supported by the frontend, but the flags can
* still be specified. Reliable transmission will be used instead.
*
* If this function is called passing NULL for buf, it will instead flush all
* previously buffered outgoing packets and instantly read any incoming packets.
* During such a call, retro_netpacket_receive_t and retro_netpacket_stop_t can
* be called. The core can perform this in a loop to do a blocking read, i.e.,
* wait for incoming data, but needs to handle stop getting called and also
* give up after a short while to avoid freezing on a connection problem.
*
* This function is not guaranteed to be thread-safe and must be called during
* retro_run or any of the netpacket callbacks passed with this interface.
*/
typedef void (RETRO_CALLCONV *retro_netpacket_send_t)(int flags, const void* buf, size_t len, uint16_t client_id, bool broadcast);
/* Called by the frontend to signify that a multiplayer session has started.
* If client_id is 0 the local player is the host of the session and at this
* point no other player has connected yet.
*
* If client_id is > 0 the local player is a client connected to a host and
* at this point is already fully connected to the host.
*
* The core must store the retro_netpacket_send_t function pointer provided
* here and use it whenever it wants to send a packet. This function pointer
* remains valid until the frontend calls retro_netpacket_stop_t.
*/
typedef void (RETRO_CALLCONV *retro_netpacket_start_t)(uint16_t client_id, retro_netpacket_send_t send_fn);
/* Called by the frontend when a new packet arrives which has been sent from
* another player with retro_netpacket_send_t. The client_id argument indicates
* who has sent the packet.
*/
typedef void (RETRO_CALLCONV *retro_netpacket_receive_t)(const void* buf, size_t len, uint16_t client_id);
/* Called by the frontend when the multiplayer session has ended.
* Once this gets called the retro_netpacket_send_t function pointer passed
* to retro_netpacket_start_t will not be valid anymore.
*/
typedef void (RETRO_CALLCONV *retro_netpacket_stop_t)(void);
/* Called by the frontend every frame (between calls to retro_run while
* updating the state of the multiplayer session.
* This is a good place for the core to call retro_netpacket_send_t from.
*/
typedef void (RETRO_CALLCONV *retro_netpacket_poll_t)(void);
/* Called by the frontend when a new player connects to the hosted session.
* This is only called on the host side, not for clients connected to the host.
* If this function returns false, the newly connected player gets dropped.
* This can be used for example to limit the number of players.
*/
typedef bool (RETRO_CALLCONV *retro_netpacket_connected_t)(uint16_t client_id);
/* Called by the frontend when a player leaves or disconnects from the hosted session.
* This is only called on the host side, not for clients connected to the host.
*/
typedef void (RETRO_CALLCONV *retro_netpacket_disconnected_t)(uint16_t client_id);
/**
* A callback interface for giving a core the ability to send and receive custom
* network packets during a multiplayer session between two or more instances
* of a libretro frontend.
*
* @see RETRO_ENVIRONMENT_SET_NETPACKET_INTERFACE
*/
struct retro_netpacket_callback
{
retro_netpacket_start_t start;
retro_netpacket_receive_t receive;
retro_netpacket_stop_t stop; /* Optional - may be NULL */
retro_netpacket_poll_t poll; /* Optional - may be NULL */
retro_netpacket_connected_t connected; /* Optional - may be NULL */
retro_netpacket_disconnected_t disconnected; /* Optional - may be NULL */
};
enum retro_pixel_format
{
/* 0RGB1555, native endian.
@ -3967,289 +3782,6 @@ struct retro_throttle_state
float rate;
};
/**
* Opaque handle to a microphone that's been opened for use.
* The underlying object is accessed or created with \c retro_microphone_interface_t.
*/
typedef struct retro_microphone retro_microphone_t;
/**
* Parameters for configuring a microphone.
* Some of these might not be honored,
* depending on the available hardware and driver configuration.
*/
typedef struct retro_microphone_params
{
/**
* The desired sample rate of the microphone's input, in Hz.
* The microphone's input will be resampled,
* so cores can ask for whichever frequency they need.
*
* If zero, some reasonable default will be provided by the frontend
* (usually from its config file).
*
* @see retro_get_mic_rate_t
*/
unsigned rate;
} retro_microphone_params_t;
/**
* @copydoc retro_microphone_interface::open_mic
*/
typedef retro_microphone_t *(RETRO_CALLCONV *retro_open_mic_t)(const retro_microphone_params_t *params);
/**
* @copydoc retro_microphone_interface::close_mic
*/
typedef void (RETRO_CALLCONV *retro_close_mic_t)(retro_microphone_t *microphone);
/**
* @copydoc retro_microphone_interface::get_params
*/
typedef bool (RETRO_CALLCONV *retro_get_mic_params_t)(const retro_microphone_t *microphone, retro_microphone_params_t *params);
/**
* @copydoc retro_microphone_interface::set_mic_state
*/
typedef bool (RETRO_CALLCONV *retro_set_mic_state_t)(retro_microphone_t *microphone, bool state);
/**
* @copydoc retro_microphone_interface::get_mic_state
*/
typedef bool (RETRO_CALLCONV *retro_get_mic_state_t)(const retro_microphone_t *microphone);
/**
* @copydoc retro_microphone_interface::read_mic
*/
typedef int (RETRO_CALLCONV *retro_read_mic_t)(retro_microphone_t *microphone, int16_t* samples, size_t num_samples);
/**
* The current version of the microphone interface.
* Will be incremented whenever \c retro_microphone_interface or \c retro_microphone_params_t
* receive new fields.
*
* Frontends using cores built against older mic interface versions
* should not access fields introduced in newer versions.
*/
#define RETRO_MICROPHONE_INTERFACE_VERSION 1
/**
* An interface for querying the microphone and accessing data read from it.
*
* @see RETRO_ENVIRONMENT_GET_MICROPHONE_INTERFACE
*/
struct retro_microphone_interface
{
/**
* The version of this microphone interface.
* Set by the core to request a particular version,
* and set by the frontend to indicate the returned version.
* 0 indicates that the interface is invalid or uninitialized.
*/
unsigned interface_version;
/**
* Initializes a new microphone.
* Assuming that microphone support is enabled and provided by the frontend,
* cores may call this function whenever necessary.
* A microphone could be opened throughout a core's lifetime,
* or it could wait until a microphone is plugged in to the emulated device.
*
* The returned handle will be valid until it's freed,
* even if the audio driver is reinitialized.
*
* This function is not guaranteed to be thread-safe.
*
* @param args[in] Parameters used to create the microphone.
* May be \c NULL, in which case the default value of each parameter will be used.
*
* @returns Pointer to the newly-opened microphone,
* or \c NULL if one couldn't be opened.
* This likely means that no microphone is plugged in and recognized,
* or the maximum number of supported microphones has been reached.
*
* @note Microphones are \em inactive by default;
* to begin capturing audio, call \c set_mic_state.
* @see retro_microphone_params_t
*/
retro_open_mic_t open_mic;
/**
* Closes a microphone that was initialized with \c open_mic.
* Calling this function will stop all microphone activity
* and free up the resources that it allocated.
* Afterwards, the handle is invalid and must not be used.
*
* A frontend may close opened microphones when unloading content,
* but this behavior is not guaranteed.
* Cores should close their microphones when exiting, just to be safe.
*
* @param microphone Pointer to the microphone that was allocated by \c open_mic.
* If \c NULL, this function does nothing.
*
* @note The handle might be reused if another microphone is opened later.
*/
retro_close_mic_t close_mic;
/**
* Returns the configured parameters of this microphone.
* These may differ from what was requested depending on
* the driver and device configuration.
*
* Cores should check these values before they start fetching samples.
*
* Will not change after the mic was opened.
*
* @param microphone[in] Opaque handle to the microphone
* whose parameters will be retrieved.
* @param params[out] The parameters object that the
* microphone's parameters will be copied to.
*
* @return \c true if the parameters were retrieved,
* \c false if there was an error.
*/
retro_get_mic_params_t get_params;
/**
* Enables or disables the given microphone.
* Microphones are disabled by default
* and must be explicitly enabled before they can be used.
* Disabled microphones will not process incoming audio samples,
* and will therefore have minimal impact on overall performance.
* Cores may enable microphones throughout their lifetime,
* or only for periods where they're needed.
*
* Cores that accept microphone input should be able to operate without it;
* we suggest substituting silence in this case.
*
* @param microphone Opaque handle to the microphone
* whose state will be adjusted.
* This will have been provided by \c open_mic.
* @param state \c true if the microphone should receive audio input,
* \c false if it should be idle.
* @returns \c true if the microphone's state was successfully set,
* \c false if \c microphone is invalid
* or if there was an error.
*/
retro_set_mic_state_t set_mic_state;
/**
* Queries the active state of a microphone at the given index.
* Will return whether the microphone is enabled,
* even if the driver is paused.
*
* @param microphone Opaque handle to the microphone
* whose state will be queried.
* @return \c true if the provided \c microphone is valid and active,
* \c false if not or if there was an error.
*/
retro_get_mic_state_t get_mic_state;
/**
* Retrieves the input processed by the microphone since the last call.
* \em Must be called every frame unless \c microphone is disabled,
* similar to how \c retro_audio_sample_batch_t works.
*
* @param[in] microphone Opaque handle to the microphone
* whose recent input will be retrieved.
* @param[out] samples The buffer that will be used to store the microphone's data.
* Microphone input is in mono (i.e. one number per sample).
* Should be large enough to accommodate the expected number of samples per frame;
* for example, a 44.1kHz sample rate at 60 FPS would require space for 735 samples.
* @param[in] num_samples The size of the data buffer in samples (\em not bytes).
* Microphone input is in mono, so a "frame" and a "sample" are equivalent in length here.
*
* @return The number of samples that were copied into \c samples.
* If \c microphone is pending driver initialization,
* this function will copy silence of the requested length into \c samples.
*
* Will return -1 if the microphone is disabled,
* the audio driver is paused,
* or there was an error.
*/
retro_read_mic_t read_mic;
};
/**
* Describes how a device is being powered.
* @see RETRO_ENVIRONMENT_GET_DEVICE_POWER
*/
enum retro_power_state
{
/**
* Indicates that the frontend cannot report its power state at this time,
* most likely due to a lack of support.
*
* \c RETRO_ENVIRONMENT_GET_DEVICE_POWER will not return this value;
* instead, the environment callback will return \c false.
*/
RETRO_POWERSTATE_UNKNOWN = 0,
/**
* Indicates that the device is running on its battery.
* Usually applies to portable devices such as handhelds, laptops, and smartphones.
*/
RETRO_POWERSTATE_DISCHARGING,
/**
* Indicates that the device's battery is currently charging.
*/
RETRO_POWERSTATE_CHARGING,
/**
* Indicates that the device is connected to a power source
* and that its battery has finished charging.
*/
RETRO_POWERSTATE_CHARGED,
/**
* Indicates that the device is connected to a power source
* and that it does not have a battery.
* This usually suggests a desktop computer or a non-portable game console.
*/
RETRO_POWERSTATE_PLUGGED_IN
};
/**
* Indicates that an estimate is not available for the battery level or time remaining,
* even if the actual power state is known.
*/
#define RETRO_POWERSTATE_NO_ESTIMATE (-1)
/**
* Describes the power state of the device running the frontend.
* @see RETRO_ENVIRONMENT_GET_DEVICE_POWER
*/
struct retro_device_power
{
/**
* The current state of the frontend's power usage.
*/
enum retro_power_state state;
/**
* A rough estimate of the amount of time remaining (in seconds)
* before the device powers off.
* This value depends on a variety of factors,
* so it is not guaranteed to be accurate.
*
* Will be set to \c RETRO_POWERSTATE_NO_ESTIMATE if \c state does not equal \c RETRO_POWERSTATE_DISCHARGING.
* May still be set to \c RETRO_POWERSTATE_NO_ESTIMATE if the frontend is unable to provide an estimate.
*/
int seconds;
/**
* The approximate percentage of battery charge,
* ranging from 0 to 100 (inclusive).
* The device may power off before this reaches 0.
*
* The user might have configured their device
* to stop charging before the battery is full,
* so do not assume that this will be 100 in the \c RETRO_POWERSTATE_CHARGED state.
*/
int8_t percent;
};
/* Callbacks */
/* Environment callback. Gives implementations a way of performing

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (dir_list.h).
@ -24,7 +24,6 @@
#define __LIBRETRO_SDK_DIR_LIST_H
#include <retro_common_api.h>
#include <boolean.h>
#include <lists/string_list.h>
@ -42,7 +41,7 @@ RETRO_BEGIN_DECLS
*
* Create a directory listing, appending to an existing list
*
* @return Returns true on success, otherwise false.
* Returns: true success, false in case of error.
**/
bool dir_list_append(struct string_list *list, const char *dir, const char *ext,
bool include_dirs, bool include_hidden, bool include_compressed, bool recursive);
@ -58,52 +57,31 @@ bool dir_list_append(struct string_list *list, const char *dir, const char *ext,
*
* Create a directory listing.
*
* @return pointer to a directory listing of type 'struct string_list *' on success,
* Returns: pointer to a directory listing of type 'struct string_list *' on success,
* NULL in case of error. Has to be freed manually.
**/
struct string_list *dir_list_new(const char *dir, const char *ext,
bool include_dirs, bool include_hidden, bool include_compressed, bool recursive);
/**
* dir_list_initialize:
*
* NOTE: @list must zero initialised before
* calling this function, otherwise UB.
**/
bool dir_list_initialize(struct string_list *list,
const char *dir,
const char *ext, bool include_dirs,
bool include_hidden, bool include_compressed,
bool recursive);
/**
* dir_list_sort:
* @list : pointer to the directory listing.
* @dir_first : move the directories in the listing to the top?
*
* Sorts a directory listing.
*
**/
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
*
* Frees a directory listing.
*
**/
void dir_list_free(struct string_list *list);
bool dir_list_deinitialize(struct string_list *list);
RETRO_END_DECLS
#endif

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (string_list.h).
@ -41,7 +41,6 @@ union string_list_elem_attr
struct string_list_elem
{
char *data;
void *userdata;
union string_list_elem_attr attr;
};
@ -59,7 +58,7 @@ struct string_list
*
* Searches for an element (@elem) inside the string list.
*
* @return Number of elements found, otherwise 0.
* Returns: true (1) if element could be found, otherwise false (0).
*/
int string_list_find_elem(const struct string_list *list, const char *elem);
@ -88,36 +87,13 @@ bool string_list_find_elem_prefix(const struct string_list *list,
*/
struct string_list *string_split(const char *str, const char *delim);
bool string_split_noalloc(struct string_list *list,
const char *str, const char *delim);
/**
* string_separate:
* @str : string to turn into a string list
* @delim : delimiter character to use for separating the string.
*
* Creates a new string list based on string @str, delimited by @delim.
* Includes empty strings - i.e. two adjacent delimiters will resolve
* to a string list element of "".
*
* @return New string list if successful, otherwise NULL.
**/
struct string_list *string_separate(char *str, const char *delim);
bool string_separate_noalloc(struct string_list *list,
char *str, const char *delim);
bool string_list_deinitialize(struct string_list *list);
bool string_list_initialize(struct string_list *list);
/**
* string_list_new:
*
* Creates a new string list. Has to be freed manually.
*
* @return New string list if successful, otherwise NULL.
**/
* Returns: new string list if successful, otherwise NULL.
*/
struct string_list *string_list_new(void);
/**
@ -127,12 +103,8 @@ struct string_list *string_list_new(void);
* @attr : attributes of new element.
*
* Appends a new element to the string list.
* Hidden non-leaf function cost:
* - Calls string_list_capacity()
* - Calls strdup
*
* @return true if successful, otherwise false.
* Returns: true (1) if successful, otherwise false (0).
**/
bool string_list_append(struct string_list *list, const char *elem,
union string_list_elem_attr attr);
@ -146,12 +118,7 @@ bool string_list_append(struct string_list *list, const char *elem,
*
* Appends a new element to the string list.
*
* Hidden non-leaf function cost:
* - Calls string_list_capacity()
* - Calls malloc
* - Calls strlcpy
*
* @return true if successful, otherwise false.
* Returns: true (1) if successful, otherwise false (0).
**/
bool string_list_append_n(struct string_list *list, const char *elem,
unsigned length, union string_list_elem_attr attr);
@ -161,7 +128,7 @@ bool string_list_append_n(struct string_list *list, const char *elem,
* @list : pointer to string list object
*
* Frees a string list.
**/
*/
void string_list_free(struct string_list *list);
/**
@ -173,13 +140,7 @@ void string_list_free(struct string_list *list);
*
* A string list will be joined/concatenated as a
* string to @buffer, delimited by @delim.
*
* NOTE: @buffer must be NULL-terminated.
*
* Hidden non-leaf function cost:
* - Calls strlen_size()
* - Calls strlcat x times in a loop
**/
*/
void string_list_join_concat(char *buffer, size_t size,
const struct string_list *list, const char *sep);
@ -190,10 +151,6 @@ void string_list_join_concat(char *buffer, size_t size,
* @str : value for the element.
*
* Set value of element inside string list.
*
* Hidden non-leaf function cost:
* - Calls free
* - Calls strdup
**/
void string_list_set(struct string_list *list, unsigned idx,
const char *str);

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (memalign.h).

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (memmap.h).
@ -26,7 +26,7 @@
#include <stdio.h>
#include <stdint.h>
#if defined(PSP) || defined(PS2) || defined(GEKKO) || defined(VITA) || defined(_XBOX) || defined(_3DS) || defined(WIIU) || defined(SWITCH) || defined(HAVE_LIBNX) || defined(__PS3__) || defined(__PSL1GHT__)
#if defined(PSP) || defined(GEKKO) || defined(VITA) || defined(_XBOX) || defined(_3DS) || defined(WIIU) || defined(SWITCH)
/* No mman available */
#elif defined(_WIN32) && !defined(_XBOX)
#include <windows.h>

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_assert.h).
@ -27,7 +27,9 @@
#ifdef RARCH_INTERNAL
#include <stdio.h>
#define retro_assert(cond) ((void)( (cond) || (printf("Assertion failed at %s:%d.\n", __FILE__, __LINE__), abort(), 0) ))
#define retro_assert(cond) do { \
if (!(cond)) { printf("Assertion failed at %s:%d.\n", __FILE__, __LINE__); abort(); } \
} while(0)
#else
#define retro_assert(cond) assert(cond)
#endif

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_common.h).
@ -34,3 +34,4 @@ in a public API, you may need this.
#include <compat/msvc.h>
#endif

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_common_api.h).
@ -89,9 +89,7 @@ typedef int ssize_t;
/* C++11 says this one isn't needed, but apparently (some versions of) mingw require it anyways */
/* https://stackoverflow.com/questions/8132399/how-to-printf-uint64-t-fails-with-spurious-trailing-in-format */
/* https://github.com/libretro/RetroArch/issues/6009 */
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS 1
#endif
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#endif
#ifndef PRId64
@ -101,26 +99,6 @@ typedef int ssize_t;
#define STRING_REP_UINT64 "%" PRIu64
#define STRING_REP_USIZE "%" PRIuPTR
/* Wrap a declaration in RETRO_DEPRECATED() to produce a compiler warning when
it's used. This is intended for developer machines, so it won't work on ancient
or obscure compilers */
#if defined(_MSC_VER)
#if _MSC_VER >= 1400 /* Visual C 2005 or later */
#define RETRO_DEPRECATED(decl) __declspec(deprecated) decl
#endif
#elif defined(__GNUC__)
#if __GNUC__ >= 3 /* GCC 3 or later */
#define RETRO_DEPRECATED(decl) decl __attribute__((deprecated))
#endif
#elif defined(__clang__)
#if __clang_major__ >= 3 /* clang 3 or later */
#define RETRO_DEPRECATED(decl) decl __attribute__((deprecated))
#endif
#endif
#ifndef RETRO_DEPRECATED /* Unsupported compilers */
#define RETRO_DEPRECATED(decl) decl
#endif
/*
I would like to see retro_inline.h moved in here; possibly boolean too.
@ -135,5 +113,6 @@ Of course, another school of thought is that you should do as little damage as p
in as few places as possible...
*/
/* _LIBRETRO_COMMON_RETRO_COMMON_API_H */
#endif

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2019 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_dirent.h).
@ -25,6 +25,7 @@
#include <libretro.h>
#include <retro_common_api.h>
#include <retro_miscellaneous.h>
#include <boolean.h>

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_endianness.h).
@ -31,98 +31,40 @@
#define SWAP16 _byteswap_ushort
#define SWAP32 _byteswap_ulong
#else
static INLINE uint16_t SWAP16(uint16_t x)
{
return ((x & 0x00ff) << 8) |
((x & 0xff00) >> 8);
}
static INLINE uint32_t SWAP32(uint32_t x)
{
return ((x & 0x000000ff) << 24) |
((x & 0x0000ff00) << 8) |
((x & 0x00ff0000) >> 8) |
((x & 0xff000000) >> 24);
}
#define SWAP16(x) ((uint16_t)( \
(((uint16_t)(x) & 0x00ff) << 8) | \
(((uint16_t)(x) & 0xff00) >> 8) \
))
#define SWAP32(x) ((uint32_t)( \
(((uint32_t)(x) & 0x000000ff) << 24) | \
(((uint32_t)(x) & 0x0000ff00) << 8) | \
(((uint32_t)(x) & 0x00ff0000) >> 8) | \
(((uint32_t)(x) & 0xff000000) >> 24) \
))
#endif
#if defined(_MSC_VER) && _MSC_VER <= 1200
static INLINE uint64_t SWAP64(uint64_t val)
{
return
((val & 0x00000000000000ff) << 56)
| ((val & 0x000000000000ff00) << 40)
| ((val & 0x0000000000ff0000) << 24)
| ((val & 0x00000000ff000000) << 8)
| ((val & 0x000000ff00000000) >> 8)
| ((val & 0x0000ff0000000000) >> 24)
| ((val & 0x00ff000000000000) >> 40)
| ((val & 0xff00000000000000) >> 56);
}
#define SWAP64(val) \
((((uint64_t)(val) & 0x00000000000000ff) << 56) \
| (((uint64_t)(val) & 0x000000000000ff00) << 40) \
| (((uint64_t)(val) & 0x0000000000ff0000) << 24) \
| (((uint64_t)(val) & 0x00000000ff000000) << 8) \
| (((uint64_t)(val) & 0x000000ff00000000) >> 8) \
| (((uint64_t)(val) & 0x0000ff0000000000) >> 24) \
| (((uint64_t)(val) & 0x00ff000000000000) >> 40) \
| (((uint64_t)(val) & 0xff00000000000000) >> 56))
#else
static INLINE uint64_t SWAP64(uint64_t val)
{
return ((val & 0x00000000000000ffULL) << 56)
| ((val & 0x000000000000ff00ULL) << 40)
| ((val & 0x0000000000ff0000ULL) << 24)
| ((val & 0x00000000ff000000ULL) << 8)
| ((val & 0x000000ff00000000ULL) >> 8)
| ((val & 0x0000ff0000000000ULL) >> 24)
| ((val & 0x00ff000000000000ULL) >> 40)
| ((val & 0xff00000000000000ULL) >> 56);
}
#define SWAP64(val) \
((((uint64_t)(val) & 0x00000000000000ffULL) << 56) \
| (((uint64_t)(val) & 0x000000000000ff00ULL) << 40) \
| (((uint64_t)(val) & 0x0000000000ff0000ULL) << 24) \
| (((uint64_t)(val) & 0x00000000ff000000ULL) << 8) \
| (((uint64_t)(val) & 0x000000ff00000000ULL) >> 8) \
| (((uint64_t)(val) & 0x0000ff0000000000ULL) >> 24) \
| (((uint64_t)(val) & 0x00ff000000000000ULL) >> 40) \
| (((uint64_t)(val) & 0xff00000000000000ULL) >> 56))
#endif
#ifdef _MSC_VER
/* MSVC pre-defines macros depending on target arch */
#if defined (_M_IX86) || defined (_M_AMD64) || defined (_M_ARM) || defined (_M_ARM64)
#ifndef LSB_FIRST
#define LSB_FIRST 1
#endif
#elif _M_PPC
#ifndef MSB_FIRST
#define MSB_FIRST 1
#endif
#else
/* MSVC can run on _M_ALPHA and _M_IA64 too, but they're both bi-endian; need to find what mode MSVC runs them at */
#error "unknown platform, can't determine endianness"
#endif
#else
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#ifndef MSB_FIRST
#define MSB_FIRST 1
#endif
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#ifndef LSB_FIRST
#define LSB_FIRST 1
#endif
#else
#error "Invalid endianness macros"
#endif
#endif
#if defined(MSB_FIRST) && defined(LSB_FIRST)
# error "Bug in LSB_FIRST/MSB_FIRST definition"
#endif
#if !defined(MSB_FIRST) && !defined(LSB_FIRST)
# error "Bug in LSB_FIRST/MSB_FIRST definition"
#endif
#ifdef MSB_FIRST
# define RETRO_IS_BIG_ENDIAN 1
# define RETRO_IS_LITTLE_ENDIAN 0
/* For compatibility */
# define WORDS_BIGENDIAN 1
#else
# define RETRO_IS_BIG_ENDIAN 0
# define RETRO_IS_LITTLE_ENDIAN 1
/* For compatibility */
# undef WORDS_BIGENDIAN
#endif
/**
* is_little_endian:
*
@ -131,7 +73,23 @@ static INLINE uint64_t SWAP64(uint64_t val)
* Returns: greater than 0 if little-endian,
* otherwise big-endian.
**/
#define is_little_endian() RETRO_IS_LITTLE_ENDIAN
#if defined(MSB_FIRST)
#define is_little_endian() (0)
#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
#define is_little_endian() (1)
#else
INLINE uint8_t is_little_endian(void)
{
union
{
uint16_t x;
uint8_t y[2];
} u;
u.x = 1;
return u.y[0];
}
#endif
/**
* swap_if_big64:
@ -143,10 +101,17 @@ static INLINE uint64_t SWAP64(uint64_t val)
* otherwise returns same value.
**/
#if RETRO_IS_BIG_ENDIAN
#if defined(MSB_FIRST)
#define swap_if_big64(val) (SWAP64(val))
#elif RETRO_IS_LITTLE_ENDIAN
#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
#define swap_if_big64(val) (val)
#else
INLINE uint64_t swap_if_big64(uint64_t val)
{
if (is_little_endian())
return val;
return SWAP64(val);
}
#endif
/**
@ -159,10 +124,17 @@ static INLINE uint64_t SWAP64(uint64_t val)
* otherwise returns same value.
**/
#if RETRO_IS_BIG_ENDIAN
#if defined(MSB_FIRST)
#define swap_if_big32(val) (SWAP32(val))
#elif RETRO_IS_LITTLE_ENDIAN
#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
#define swap_if_big32(val) (val)
#else
INLINE uint32_t swap_if_big32(uint32_t val)
{
if (is_little_endian())
return val;
return SWAP32(val);
}
#endif
/**
@ -175,10 +147,17 @@ static INLINE uint64_t SWAP64(uint64_t val)
* otherwise returns same value.
**/
#if RETRO_IS_BIG_ENDIAN
#if defined(MSB_FIRST)
#define swap_if_little64(val) (val)
#elif RETRO_IS_LITTLE_ENDIAN
#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
#define swap_if_little64(val) (SWAP64(val))
#else
INLINE uint64_t swap_if_little64(uint64_t val)
{
if (is_little_endian())
return SWAP64(val);
return val;
}
#endif
/**
@ -191,10 +170,17 @@ static INLINE uint64_t SWAP64(uint64_t val)
* otherwise returns same value.
**/
#if RETRO_IS_BIG_ENDIAN
#if defined(MSB_FIRST)
#define swap_if_little32(val) (val)
#elif RETRO_IS_LITTLE_ENDIAN
#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
#define swap_if_little32(val) (SWAP32(val))
#else
INLINE uint32_t swap_if_little32(uint32_t val)
{
if (is_little_endian())
return SWAP32(val);
return val;
}
#endif
/**
@ -207,10 +193,17 @@ static INLINE uint64_t SWAP64(uint64_t val)
* otherwise returns same value.
**/
#if RETRO_IS_BIG_ENDIAN
#if defined(MSB_FIRST)
#define swap_if_big16(val) (SWAP16(val))
#elif RETRO_IS_LITTLE_ENDIAN
#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
#define swap_if_big16(val) (val)
#else
INLINE uint16_t swap_if_big16(uint16_t val)
{
if (is_little_endian())
return val;
return SWAP16(val);
}
#endif
/**
@ -223,10 +216,17 @@ static INLINE uint64_t SWAP64(uint64_t val)
* otherwise returns same value.
**/
#if RETRO_IS_BIG_ENDIAN
#if defined(MSB_FIRST)
#define swap_if_little16(val) (val)
#elif RETRO_IS_LITTLE_ENDIAN
#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
#define swap_if_little16(val) (SWAP16(val))
#else
INLINE uint16_t swap_if_little16(uint16_t val)
{
if (is_little_endian())
return SWAP16(val);
return val;
}
#endif
/**
@ -237,7 +237,7 @@ static INLINE uint64_t SWAP64(uint64_t val)
* Write data to address. Endian-safe. Byteswaps the data
* first if necessary before storing it.
**/
static INLINE void store32be(uint32_t *addr, uint32_t data)
INLINE void store32be(uint32_t *addr, uint32_t data)
{
*addr = swap_if_little32(data);
}
@ -250,331 +250,9 @@ static INLINE void store32be(uint32_t *addr, uint32_t data)
*
* Returns: value from address, byte-swapped if necessary.
**/
static INLINE uint32_t load32be(const uint32_t *addr)
INLINE uint32_t load32be(const uint32_t *addr)
{
return swap_if_little32(*addr);
}
/**
* retro_cpu_to_le16:
* @val : unsigned 16-bit value
*
* Convert unsigned 16-bit value from system to little-endian.
*
* Returns: Little-endian representation of val.
**/
#define retro_cpu_to_le16(val) swap_if_big16(val)
/**
* retro_cpu_to_le32:
* @val : unsigned 32-bit value
*
* Convert unsigned 32-bit value from system to little-endian.
*
* Returns: Little-endian representation of val.
**/
#define retro_cpu_to_le32(val) swap_if_big32(val)
/**
* retro_cpu_to_le64:
* @val : unsigned 64-bit value
*
* Convert unsigned 64-bit value from system to little-endian.
*
* Returns: Little-endian representation of val.
**/
#define retro_cpu_to_le64(val) swap_if_big64(val)
/**
* retro_le_to_cpu16:
* @val : unsigned 16-bit value
*
* Convert unsigned 16-bit value from little-endian to native.
*
* Returns: Native representation of little-endian val.
**/
#define retro_le_to_cpu16(val) swap_if_big16(val)
/**
* retro_le_to_cpu32:
* @val : unsigned 32-bit value
*
* Convert unsigned 32-bit value from little-endian to native.
*
* Returns: Native representation of little-endian val.
**/
#define retro_le_to_cpu32(val) swap_if_big32(val)
/**
* retro_le_to_cpu16:
* @val : unsigned 64-bit value
*
* Convert unsigned 64-bit value from little-endian to native.
*
* Returns: Native representation of little-endian val.
**/
#define retro_le_to_cpu64(val) swap_if_big64(val)
/**
* retro_cpu_to_be16:
* @val : unsigned 16-bit value
*
* Convert unsigned 16-bit value from system to big-endian.
*
* Returns: Big-endian representation of val.
**/
#define retro_cpu_to_be16(val) swap_if_little16(val)
/**
* retro_cpu_to_be32:
* @val : unsigned 32-bit value
*
* Convert unsigned 32-bit value from system to big-endian.
*
* Returns: Big-endian representation of val.
**/
#define retro_cpu_to_be32(val) swap_if_little32(val)
/**
* retro_cpu_to_be64:
* @val : unsigned 64-bit value
*
* Convert unsigned 64-bit value from system to big-endian.
*
* Returns: Big-endian representation of val.
**/
#define retro_cpu_to_be64(val) swap_if_little64(val)
/**
* retro_be_to_cpu16:
* @val : unsigned 16-bit value
*
* Convert unsigned 16-bit value from big-endian to native.
*
* Returns: Native representation of big-endian val.
**/
#define retro_be_to_cpu16(val) swap_if_little16(val)
/**
* retro_be_to_cpu32:
* @val : unsigned 32-bit value
*
* Convert unsigned 32-bit value from big-endian to native.
*
* Returns: Native representation of big-endian val.
**/
#define retro_be_to_cpu32(val) swap_if_little32(val)
/**
* retro_be_to_cpu64:
* @val : unsigned 64-bit value
*
* Convert unsigned 64-bit value from big-endian to native.
*
* Returns: Native representation of big-endian val.
**/
#define retro_be_to_cpu64(val) swap_if_little64(val)
#ifdef __GNUC__
/* This attribute means that the same memory may be referred through
pointers to different size of the object (aliasing). E.g. that u8 *
and u32 * may actually be pointing to the same object. */
#define MAY_ALIAS __attribute__((__may_alias__))
#else
#define MAY_ALIAS
#endif
#pragma pack(push, 1)
struct retro_unaligned_uint16_s
{
uint16_t val;
} MAY_ALIAS;
struct retro_unaligned_uint32_s
{
uint32_t val;
} MAY_ALIAS;
struct retro_unaligned_uint64_s
{
uint64_t val;
} MAY_ALIAS;
#pragma pack(pop)
typedef struct retro_unaligned_uint16_s retro_unaligned_uint16_t;
typedef struct retro_unaligned_uint32_s retro_unaligned_uint32_t;
typedef struct retro_unaligned_uint64_s retro_unaligned_uint64_t;
/* L-value references to unaligned pointers. */
#define retro_unaligned16(p) (((retro_unaligned_uint16_t *)p)->val)
#define retro_unaligned32(p) (((retro_unaligned_uint32_t *)p)->val)
#define retro_unaligned64(p) (((retro_unaligned_uint64_t *)p)->val)
/**
* retro_get_unaligned_16be:
* @addr : pointer to unsigned 16-bit value
*
* Convert unsigned unaligned 16-bit value from big-endian to native.
*
* Returns: Native representation of big-endian val.
**/
static INLINE uint16_t retro_get_unaligned_16be(void *addr) {
return retro_be_to_cpu16(retro_unaligned16(addr));
}
/**
* retro_get_unaligned_32be:
* @addr : pointer to unsigned 32-bit value
*
* Convert unsigned unaligned 32-bit value from big-endian to native.
*
* Returns: Native representation of big-endian val.
**/
static INLINE uint32_t retro_get_unaligned_32be(void *addr) {
return retro_be_to_cpu32(retro_unaligned32(addr));
}
/**
* retro_get_unaligned_64be:
* @addr : pointer to unsigned 64-bit value
*
* Convert unsigned unaligned 64-bit value from big-endian to native.
*
* Returns: Native representation of big-endian val.
**/
static INLINE uint64_t retro_get_unaligned_64be(void *addr) {
return retro_be_to_cpu64(retro_unaligned64(addr));
}
/**
* retro_get_unaligned_16le:
* @addr : pointer to unsigned 16-bit value
*
* Convert unsigned unaligned 16-bit value from little-endian to native.
*
* Returns: Native representation of little-endian val.
**/
static INLINE uint16_t retro_get_unaligned_16le(void *addr) {
return retro_le_to_cpu16(retro_unaligned16(addr));
}
/**
* retro_get_unaligned_32le:
* @addr : pointer to unsigned 32-bit value
*
* Convert unsigned unaligned 32-bit value from little-endian to native.
*
* Returns: Native representation of little-endian val.
**/
static INLINE uint32_t retro_get_unaligned_32le(void *addr) {
return retro_le_to_cpu32(retro_unaligned32(addr));
}
/**
* retro_get_unaligned_64le:
* @addr : pointer to unsigned 64-bit value
*
* Convert unsigned unaligned 64-bit value from little-endian to native.
*
* Returns: Native representation of little-endian val.
**/
static INLINE uint64_t retro_get_unaligned_64le(void *addr) {
return retro_le_to_cpu64(retro_unaligned64(addr));
}
/**
* retro_set_unaligned_16le:
* @addr : pointer to unsigned 16-bit value
* @val : value to store
*
* Convert native value to unsigned unaligned 16-bit little-endian value
*
**/
static INLINE void retro_set_unaligned_16le(void *addr, uint16_t v) {
retro_unaligned16(addr) = retro_cpu_to_le16(v);
}
/**
* retro_set_unaligned_32le:
* @addr : pointer to unsigned 32-bit value
* @val : value to store
*
* Convert native value to unsigned unaligned 32-bit little-endian value
*
**/
static INLINE void retro_set_unaligned_32le(void *addr, uint32_t v) {
retro_unaligned32(addr) = retro_cpu_to_le32(v);
}
/**
* retro_set_unaligned_32le:
* @addr : pointer to unsigned 32-bit value
* @val : value to store
*
* Convert native value to unsigned unaligned 32-bit little-endian value
*
**/
static INLINE void retro_set_unaligned_64le(void *addr, uint64_t v) {
retro_unaligned64(addr) = retro_cpu_to_le64(v);
}
/**
* retro_set_unaligned_16be:
* @addr : pointer to unsigned 16-bit value
* @val : value to store
*
* Convert native value to unsigned unaligned 16-bit big-endian value
*
**/
static INLINE void retro_set_unaligned_16be(void *addr, uint16_t v) {
retro_unaligned16(addr) = retro_cpu_to_be16(v);
}
/**
* retro_set_unaligned_32be:
* @addr : pointer to unsigned 32-bit value
* @val : value to store
*
* Convert native value to unsigned unaligned 32-bit big-endian value
*
**/
static INLINE void retro_set_unaligned_32be(void *addr, uint32_t v) {
retro_unaligned32(addr) = retro_cpu_to_be32(v);
}
/**
* retro_set_unaligned_32be:
* @addr : pointer to unsigned 32-bit value
* @val : value to store
*
* Convert native value to unsigned unaligned 32-bit big-endian value
*
**/
static INLINE void retro_set_unaligned_64be(void *addr, uint64_t v) {
retro_unaligned64(addr) = retro_cpu_to_be64(v);
}
#endif

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_environment.h).

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_inline.h).

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_math.h).
@ -61,7 +61,7 @@
*
* Returns: next power of 2 value (derived from @v).
**/
static INLINE uint32_t next_pow2(uint32_t v)
INLINE uint32_t next_pow2(uint32_t v)
{
v--;
v |= v >> 1;
@ -81,7 +81,7 @@ static INLINE uint32_t next_pow2(uint32_t v)
*
* Returns: previous power of 2 value (derived from @v).
**/
static INLINE uint32_t prev_pow2(uint32_t v)
INLINE uint32_t prev_pow2(uint32_t v)
{
v |= v >> 1;
v |= v >> 2;
@ -91,100 +91,4 @@ static INLINE uint32_t prev_pow2(uint32_t v)
return v - (v >> 1);
}
/**
* clamp:
* @v : initial value
*
* Get the clamped value based on initial value.
*
* Returns: clamped value (derived from @v).
**/
static INLINE float clamp_value(float v, float min, float max)
{
return v <= min ? min : v >= max ? max : v;
}
/**
* saturate_value:
* @v : initial value
*
* Get the clamped 0.0-1.0 value based on initial value.
*
* Returns: clamped 0.0-1.0 value (derived from @v).
**/
static INLINE float saturate_value(float v)
{
return clamp_value(v, 0.0f, 1.0f);
}
/**
* dot_product:
* @a : left hand vector value
* @b : right hand vector value
*
* Get the dot product of the two passed in vectors.
*
* Returns: dot product value (derived from @a and @b).
**/
static INLINE float dot_product(const float* a, const float* b)
{
return (a[0] * b[0]) + (a[1] * b[1]) + (a[2] * b[2]);
}
/**
* convert_rgb_to_yxy:
* @rgb : in RGB colour space value
* @Yxy : out Yxy colour space value
*
* Convert from RGB colour space to Yxy colour space.
*
* Returns: Yxy colour space value (derived from @rgb).
**/
static INLINE void convert_rgb_to_yxy(const float* rgb, float* Yxy)
{
float inv;
float xyz[3];
float one[3] = {1.0, 1.0, 1.0};
float rgb_xyz[3][3] = {
{0.4124564, 0.3575761, 0.1804375},
{0.2126729, 0.7151522, 0.0721750},
{0.0193339, 0.1191920, 0.9503041}
};
xyz[0] = dot_product(rgb_xyz[0], rgb);
xyz[1] = dot_product(rgb_xyz[1], rgb);
xyz[2] = dot_product(rgb_xyz[2], rgb);
inv = 1.0f / dot_product(xyz, one);
Yxy[0] = xyz[1];
Yxy[1] = xyz[0] * inv;
Yxy[2] = xyz[1] * inv;
}
/**
* convert_yxy_to_rgb:
* @rgb : in Yxy colour space value
* @Yxy : out rgb colour space value
*
* Convert from Yxy colour space to rgb colour space.
*
* Returns: rgb colour space value (derived from @Yxy).
**/
static INLINE void convert_yxy_to_rgb(const float* Yxy, float* rgb)
{
float xyz[3];
float xyz_rgb[3][3] = {
{3.2404542, -1.5371385, -0.4985314},
{-0.9692660, 1.8760108, 0.0415560},
{0.0556434, -0.2040259, 1.0572252}
};
xyz[0] = Yxy[0] * Yxy[1] / Yxy[2];
xyz[1] = Yxy[0];
xyz[2] = Yxy[0] * (1.0 - Yxy[1] - Yxy[2]) / Yxy[2];
rgb[0] = dot_product(xyz_rgb[0], xyz);
rgb[1] = dot_product(xyz_rgb[1], xyz);
rgb[2] = dot_product(xyz_rgb[2], xyz);
}
#endif

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_miscellaneous.h).
@ -30,17 +30,13 @@
#include <boolean.h>
#include <retro_inline.h>
#if defined(_WIN32)
#if defined(_XBOX)
#include <Xtl.h>
#else
#if defined(_WIN32) && !defined(_XBOX)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#endif
#elif defined(_WIN32) && defined(_XBOX)
#include <Xtl.h>
#endif
#include <limits.h>
@ -49,25 +45,21 @@
#include <compat/msvc.h>
#endif
#ifdef IOS
#include <sys/param.h>
#endif
static INLINE void bits_or_bits(uint32_t *a, uint32_t *b, uint32_t count)
INLINE void bits_or_bits(uint32_t *a, uint32_t *b, uint32_t count)
{
uint32_t i;
for (i = 0; i < count;i++)
a[i] |= b[i];
}
static INLINE void bits_clear_bits(uint32_t *a, uint32_t *b, uint32_t count)
INLINE void bits_clear_bits(uint32_t *a, uint32_t *b, uint32_t count)
{
uint32_t i;
for (i = 0; i < count;i++)
a[i] &= ~b[i];
}
static INLINE bool bits_any_set(uint32_t* ptr, uint32_t count)
INLINE bool bits_any_set(uint32_t* ptr, uint32_t count)
{
uint32_t i;
for (i = 0; i < count; i++)
@ -78,29 +70,14 @@ static INLINE bool bits_any_set(uint32_t* ptr, uint32_t count)
return false;
}
static INLINE bool bits_any_different(uint32_t *a, uint32_t *b, uint32_t count)
{
uint32_t i;
for (i = 0; i < count; i++)
{
if (a[i] != b[i])
return true;
}
return false;
}
#ifndef PATH_MAX_LENGTH
#if defined(_XBOX1) || defined(_3DS) || defined(PSP) || defined(PS2) || defined(GEKKO)|| defined(WIIU) || defined(__PSL1GHT__) || defined(__PS3__)
#if defined(_XBOX1) || defined(_3DS) || defined(PSP) || defined(PS2) || defined(GEKKO)|| defined(WIIU) || defined(ORBIS)
#define PATH_MAX_LENGTH 512
#else
#define PATH_MAX_LENGTH 4096
#endif
#endif
#ifndef NAME_MAX_LENGTH
#define NAME_MAX_LENGTH 256
#endif
#ifndef MAX
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
@ -123,8 +100,8 @@ static INLINE bool bits_any_different(uint32_t *a, uint32_t *b, uint32_t count)
#define BIT16_GET(a, bit) (((a) >> ((bit) & 15)) & 1)
#define BIT16_CLEAR_ALL(a) ((a) = 0)
#define BIT32_SET(a, bit) ((a) |= (UINT32_C(1) << ((bit) & 31)))
#define BIT32_CLEAR(a, bit) ((a) &= ~(UINT32_C(1) << ((bit) & 31)))
#define BIT32_SET(a, bit) ((a) |= (1 << ((bit) & 31)))
#define BIT32_CLEAR(a, bit) ((a) &= ~(1 << ((bit) & 31)))
#define BIT32_GET(a, bit) (((a) >> ((bit) & 31)) & 1)
#define BIT32_CLEAR_ALL(a) ((a) = 0)
@ -133,8 +110,8 @@ static INLINE bool bits_any_different(uint32_t *a, uint32_t *b, uint32_t count)
#define BIT64_GET(a, bit) (((a) >> ((bit) & 63)) & 1)
#define BIT64_CLEAR_ALL(a) ((a) = 0)
#define BIT128_SET(a, bit) ((a).data[(bit) >> 5] |= (UINT32_C(1) << ((bit) & 31)))
#define BIT128_CLEAR(a, bit) ((a).data[(bit) >> 5] &= ~(UINT32_C(1) << ((bit) & 31)))
#define BIT128_SET(a, bit) ((a).data[(bit) >> 5] |= (1 << ((bit) & 31)))
#define BIT128_CLEAR(a, bit) ((a).data[(bit) >> 5] &= ~(1 << ((bit) & 31)))
#define BIT128_GET(a, bit) (((a).data[(bit) >> 5] >> ((bit) & 31)) & 1)
#define BIT128_CLEAR_ALL(a) memset(&(a), 0, sizeof(a))
@ -153,16 +130,6 @@ static INLINE bool bits_any_different(uint32_t *a, uint32_t *b, uint32_t count)
#define BIT256_GET_PTR(a, bit) BIT256_GET(*a, bit)
#define BIT256_CLEAR_ALL_PTR(a) BIT256_CLEAR_ALL(*a)
#define BIT512_SET(a, bit) BIT256_SET(a, bit)
#define BIT512_CLEAR(a, bit) BIT256_CLEAR(a, bit)
#define BIT512_GET(a, bit) BIT256_GET(a, bit)
#define BIT512_CLEAR_ALL(a) BIT256_CLEAR_ALL(a)
#define BIT512_SET_PTR(a, bit) BIT512_SET(*a, bit)
#define BIT512_CLEAR_PTR(a, bit) BIT512_CLEAR(*a, bit)
#define BIT512_GET_PTR(a, bit) BIT512_GET(*a, bit)
#define BIT512_CLEAR_ALL_PTR(a) BIT512_CLEAR_ALL(*a)
#define BITS_COPY16_PTR(a,bits) \
{ \
BIT128_CLEAR_ALL_PTR(a); \
@ -175,13 +142,6 @@ static INLINE bool bits_any_different(uint32_t *a, uint32_t *b, uint32_t count)
BITS_GET_ELEM_PTR(a, 0) = (bits); \
}
#define BITS_COPY64_PTR(a,bits) \
{ \
BIT128_CLEAR_ALL_PTR(a); \
BITS_GET_ELEM_PTR(a, 0) = (bits); \
BITS_GET_ELEM_PTR(a, 1) = (bits >> 32); \
}
/* Helper macros and struct to keep track of many booleans. */
/* This struct has 256 bits. */
typedef struct
@ -189,12 +149,6 @@ typedef struct
uint32_t data[8];
} retro_bits_t;
/* This struct has 512 bits. */
typedef struct
{
uint32_t data[16];
} retro_bits_512_t;
#ifdef _WIN32
# ifdef _WIN64
# define PRI_SIZET PRIu64
@ -205,7 +159,7 @@ typedef struct
# define PRI_SIZET "u"
# endif
# endif
#elif defined(PS2)
#elif PS2
# define PRI_SIZET "u"
#else
# if (SIZE_MAX == 0xFFFF)

View File

@ -27,8 +27,6 @@
#if defined(XENON)
#include <time/time.h>
#elif !defined(__PSL1GHT__) && defined(__PS3__)
#include <sys/timer.h>
#elif defined(GEKKO) || defined(__PSL1GHT__) || defined(__QNX__)
#include <unistd.h>
#elif defined(WIIU)
@ -39,8 +37,6 @@
#include <psp2/kernel/threadmgr.h>
#elif defined(_3DS)
#include <3ds.h>
#elif defined(EMSCRIPTEN)
#include <emscripten/emscripten.h>
#else
#include <time.h>
#endif
@ -85,7 +81,7 @@ static int nanosleepDOS(const struct timespec *rqtp, struct timespec *rmtp)
*
* Sleeps for a specified amount of milliseconds (@msec).
**/
#if defined(VITA)
#if defined(PSP) || defined(VITA)
#define retro_sleep(msec) (sceKernelDelayThread(1000 * (msec)))
#elif defined(_3DS)
#define retro_sleep(msec) (svcSleepThread(1000000 * (s64)(msec)))
@ -95,21 +91,17 @@ static int nanosleepDOS(const struct timespec *rqtp, struct timespec *rmtp)
#define retro_sleep(msec) (Sleep((msec)))
#elif defined(XENON)
#define retro_sleep(msec) (udelay(1000 * (msec)))
#elif !defined(__PSL1GHT__) && defined(__PS3__)
#define retro_sleep(msec) (sys_timer_usleep(1000 * (msec)))
#elif defined(GEKKO) || defined(__PSL1GHT__) || defined(__QNX__)
#define retro_sleep(msec) (usleep(1000 * (msec)))
#elif defined(WIIU)
#define retro_sleep(msec) (OSSleepTicks(ms_to_ticks((msec))))
#elif defined(EMSCRIPTEN)
#define retro_sleep(msec) (emscripten_sleep(msec))
#else
static INLINE void retro_sleep(unsigned msec)
{
struct timespec tv;
tv.tv_sec = msec / 1000;
tv.tv_nsec = (msec % 1000) * 1000000;
nanosleep(&tv, NULL);
#define retro_sleep(msec) \
{ \
struct timespec tv = {0}; \
tv.tv_sec = msec / 1000; \
tv.tv_nsec = (msec % 1000) * 1000000; \
nanosleep(&tv, NULL); \
}
#endif

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (file_stream.h).
@ -59,9 +59,9 @@ int64_t filestream_truncate(RFILE *stream, int64_t length);
* @bufsize : optional buffer size (-1 or 0 to use default)
*
* Opens a file for reading or writing, depending on the requested mode.
* @return A pointer to an RFILE if opened successfully, otherwise NULL.
* Returns a pointer to an RFILE if opened successfully, otherwise NULL.
**/
RFILE* filestream_open(const char *path, unsigned mode, unsigned hints);
RFILE *filestream_open(const char *path, unsigned mode, unsigned hints);
int64_t filestream_seek(RFILE *stream, int64_t offset, int seek_position);
@ -75,39 +75,16 @@ void filestream_rewind(RFILE *stream);
int filestream_close(RFILE *stream);
/**
* filestream_read_file:
* @path : path to file.
* @buf : buffer to allocate and read the contents of the
* file into. Needs to be freed manually.
* @len : optional output integer containing bytes read.
*
* Read the contents of a file into @buf.
*
* @return Non-zero on success.
*/
int64_t filestream_read_file(const char *path, void **buf, int64_t *len);
char* filestream_gets(RFILE *stream, char *s, size_t len);
char *filestream_gets(RFILE *stream, char *s, size_t len);
int filestream_getc(RFILE *stream);
int filestream_vscanf(RFILE *stream, const char* format, va_list *args);
int filestream_scanf(RFILE *stream, const char* format, ...);
int filestream_eof(RFILE *stream);
/**
* filestream_write_file:
* @path : path to file.
* @data : contents to write to the file.
* @size : size of the contents.
*
* Writes data to a file.
*
* @return true on success, otherwise false.
**/
bool filestream_write_file(const char *path, const void *data, int64_t size);
int filestream_putc(RFILE *stream, int c);
@ -124,16 +101,11 @@ int filestream_delete(const char *path);
int filestream_rename(const char *old_path, const char *new_path);
const char* filestream_get_path(RFILE *stream);
const char *filestream_get_path(RFILE *stream);
bool filestream_exists(const char *path);
/**
* filestream_getline:
*
* Returned pointer must be freed by the caller.
**/
char* filestream_getline(RFILE *stream);
char *filestream_getline(RFILE *stream);
libretro_vfs_implementation_file* filestream_get_vfs_handle(RFILE *stream);

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (file_stream_transforms.h).
@ -30,8 +30,6 @@
RETRO_BEGIN_DECLS
#ifndef SKIP_STDIO_REDEFINES
#define FILE RFILE
#undef fopen
@ -43,11 +41,9 @@ RETRO_BEGIN_DECLS
#undef fgetc
#undef fwrite
#undef fputc
#undef fflush
#undef fprintf
#undef ferror
#undef feof
#undef fscanf
#define fopen rfopen
#define fclose rfclose
@ -58,13 +54,9 @@ RETRO_BEGIN_DECLS
#define fgetc rfgetc
#define fwrite rfwrite
#define fputc rfputc
#define fflush rfflush
#define fprintf rfprintf
#define ferror rferror
#define feof rfeof
#define fscanf rfscanf
#endif
RFILE* rfopen(const char *path, const char *mode);
@ -86,16 +78,12 @@ int64_t rfwrite(void const* buffer,
int rfputc(int character, RFILE * stream);
int64_t rfflush(RFILE * stream);
int rfprintf(RFILE * stream, const char * format, ...);
int rferror(RFILE* stream);
int rfeof(RFILE* stream);
int rfscanf(RFILE * stream, const char * format, ...);
RETRO_END_DECLS
#endif

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2019 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (stdstring.h).
@ -35,87 +35,42 @@
RETRO_BEGIN_DECLS
#define STRLEN_CONST(x) ((sizeof((x))-1))
#define strcpy_literal(a, b) strcpy(a, b)
#define string_is_not_equal(a, b) !string_is_equal((a), (b))
#define string_is_not_equal_fast(a, b, size) (memcmp(a, b, size) != 0)
#define string_is_equal_fast(a, b, size) (memcmp(a, b, size) == 0)
#define TOLOWER(c) ((c) | (lr_char_props[(unsigned char)(c)] & 0x20))
#define TOUPPER(c) ((c) & ~(lr_char_props[(unsigned char)(c)] & 0x20))
/* C standard says \f \v are space, but this one disagrees */
#define ISSPACE(c) (lr_char_props[(unsigned char)(c)] & 0x80)
#define ISDIGIT(c) (lr_char_props[(unsigned char)(c)] & 0x40)
#define ISALPHA(c) (lr_char_props[(unsigned char)(c)] & 0x20)
#define ISLOWER(c) (lr_char_props[(unsigned char)(c)] & 0x04)
#define ISUPPER(c) (lr_char_props[(unsigned char)(c)] & 0x02)
#define ISALNUM(c) (lr_char_props[(unsigned char)(c)] & 0x60)
#define ISUALPHA(c) (lr_char_props[(unsigned char)(c)] & 0x28)
#define ISUALNUM(c) (lr_char_props[(unsigned char)(c)] & 0x68)
#define IS_XDIGIT(c) (lr_char_props[(unsigned char)(c)] & 0x01)
/* Deprecated alias, all callers should use string_is_equal_case_insensitive instead */
#define string_is_equal_noncase string_is_equal_case_insensitive
static INLINE bool string_is_empty(const char *data)
INLINE bool string_is_empty(const char *data)
{
return !data || (*data == '\0');
}
static INLINE bool string_is_equal(const char *a, const char *b)
INLINE bool string_is_equal(const char *a, const char *b)
{
return (a && b) ? !strcmp(a, b) : false;
}
static INLINE bool string_starts_with_size(const char *str, const char *prefix,
#define STRLEN_CONST(x) ((sizeof((x))-1))
#define string_is_not_equal(a, b) !string_is_equal((a), (b))
#define string_add_pair_open(s, size) strlcat((s), " (", (size))
#define string_add_pair_close(s, size) strlcat((s), ")", (size))
#define string_add_bracket_open(s, size) strlcat((s), "{", (size))
#define string_add_bracket_close(s, size) strlcat((s), "}", (size))
#define string_add_single_quote(s, size) strlcat((s), "'", (size))
#define string_add_quote(s, size) strlcat((s), "\"", (size))
#define string_add_colon(s, size) strlcat((s), ":", (size))
#define string_add_glob_open(s, size) strlcat((s), "glob('*", (size))
#define string_add_glob_close(s, size) strlcat((s), "*')", (size))
#define string_is_not_equal_fast(a, b, size) (memcmp(a, b, size) != 0)
#define string_is_equal_fast(a, b, size) (memcmp(a, b, size) == 0)
INLINE void string_add_between_pairs(char *s, const char *str,
size_t size)
{
return (str && prefix) ? !strncmp(prefix, str, size) : false;
string_add_pair_open(s, size);
strlcat(s, str, size);
string_add_pair_close(s, size);
}
static INLINE bool string_starts_with(const char *str, const char *prefix)
{
return (str && prefix) ? !strncmp(prefix, str, strlen(prefix)) : false;
}
static INLINE bool string_ends_with_size(const char *str, const char *suffix,
size_t str_len, size_t suffix_len)
{
return (str_len < suffix_len) ? false :
!memcmp(suffix, str + (str_len - suffix_len), suffix_len);
}
static INLINE bool string_ends_with(const char *str, const char *suffix)
{
return str && suffix && string_ends_with_size(str, suffix, strlen(str), strlen(suffix));
}
/**
* strlen_size:
*
* Leaf function.
*
* @return the length of 'str' (c.f. strlen()), but only
* checks the first 'size' characters
* - If 'str' is NULL, returns 0
* - If 'str' is not NULL and no '\0' character is found
* in the first 'size' characters, returns 'size'
**/
static INLINE size_t strlen_size(const char *str, size_t size)
{
size_t i = 0;
if (str)
while (i < size && str[i]) i++;
return i;
}
static INLINE bool string_is_equal_case_insensitive(const char *a,
INLINE bool string_is_equal_case_insensitive(const char *a,
const char *b)
{
int result = 0;
@ -134,23 +89,22 @@ static INLINE bool string_is_equal_case_insensitive(const char *a,
return (result == 0);
}
static INLINE bool string_starts_with_case_insensitive(const char *str,
const char *prefix)
INLINE bool string_is_equal_noncase(const char *a, const char *b)
{
int result = 0;
const unsigned char *p1 = (const unsigned char*)str;
const unsigned char *p2 = (const unsigned char*)prefix;
const unsigned char *p1 = (const unsigned char*)a;
const unsigned char *p2 = (const unsigned char*)b;
if (!str || !prefix)
if (!a || !b)
return false;
if (p1 == p2)
return true;
return false;
while ((result = tolower (*p1++) - tolower (*p2)) == 0)
if (*p2++ == '\0')
while ((result = tolower (*p1) - tolower (*p2++)) == 0)
if (*p1++ == '\0')
break;
return (result == 0 || *p2 == '\0');
return (result == 0);
}
char *string_to_upper(char *s);
@ -159,228 +113,21 @@ char *string_to_lower(char *s);
char *string_ucwords(char *s);
char *string_replace_substring(const char *in,
const char *pattern, size_t pattern_len,
const char *replacement, size_t replacement_len);
char *string_replace_substring(const char *in, const char *pattern,
const char *by);
/**
* string_trim_whitespace_left:
*
* Remove leading whitespaces
**/
/* Remove leading whitespaces */
char *string_trim_whitespace_left(char *const s);
/**
* string_trim_whitespace_right:
*
* Remove trailing whitespaces
**/
/* Remove trailing whitespaces */
char *string_trim_whitespace_right(char *const s);
/**
* string_trim_whitespace:
*
* Remove leading and trailing whitespaces
**/
/* Remove leading and trailing whitespaces */
char *string_trim_whitespace(char *const s);
/**
* word_wrap:
* @dst : pointer to destination buffer.
* @dst_size : size of destination buffer.
* @src : pointer to input string.
* @src_len : length of @src
* @line_width : max number of characters per line.
* @wideglyph_width : not used, but is necessary to keep
* compatibility with word_wrap_wideglyph().
* @max_lines : max lines of destination string.
* 0 means no limit.
*
* Wraps string specified by 'src' to destination buffer
* specified by 'dst' and 'dst_size'.
* This function assumes that all glyphs in the string
* have an on-screen pixel width similar to that of
* regular Latin characters - i.e. it will not wrap
* correctly any text containing so-called 'wide' Unicode
* characters (e.g. CJK languages, emojis, etc.).
**/
size_t word_wrap(char *dst, size_t dst_size, const char *src, size_t src_len,
int line_width, int wideglyph_width, unsigned max_lines);
/**
* word_wrap_wideglyph:
* @dst : pointer to destination buffer.
* @dst_size : size of destination buffer.
* @src : pointer to input string.
* @src_len : length of @src
* @line_width : max number of characters per line.
* @wideglyph_width : effective width of 'wide' Unicode glyphs.
* the value here is normalised relative to the
* typical on-screen pixel width of a regular
* Latin character:
* - a regular Latin character is defined to
* have an effective width of 100
* - wideglyph_width = 100 * (wide_character_pixel_width / latin_character_pixel_width)
* - e.g. if 'wide' Unicode characters in 'src'
* have an on-screen pixel width twice that of
* regular Latin characters, wideglyph_width
* would be 200
* @max_lines : max lines of destination string.
* 0 means no limit.
*
* Wraps string specified by @src to destination buffer
* specified by @dst and @dst_size.
* This function assumes that all glyphs in the string
* are:
* - EITHER 'non-wide' Unicode glyphs, with an on-screen
* pixel width similar to that of regular Latin characters
* - OR 'wide' Unicode glyphs (e.g. CJK languages, emojis, etc.)
* with an on-screen pixel width defined by @wideglyph_width
* Note that wrapping may occur in inappropriate locations
* if @src string contains 'wide' Unicode characters whose
* on-screen pixel width deviates greatly from the set
* @wideglyph_width value.
**/
size_t word_wrap_wideglyph(
char *dst, size_t dst_size,
const char *src, size_t src_len,
int line_width, int wideglyph_width,
unsigned max_lines);
/**
* string_tokenize:
*
* Splits string into tokens seperated by @delim
* > Returned token string must be free()'d
* > Returns NULL if token is not found
* > After each call, @str is set to the position after the
* last found token
* > Tokens *include* empty strings
* Usage example:
* char *str = "1,2,3,4,5,6,7,,,10,";
* char **str_ptr = &str;
* char *token = NULL;
* while ((token = string_tokenize(str_ptr, ",")))
* {
* printf("%s\n", token);
* free(token);
* token = NULL;
* }
**/
char* string_tokenize(char **str, const char *delim);
/**
* string_remove_all_chars:
* @str : input string (must be non-NULL, otherwise UB)
*
* Leaf function.
*
* Removes every instance of character @c from @str
**/
void string_remove_all_chars(char *str, char c);
/**
* string_replace_all_chars:
* @str : input string (must be non-NULL, otherwise UB)
* @find : character to find
* @replace : character to replace @find with
*
* Hidden non-leaf function cost:
* - Calls strchr (in a loop)
*
* Replaces every instance of character @find in @str
* with character @replace
**/
void string_replace_all_chars(char *str, char find, char replace);
/**
* string_to_unsigned:
* @str : input string
*
* Converts string to unsigned integer.
*
* @return 0 if string is invalid, otherwise > 0
**/
unsigned string_to_unsigned(const char *str);
/**
* string_hex_to_unsigned:
* @str : input string (must be non-NULL, otherwise UB)
*
* Converts hexadecimal string to unsigned integer.
* Handles optional leading '0x'.
*
* @return 0 if string is invalid, otherwise > 0
**/
unsigned string_hex_to_unsigned(const char *str);
char *string_init(const char *src);
void string_set(char **string, const char *src);
/**
* string_count_occurrences_single_character:
*
* Leaf function.
*
* Get the total number of occurrences of character @c in @str.
*
* @return Total number of occurrences of character @c
*/
int string_count_occurrences_single_character(const char *str, char c);
/**
* string_replace_whitespace_with_single_character:
*
* Leaf function.
*
* Replaces all spaces with given character @c.
**/
void string_replace_whitespace_with_single_character(char *str, char c);
/**
* string_replace_multi_space_with_single_space:
*
* Leaf function.
*
* Replaces multiple spaces with a single space in a string.
**/
void string_replace_multi_space_with_single_space(char *str);
/**
* string_remove_all_whitespace:
*
* Leaf function.
*
* Remove all spaces from the given string.
**/
void string_remove_all_whitespace(char *str_trimmed, const char *str);
/* Retrieve the last occurance of the given character in a string. */
int string_index_last_occurance(const char *str, char c);
/**
* string_find_index_substring_string:
* @str : input string (must be non-NULL, otherwise UB)
* @substr : substring to find in @str
*
* Hidden non-leaf function cost:
* - Calls strstr
*
* Find the position of substring @substr in string @str.
**/
int string_find_index_substring_string(const char *str, const char *substr);
/**
* string_copy_only_ascii:
*
* Leaf function.
*
* Strips non-ASCII characters from a string.
**/
void string_copy_only_ascii(char *str_stripped, const char *str);
extern const unsigned char lr_char_props[256];
/* max_lines == 0 means no limit */
char *word_wrap(char *buffer, const char *string,
int line_width, bool unicode, unsigned max_lines);
RETRO_END_DECLS

View File

@ -1,48 +0,0 @@
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (rtime.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __LIBRETRO_SDK_RTIME_H__
#define __LIBRETRO_SDK_RTIME_H__
#include <retro_common_api.h>
#include <stdint.h>
#include <stddef.h>
#include <time.h>
RETRO_BEGIN_DECLS
/* TODO/FIXME: Move all generic time handling functions
* to this file */
/* Must be called before using rtime_localtime() */
void rtime_init(void);
/* Must be called upon program termination */
void rtime_deinit(void);
/* Thread-safe wrapper for localtime() */
struct tm *rtime_localtime(const time_t *timep, struct tm *result);
RETRO_END_DECLS
#endif

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2019 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (vfs_implementation.h).
@ -41,17 +41,17 @@ typedef void* HANDLE;
#ifdef HAVE_CDROM
typedef struct
{
int64_t byte_pos;
char *cue_buf;
size_t cue_len;
unsigned cur_lba;
unsigned last_frame_lba;
int64_t byte_pos;
char drive;
unsigned char cur_min;
unsigned char cur_sec;
unsigned char cur_frame;
unsigned char cur_track;
unsigned cur_lba;
unsigned last_frame_lba;
unsigned char last_frame[2352];
char drive;
bool last_frame_valid;
} vfs_cdrom_t;
#endif
@ -62,29 +62,29 @@ enum vfs_scheme
VFS_SCHEME_CDROM
};
#if !(defined(__WINRT__) && defined(__cplusplus_winrt))
#ifndef __WINRT__
#ifdef VFS_FRONTEND
struct retro_vfs_file_handle
#else
struct libretro_vfs_implementation_file
#endif
{
#ifdef HAVE_CDROM
vfs_cdrom_t cdrom; /* int64_t alignment */
#endif
int fd;
unsigned hints;
int64_t size;
uint64_t mappos;
uint64_t mapsize;
char *buf;
FILE *fp;
#ifdef _WIN32
HANDLE fh;
#endif
char *buf;
char* orig_path;
uint64_t mappos;
uint64_t mapsize;
uint8_t *mapped;
int fd;
unsigned hints;
enum vfs_scheme scheme;
#ifdef HAVE_CDROM
vfs_cdrom_t cdrom;
#endif
};
#endif

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2019 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (vfs_implementation.h).
@ -71,12 +71,6 @@ bool retro_vfs_dirent_is_dir_impl(libretro_vfs_implementation_dir *dirstream);
int retro_vfs_closedir_impl(libretro_vfs_implementation_dir *dirstream);
#ifdef __WINRT__
void uwp_set_acl(const wchar_t* path, const wchar_t* AccessString);
#endif
RETRO_END_DECLS
#endif

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2019 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (vfs_implementation_cdrom.h).

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (dir_list.c).
@ -46,22 +46,6 @@ 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_;
@ -75,25 +59,13 @@ 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.
* @dir_first : move the directories in the listing to the top?
*
* Sorts a directory listing.
*
**/
void dir_list_sort(struct string_list *list, bool dir_first)
{
@ -102,38 +74,18 @@ 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
*
* Frees a directory listing.
*
**/
void dir_list_free(struct string_list *list)
{
string_list_free(list);
}
bool dir_list_deinitialize(struct string_list *list)
{
if (!list)
return false;
return string_list_deinitialize(list);
}
/**
* dir_list_read:
* @dir : directory path.
@ -146,7 +98,7 @@ bool dir_list_deinitialize(struct string_list *list)
*
* Add files within a directory to an existing string list
*
* @return -1 on error, 0 on success.
* Returns: -1 on error, 0 on success.
**/
static int dir_list_read(const char *dir,
struct string_list *list, struct string_list *ext_list,
@ -164,31 +116,16 @@ static int dir_list_read(const char *dir,
char file_path[PATH_MAX_LENGTH];
const char *name = retro_dirent_get_name(entry);
if (name[0] == '.')
{
/* Do not include hidden files and directories */
if (!include_hidden)
continue;
if (!include_hidden && *name == '.')
continue;
if (!strcmp(name, ".") || !strcmp(name, ".."))
continue;
/* char-wise comparisons to avoid string comparison */
/* Do not include current dir */
if (name[1] == '\0')
continue;
/* Do not include parent dir */
if (name[1] == '.' && name[2] == '\0')
continue;
}
fill_pathname_join_special(file_path, dir, name, sizeof(file_path));
file_path[0] = '\0';
fill_pathname_join(file_path, dir, name, sizeof(file_path));
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);
@ -251,7 +188,7 @@ error:
*
* Create a directory listing, appending to an existing list
*
* @return Returns true on success, otherwise false.
* Returns: true success, false in case of error.
**/
bool dir_list_append(struct string_list *list,
const char *dir,
@ -259,19 +196,12 @@ bool dir_list_append(struct string_list *list,
bool include_hidden, bool include_compressed,
bool recursive)
{
bool ret = false;
struct string_list ext_list = {0};
struct string_list *ext_list_ptr = NULL;
if (ext)
{
string_list_initialize(&ext_list);
string_split_noalloc(&ext_list, ext, "|");
ext_list_ptr = &ext_list;
}
ret = dir_list_read(dir, list, ext_list_ptr,
struct string_list *ext_list = ext ? string_split(ext, "|") : NULL;
bool ret = dir_list_read(dir, list, ext_list,
include_dirs, include_hidden, include_compressed, recursive) != -1;
string_list_deinitialize(&ext_list);
string_list_free(ext_list);
return ret;
}
@ -286,7 +216,7 @@ bool dir_list_append(struct string_list *list,
*
* Create a directory listing.
*
* @return pointer to a directory listing of type 'struct string_list *' on success,
* Returns: pointer to a directory listing of type 'struct string_list *' on success,
* NULL in case of error. Has to be freed manually.
**/
struct string_list *dir_list_new(const char *dir,
@ -294,9 +224,9 @@ struct string_list *dir_list_new(const char *dir,
bool include_hidden, bool include_compressed,
bool recursive)
{
struct string_list *list = string_list_new();
struct string_list *list = NULL;
if (!list)
if (!(list = string_list_new()))
return NULL;
if (!dir_list_append(list, dir, ext, include_dirs,
@ -308,21 +238,3 @@ struct string_list *dir_list_new(const char *dir,
return list;
}
/**
* dir_list_initialize:
*
* NOTE: @list must zero initialised before
* calling this function, otherwise UB.
**/
bool dir_list_initialize(struct string_list *list,
const char *dir,
const char *ext, bool include_dirs,
bool include_hidden, bool include_compressed,
bool recursive)
{
if (list && string_list_initialize(list))
return dir_list_append(list, dir, ext, include_dirs,
include_hidden, include_compressed, recursive);
return false;
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (string_list.c).
@ -29,30 +29,32 @@
#include <compat/posix_string.h>
#include <string/stdstring.h>
static bool string_list_deinitialize_internal(struct string_list *list)
/**
* string_list_free
* @list : pointer to string list object
*
* Frees a string list.
*/
void string_list_free(struct string_list *list)
{
size_t i;
if (!list)
return false;
return;
if (list->elems)
{
unsigned i;
for (i = 0; i < list->size; i++)
{
if (list->elems[i].data)
free(list->elems[i].data);
if (list->elems[i].userdata)
free(list->elems[i].userdata);
list->elems[i].data = NULL;
list->elems[i].userdata = NULL;
list->elems[i].data = NULL;
}
free(list->elems);
}
list->elems = NULL;
return true;
free(list);
}
/**
@ -62,7 +64,7 @@ static bool string_list_deinitialize_internal(struct string_list *list)
*
* Change maximum capacity of string list's size.
*
* @return true if successful, otherwise false.
* Returns: true (1) if successful, otherwise false (0).
**/
static bool string_list_capacity(struct string_list *list, size_t cap)
{
@ -80,82 +82,30 @@ static bool string_list_capacity(struct string_list *list, size_t cap)
return true;
}
/**
* string_list_free
* @list : pointer to string list object
*
* Frees a string list.
**/
void string_list_free(struct string_list *list)
{
if (!list)
return;
string_list_deinitialize_internal(list);
free(list);
}
bool string_list_deinitialize(struct string_list *list)
{
if (!list)
return false;
if (!string_list_deinitialize_internal(list))
return false;
list->elems = NULL;
list->size = 0;
list->cap = 0;
return true;
}
/**
* string_list_new:
*
* Creates a new string list. Has to be freed manually.
*
* @return New string list if successful, otherwise NULL.
**/
* Returns: new string list if successful, otherwise NULL.
*/
struct string_list *string_list_new(void)
{
struct string_list_elem *
elems = NULL;
struct string_list *list = (struct string_list*)
malloc(sizeof(*list));
calloc(1, sizeof(*list));
if (!list)
return NULL;
if (!(elems = (struct string_list_elem*)
calloc(32, sizeof(*elems))))
if (!string_list_capacity(list, 32))
{
string_list_free(list);
return NULL;
}
list->elems = elems;
list->size = 0;
list->cap = 32;
return list;
}
bool string_list_initialize(struct string_list *list)
{
struct string_list_elem *
elems = NULL;
if (!list)
return false;
if (!(elems = (struct string_list_elem*)
calloc(32, sizeof(*elems))))
{
string_list_deinitialize(list);
return false;
}
list->elems = elems;
list->size = 0;
list->cap = 32;
return true;
}
/**
* string_list_append:
* @list : pointer to string list
@ -164,25 +114,19 @@ bool string_list_initialize(struct string_list *list)
*
* Appends a new element to the string list.
*
* @return true if successful, otherwise false.
* Returns: true (1) if successful, otherwise false (0).
**/
bool string_list_append(struct string_list *list, const char *elem,
union string_list_elem_attr attr)
{
char *data_dup = NULL;
/* Note: If 'list' is incorrectly initialised
* (i.e. if struct is zero initialised and
* string_list_initialize() is not called on
* it) capacity will be zero. This will cause
* a segfault. Handle this case by forcing the new
* capacity to a fixed size of 32 */
if (list->size >= list->cap &&
!string_list_capacity(list,
(list->cap > 0) ? (list->cap * 2) : 32))
!string_list_capacity(list, list->cap * 2))
return false;
if (!(data_dup = strdup(elem)))
data_dup = strdup(elem);
if (!data_dup)
return false;
list->elems[list->size].data = data_dup;
@ -201,7 +145,7 @@ bool string_list_append(struct string_list *list, const char *elem,
*
* Appends a new element to the string list.
*
* @return true if successful, otherwise false.
* Returns: true (1) if successful, otherwise false (0).
**/
bool string_list_append_n(struct string_list *list, const char *elem,
unsigned length, union string_list_elem_attr attr)
@ -212,7 +156,9 @@ bool string_list_append_n(struct string_list *list, const char *elem,
!string_list_capacity(list, list->cap * 2))
return false;
if (!(data_dup = (char*)malloc(length + 1)))
data_dup = (char*)malloc(length + 1);
if (!data_dup)
return false;
strlcpy(data_dup, elem, length + 1);
@ -248,22 +194,11 @@ void string_list_set(struct string_list *list,
*
* A string list will be joined/concatenated as a
* string to @buffer, delimited by @delim.
**/
*/
void string_list_join_concat(char *buffer, size_t size,
const struct string_list *list, const char *delim)
{
size_t i;
size_t len = strlen_size(buffer, size);
/* If buffer is already 'full', nothing
* further can be added
* > This condition will also be triggered
* if buffer is not NULL-terminated,
* in which case any attempt to increment
* buffer or decrement size would lead to
* undefined behaviour */
if (len >= size)
return;
size_t i, len = strlen(buffer);
buffer += len;
size -= len;
@ -293,9 +228,10 @@ struct string_list *string_split(const char *str, const char *delim)
struct string_list *list = string_list_new();
if (!list)
return NULL;
goto error;
if (!(copy = strdup(str)))
copy = strdup(str);
if (!copy)
goto error;
tmp = strtok_r(copy, delim, &save);
@ -320,211 +256,100 @@ error:
return NULL;
}
bool string_split_noalloc(struct string_list *list,
const char *str, const char *delim)
/**
* string_list_find_elem:
* @list : pointer to string list
* @elem : element to find inside the string list.
*
* Searches for an element (@elem) inside the string list.
*
* Returns: true (1) if element could be found, otherwise false (0).
*/
int string_list_find_elem(const struct string_list *list, const char *elem)
{
char *save = NULL;
char *copy = NULL;
const char *tmp = NULL;
size_t i;
if (!list)
return false;
if (!(copy = strdup(str)))
return false;
tmp = strtok_r(copy, delim, &save);
while (tmp)
for (i = 0; i < list->size; i++)
{
union string_list_elem_attr attr;
attr.i = 0;
if (!string_list_append(list, tmp, attr))
{
free(copy);
return false;
}
tmp = strtok_r(NULL, delim, &save);
if (string_is_equal_noncase(list->elems[i].data, elem))
return (int)(i + 1);
}
free(copy);
return true;
}
/**
* string_separate:
* @str : string to turn into a string list
* @delim : delimiter character to use for separating the string.
*
* Creates a new string list based on string @str, delimited by @delim.
* Includes empty strings - i.e. two adjacent delimiters will resolve
* to a string list element of "".
*
* @return New string list if successful, otherwise NULL.
**/
struct string_list *string_separate(char *str, const char *delim)
{
char *token = NULL;
char **str_ptr = NULL;
struct string_list *list = NULL;
/* Sanity check */
if (!str || string_is_empty(delim))
return NULL;
if (!(list = string_list_new()))
return NULL;
str_ptr = &str;
token = string_tokenize(str_ptr, delim);
while (token)
{
union string_list_elem_attr attr;
attr.i = 0;
if (!string_list_append(list, token, attr))
{
free(token);
string_list_free(list);
return NULL;
}
free(token);
token = string_tokenize(str_ptr, delim);
}
return list;
}
bool string_separate_noalloc(
struct string_list *list,
char *str, const char *delim)
{
char *token = NULL;
char **str_ptr = NULL;
/* Sanity check */
if (!str || string_is_empty(delim) || !list)
return false;
str_ptr = &str;
token = string_tokenize(str_ptr, delim);
while (token)
{
union string_list_elem_attr attr;
attr.i = 0;
if (!string_list_append(list, token, attr))
{
free(token);
return false;
}
free(token);
token = string_tokenize(str_ptr, delim);
}
return true;
}
/**
* string_list_find_elem:
*
* @param list
* Pointer to string list
* @param elem
* Element to find inside the string list.
*
* Searches for an element (@elem) inside the string list.
*
* @return Number of elements found, otherwise 0.
*/
int string_list_find_elem(const struct string_list *list, const char *elem)
{
if (list)
{
size_t i;
for (i = 0; i < list->size; i++)
{
if (string_is_equal_noncase(list->elems[i].data, elem))
return (int)(i + 1);
}
}
return 0;
return false;
}
/**
* string_list_find_elem_prefix:
*
* @param list
* Pointer to string list
* @param prefix
* Prefix to append to @elem
* @param elem
* Element to find inside the string list.
* @list : pointer to string list
* @prefix : prefix to append to @elem
* @elem : element to find inside the string list.
*
* Searches for an element (@elem) inside the string list. Will
* also search for the same element prefixed by @prefix.
*
* @return true if element could be found, otherwise false.
* Returns: true (1) if element could be found, otherwise false (0).
*/
bool string_list_find_elem_prefix(const struct string_list *list,
const char *prefix, const char *elem)
{
if (list)
size_t i;
char prefixed[255];
if (!list)
return false;
prefixed[0] = '\0';
strlcpy(prefixed, prefix, sizeof(prefixed));
strlcat(prefixed, elem, sizeof(prefixed));
for (i = 0; i < list->size; i++)
{
size_t i;
char prefixed[255];
size_t _len = strlcpy(prefixed, prefix, sizeof(prefixed));
strlcpy(prefixed + _len, elem, sizeof(prefixed) - _len);
for (i = 0; i < list->size; i++)
{
if ( string_is_equal_noncase(list->elems[i].data, elem)
|| string_is_equal_noncase(list->elems[i].data, prefixed))
return true;
}
if (string_is_equal_noncase(list->elems[i].data, elem) ||
string_is_equal_noncase(list->elems[i].data, prefixed))
return true;
}
return false;
}
struct string_list *string_list_clone(const struct string_list *src)
struct string_list *string_list_clone(
const struct string_list *src)
{
size_t i;
unsigned i;
struct string_list_elem *elems = NULL;
struct string_list *dest = (struct string_list*)
malloc(sizeof(struct string_list));
calloc(1, sizeof(struct string_list));
if (!dest)
return NULL;
dest->elems = NULL;
dest->size = src->size;
if (src->cap < dest->size)
dest->cap = dest->size;
else
dest->cap = src->cap;
dest->size = src->size;
dest->cap = src->cap;
if (dest->cap < dest->size)
dest->cap = dest->size;
if (!(elems = (struct string_list_elem*)
calloc(dest->cap, sizeof(struct string_list_elem))))
elems = (struct string_list_elem*)
calloc(dest->cap, sizeof(struct string_list_elem));
if (!elems)
{
free(dest);
return NULL;
}
dest->elems = elems;
dest->elems = elems;
for (i = 0; i < src->size; i++)
{
const char *_src = src->elems[i].data;
size_t len = _src ? strlen(_src) : 0;
const char *_src = src->elems[i].data;
size_t len = _src ? strlen(_src) : 0;
dest->elems[i].data = NULL;
dest->elems[i].attr = src->elems[i].attr;
dest->elems[i].data = NULL;
dest->elems[i].attr = src->elems[i].attr;
if (len != 0)
{

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (memalign.c).

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (memmap.c).
@ -21,7 +21,6 @@
*/
#include <stdint.h>
#include <stdlib.h>
#include <memmap.h>
#ifndef PROT_READ
@ -131,14 +130,14 @@ int mprotect(void *addr, size_t len, int prot)
#endif
#if defined(__MACH__) && (defined(__arm__) || defined(__arm64__))
#if defined(__MACH__) && defined(__arm__)
#include <libkern/OSCacheControl.h>
#endif
int memsync(void *start, void *end)
{
size_t len = (char*)end - (char*)start;
#if defined(__MACH__) && (defined(__arm__) || defined(__arm64__))
#if defined(__MACH__) && defined(__arm__)
sys_dcache_flush(start ,len);
sys_icache_invalidate(start, len);
return 0;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (file_stream.c).
@ -25,27 +25,17 @@
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#include <errno.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef _MSC_VER
#include <compat/msvc.h>
#endif
#include <string/stdstring.h>
#include <streams/file_stream.h>
#define VFS_FRONTEND
#include <vfs/vfs_implementation.h>
#define VFS_ERROR_RETURN_VALUE -1
struct RFILE
{
struct retro_vfs_file_handle *hfile;
bool error_flag;
};
static const int64_t vfs_error_return_value = -1;
static retro_vfs_get_path_t filestream_get_path_cb = NULL;
static retro_vfs_open_t filestream_open_cb = NULL;
@ -60,12 +50,18 @@ static retro_vfs_flush_t filestream_flush_cb = NULL;
static retro_vfs_remove_t filestream_remove_cb = NULL;
static retro_vfs_rename_t filestream_rename_cb = NULL;
struct RFILE
{
struct retro_vfs_file_handle *hfile;
bool error_flag;
bool eof_flag;
};
/* VFS Initialization */
void filestream_vfs_init(const struct retro_vfs_interface_info* vfs_info)
{
const struct retro_vfs_interface *
vfs_iface = vfs_info->iface;
const struct retro_vfs_interface* vfs_iface;
filestream_get_path_cb = NULL;
filestream_open_cb = NULL;
@ -80,9 +76,9 @@ void filestream_vfs_init(const struct retro_vfs_interface_info* vfs_info)
filestream_remove_cb = NULL;
filestream_rename_cb = NULL;
if (
(vfs_info->required_interface_version <
FILESTREAM_REQUIRED_VFS_VERSION)
vfs_iface = vfs_info->iface;
if (vfs_info->required_interface_version < FILESTREAM_REQUIRED_VFS_VERSION
|| !vfs_iface)
return;
@ -103,20 +99,19 @@ void filestream_vfs_init(const struct retro_vfs_interface_info* vfs_info)
/* Callback wrappers */
bool filestream_exists(const char *path)
{
RFILE *dummy = NULL;
RFILE *dummy = NULL;
if (!path || !*path)
return false;
if (!(dummy = filestream_open(
path,
dummy = filestream_open(path,
RETRO_VFS_FILE_ACCESS_READ,
RETRO_VFS_FILE_ACCESS_HINT_NONE)))
RETRO_VFS_FILE_ACCESS_HINT_NONE);
if (!dummy)
return false;
if (filestream_close(dummy) != 0)
free(dummy);
dummy = NULL;
filestream_close(dummy);
return true;
}
@ -124,13 +119,12 @@ int64_t filestream_get_size(RFILE *stream)
{
int64_t output;
if (filestream_size_cb)
if (filestream_size_cb != NULL)
output = filestream_size_cb(stream->hfile);
else
output = retro_vfs_file_size_impl(
(libretro_vfs_implementation_file*)stream->hfile);
output = retro_vfs_file_size_impl((libretro_vfs_implementation_file*)stream->hfile);
if (output == VFS_ERROR_RETURN_VALUE)
if (output == vfs_error_return_value)
stream->error_flag = true;
return output;
@ -140,13 +134,12 @@ int64_t filestream_truncate(RFILE *stream, int64_t length)
{
int64_t output;
if (filestream_truncate_cb)
if (filestream_truncate_cb != NULL)
output = filestream_truncate_cb(stream->hfile, length);
else
output = retro_vfs_file_truncate_impl(
(libretro_vfs_implementation_file*)stream->hfile, length);
output = retro_vfs_file_truncate_impl((libretro_vfs_implementation_file*)stream->hfile, length);
if (output == VFS_ERROR_RETURN_VALUE)
if (output == vfs_error_return_value)
stream->error_flag = true;
return output;
@ -159,14 +152,14 @@ int64_t filestream_truncate(RFILE *stream, int64_t length)
* @hints :
*
* Opens a file for reading or writing, depending on the requested mode.
* @return A pointer to an RFILE if opened successfully, otherwise NULL.
* Returns a pointer to an RFILE if opened successfully, otherwise NULL.
**/
RFILE* filestream_open(const char *path, unsigned mode, unsigned hints)
RFILE *filestream_open(const char *path, unsigned mode, unsigned hints)
{
struct retro_vfs_file_handle *fp = NULL;
RFILE* output = NULL;
if (filestream_open_cb)
if (filestream_open_cb != NULL)
fp = (struct retro_vfs_file_handle*)
filestream_open_cb(path, mode, hints);
else
@ -178,11 +171,12 @@ RFILE* filestream_open(const char *path, unsigned mode, unsigned hints)
output = (RFILE*)malloc(sizeof(RFILE));
output->error_flag = false;
output->eof_flag = false;
output->hfile = fp;
return output;
}
char* filestream_gets(RFILE *stream, char *s, size_t len)
char *filestream_gets(RFILE *stream, char *s, size_t len)
{
int c = 0;
char *p = s;
@ -209,19 +203,22 @@ char* filestream_gets(RFILE *stream, char *s, size_t len)
int filestream_getc(RFILE *stream)
{
char c = 0;
if (stream && filestream_read(stream, &c, 1) == 1)
if (!stream)
return EOF;
if (filestream_read(stream, &c, 1) == 1)
return (int)(unsigned char)c;
return EOF;
}
int filestream_vscanf(RFILE *stream, const char* format, va_list *args)
int filestream_scanf(RFILE *stream, const char* format, ...)
{
char buf[4096];
char subfmt[64];
va_list args_copy;
const char *bufiter = buf;
int ret = 0;
va_list args;
const char * bufiter = buf;
int64_t startpos = filestream_tell(stream);
int ret = 0;
int64_t maxlen = filestream_read(stream, buf, sizeof(buf)-1);
if (maxlen <= 0)
@ -229,22 +226,14 @@ int filestream_vscanf(RFILE *stream, const char* format, va_list *args)
buf[maxlen] = '\0';
/* Have to copy the input va_list here
* > Calling va_arg() on 'args' directly would
* cause the va_list to have an indeterminate value
* in the function calling filestream_vscanf(),
* leading to unexpected behaviour */
#ifdef __va_copy
__va_copy(args_copy, *args);
#else
va_copy(args_copy, *args);
#endif
va_start(args, format);
while (*format)
{
if (*format == '%')
{
int sublen;
char* subfmtiter = subfmt;
bool asterisk = false;
@ -254,25 +243,19 @@ int filestream_vscanf(RFILE *stream, const char* format, va_list *args)
if (*format == '*')
{
asterisk = true;
asterisk = true;
*subfmtiter++ = *format++;
}
while (ISDIGIT((unsigned char)*format))
*subfmtiter++ = *format++; /* width */
while (isdigit(*format)) *subfmtiter++ = *format++; /* width */
/* length */
if (*format == 'h' || *format == 'l')
{
if (format[1] == format[0])
*subfmtiter++ = *format++;
*subfmtiter++ = *format++;
if (format[1] == format[0]) *subfmtiter++ = *format++;
*subfmtiter++ = *format++;
}
else if (
*format == 'j' ||
*format == 'z' ||
*format == 't' ||
*format == 'L')
else if (*format == 'j' || *format == 'z' || *format == 't' || *format == 'L')
{
*subfmtiter++ = *format++;
}
@ -280,44 +263,31 @@ int filestream_vscanf(RFILE *stream, const char* format, va_list *args)
/* specifier - always a single character (except ]) */
if (*format == '[')
{
while (*format != ']')
*subfmtiter++ = *format++;
*subfmtiter++ = *format++;
while (*format != ']') *subfmtiter++ = *format++;
*subfmtiter++ = *format++;
}
else
*subfmtiter++ = *format++;
else *subfmtiter++ = *format++;
*subfmtiter++ = '%';
*subfmtiter++ = 'n';
*subfmtiter++ = '\0';
if (sizeof(void*) != sizeof(long*))
abort(); /* all pointers must have the same size */
*subfmtiter++ = '%';
*subfmtiter++ = 'n';
*subfmtiter++ = '\0';
if (sizeof(void*) != sizeof(long*)) abort(); /* all pointers must have the same size */
if (asterisk)
{
int v = sscanf(bufiter, subfmt, &sublen);
if (v == EOF)
return EOF;
if (v != 0)
break;
if (sscanf(bufiter, subfmt, &sublen) != 0) break;
}
else
{
int v = sscanf(bufiter, subfmt, va_arg(args_copy, void*), &sublen);
if (v == EOF)
return EOF;
if (v != 1)
break;
if (sscanf(bufiter, subfmt, va_arg(args, void*), &sublen) != 1) break;
}
ret++;
bufiter += sublen;
}
else if (isspace((unsigned char)*format))
else if (isspace(*format))
{
while (isspace((unsigned char)*bufiter))
bufiter++;
while (isspace(*bufiter)) bufiter++;
format++;
}
else
@ -329,56 +299,43 @@ int filestream_vscanf(RFILE *stream, const char* format, va_list *args)
}
}
va_end(args_copy);
filestream_seek(stream, startpos + (bufiter - buf),
RETRO_VFS_SEEK_POSITION_START);
va_end(args);
filestream_seek(stream, startpos+(bufiter-buf), RETRO_VFS_SEEK_POSITION_START);
return ret;
}
int filestream_scanf(RFILE *stream, const char* format, ...)
{
int result;
va_list vl;
va_start(vl, format);
result = filestream_vscanf(stream, format, &vl);
va_end(vl);
return result;
}
int64_t filestream_seek(RFILE *stream, int64_t offset, int seek_position)
{
int64_t output;
if (filestream_seek_cb)
if (filestream_seek_cb != NULL)
output = filestream_seek_cb(stream->hfile, offset, seek_position);
else
output = retro_vfs_file_seek_impl(
(libretro_vfs_implementation_file*)stream->hfile,
offset, seek_position);
output = retro_vfs_file_seek_impl((libretro_vfs_implementation_file*)stream->hfile, offset, seek_position);
if (output == VFS_ERROR_RETURN_VALUE)
if (output == vfs_error_return_value)
stream->error_flag = true;
stream->eof_flag = false;
return output;
}
int filestream_eof(RFILE *stream)
{
return filestream_tell(stream) == filestream_get_size(stream) ? EOF : 0;
return stream->eof_flag;
}
int64_t filestream_tell(RFILE *stream)
{
int64_t output;
if (filestream_size_cb)
if (filestream_size_cb != NULL)
output = filestream_tell_cb(stream->hfile);
else
output = retro_vfs_file_tell_impl(
(libretro_vfs_implementation_file*)stream->hfile);
output = retro_vfs_file_tell_impl((libretro_vfs_implementation_file*)stream->hfile);
if (output == VFS_ERROR_RETURN_VALUE)
if (output == vfs_error_return_value)
stream->error_flag = true;
return output;
@ -390,20 +347,23 @@ void filestream_rewind(RFILE *stream)
return;
filestream_seek(stream, 0L, RETRO_VFS_SEEK_POSITION_START);
stream->error_flag = false;
stream->eof_flag = false;
}
int64_t filestream_read(RFILE *stream, void *s, int64_t len)
{
int64_t output;
if (filestream_read_cb)
if (filestream_read_cb != NULL)
output = filestream_read_cb(stream->hfile, s, len);
else
output = retro_vfs_file_read_impl(
(libretro_vfs_implementation_file*)stream->hfile, s, len);
if (output == VFS_ERROR_RETURN_VALUE)
if (output == vfs_error_return_value)
stream->error_flag = true;
if (output < len)
stream->eof_flag = true;
return output;
}
@ -412,13 +372,12 @@ int filestream_flush(RFILE *stream)
{
int output;
if (filestream_flush_cb)
if (filestream_flush_cb != NULL)
output = filestream_flush_cb(stream->hfile);
else
output = retro_vfs_file_flush_impl(
(libretro_vfs_implementation_file*)stream->hfile);
output = retro_vfs_file_flush_impl((libretro_vfs_implementation_file*)stream->hfile);
if (output == VFS_ERROR_RETURN_VALUE)
if (output == vfs_error_return_value)
stream->error_flag = true;
return output;
@ -426,7 +385,7 @@ int filestream_flush(RFILE *stream)
int filestream_delete(const char *path)
{
if (filestream_remove_cb)
if (filestream_remove_cb != NULL)
return filestream_remove_cb(path);
return retro_vfs_file_remove_impl(path);
@ -434,32 +393,30 @@ int filestream_delete(const char *path)
int filestream_rename(const char *old_path, const char *new_path)
{
if (filestream_rename_cb)
if (filestream_rename_cb != NULL)
return filestream_rename_cb(old_path, new_path);
return retro_vfs_file_rename_impl(old_path, new_path);
}
const char* filestream_get_path(RFILE *stream)
const char *filestream_get_path(RFILE *stream)
{
if (filestream_get_path_cb)
if (filestream_get_path_cb != NULL)
return filestream_get_path_cb(stream->hfile);
return retro_vfs_file_get_path_impl(
(libretro_vfs_implementation_file*)stream->hfile);
return retro_vfs_file_get_path_impl((libretro_vfs_implementation_file*)stream->hfile);
}
int64_t filestream_write(RFILE *stream, const void *s, int64_t len)
{
int64_t output;
if (filestream_write_cb)
if (filestream_write_cb != NULL)
output = filestream_write_cb(stream->hfile, s, len);
else
output = retro_vfs_file_write_impl(
(libretro_vfs_implementation_file*)stream->hfile, s, len);
output = retro_vfs_file_write_impl((libretro_vfs_implementation_file*)stream->hfile, s, len);
if (output == VFS_ERROR_RETURN_VALUE)
if (output == vfs_error_return_value)
stream->error_flag = true;
return output;
@ -470,16 +427,13 @@ int filestream_putc(RFILE *stream, int c)
char c_char = (char)c;
if (!stream)
return EOF;
return filestream_write(stream, &c_char, 1) == 1
? (int)(unsigned char)c
: EOF;
return filestream_write(stream, &c_char, 1)==1 ? (int)(unsigned char)c : EOF;
}
int filestream_vprintf(RFILE *stream, const char* format, va_list args)
{
static char buffer[8 * 1024];
int64_t num_chars = vsnprintf(buffer, sizeof(buffer),
format, args);
int64_t num_chars = vsprintf(buffer, format, args);
if (num_chars < 0)
return -1;
@ -501,7 +455,9 @@ int filestream_printf(RFILE *stream, const char* format, ...)
int filestream_error(RFILE *stream)
{
return (stream && stream->error_flag);
if (stream && stream->error_flag)
return 1;
return 0;
}
int filestream_close(RFILE *stream)
@ -509,11 +465,10 @@ int filestream_close(RFILE *stream)
int output;
struct retro_vfs_file_handle* fp = stream->hfile;
if (filestream_close_cb)
if (filestream_close_cb != NULL)
output = filestream_close_cb(fp);
else
output = retro_vfs_file_close_impl(
(libretro_vfs_implementation_file*)fp);
output = retro_vfs_file_close_impl((libretro_vfs_implementation_file*)fp);
if (output == 0)
free(stream);
@ -526,11 +481,10 @@ int filestream_close(RFILE *stream)
* @path : path to file.
* @buf : buffer to allocate and read the contents of the
* file into. Needs to be freed manually.
* @len : optional output integer containing bytes read.
*
* Read the contents of a file into @buf.
*
* @return Non-zero on success.
* Returns: number of items read, -1 on error.
*/
int64_t filestream_read_file(const char *path, void **buf, int64_t *len)
{
@ -543,24 +497,30 @@ int64_t filestream_read_file(const char *path, void **buf, int64_t *len)
if (!file)
{
*buf = NULL;
return 0;
fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
goto error;
}
if ((content_buf_size = filestream_get_size(file)) < 0)
content_buf_size = filestream_get_size(file);
if (content_buf_size < 0)
goto error;
if (!(content_buf = malloc((size_t)(content_buf_size + 1))))
content_buf = malloc((size_t)(content_buf_size + 1));
if (!content_buf)
goto error;
if ((int64_t)(uint64_t)(content_buf_size + 1) != (content_buf_size + 1))
goto error;
if ((ret = filestream_read(file, content_buf, (int64_t)content_buf_size)) <
0)
ret = filestream_read(file, content_buf, (int64_t)content_buf_size);
if (ret < 0)
{
fprintf(stderr, "Failed to read %s: %s\n", path, strerror(errno));
goto error;
}
if (filestream_close(file) != 0)
free(file);
filestream_close(file);
*buf = content_buf;
@ -574,8 +534,8 @@ int64_t filestream_read_file(const char *path, void **buf, int64_t *len)
return 1;
error:
if (filestream_close(file) != 0)
free(file);
if (file)
filestream_close(file);
if (content_buf)
free(content_buf);
if (len)
@ -592,8 +552,8 @@ error:
*
* Writes data to a file.
*
* @return true on success, otherwise false.
**/
* Returns: true (1) on success, false (0) otherwise.
*/
bool filestream_write_file(const char *path, const void *data, int64_t size)
{
int64_t ret = 0;
@ -602,24 +562,23 @@ bool filestream_write_file(const char *path, const void *data, int64_t size)
RETRO_VFS_FILE_ACCESS_HINT_NONE);
if (!file)
return false;
ret = filestream_write(file, data, size);
if (filestream_close(file) != 0)
free(file);
return (ret == size);
filestream_close(file);
if (ret != size)
return false;
return true;
}
/**
* filestream_getline:
*
* Returned pointer must be freed by the caller.
**/
char *filestream_getline(RFILE *stream)
{
char *newline_tmp = NULL;
char* newline_tmp = NULL;
size_t cur_size = 8;
size_t idx = 0;
int in = 0;
char *newline = (char*)malloc(9);
char* newline = (char*)malloc(9);
if (!stream || !newline)
{
@ -628,15 +587,16 @@ char *filestream_getline(RFILE *stream)
return NULL;
}
in = filestream_getc(stream);
in = filestream_getc(stream);
while (in != EOF && in != '\n')
{
if (idx == cur_size)
{
cur_size *= 2;
newline_tmp = (char*)realloc(newline, cur_size + 1);
if (!(newline_tmp = (char*)realloc(newline, cur_size + 1)))
if (!newline_tmp)
{
free(newline);
return NULL;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (file_stream_transforms.c).
@ -37,7 +37,7 @@ RFILE* rfopen(const char *path, const char *mode)
retro_mode = RETRO_VFS_FILE_ACCESS_READ;
if (strstr(mode, "+"))
{
retro_mode = RETRO_VFS_FILE_ACCESS_READ_WRITE |
retro_mode = RETRO_VFS_FILE_ACCESS_READ_WRITE |
RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING;
}
}
@ -49,12 +49,12 @@ RFILE* rfopen(const char *path, const char *mode)
}
else if (strstr(mode, "a"))
{
retro_mode = RETRO_VFS_FILE_ACCESS_WRITE |
retro_mode = RETRO_VFS_FILE_ACCESS_WRITE |
RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING;
position_to_end = true;
if (strstr(mode, "+"))
{
retro_mode = RETRO_VFS_FILE_ACCESS_READ_WRITE |
retro_mode = RETRO_VFS_FILE_ACCESS_READ_WRITE |
RETRO_VFS_FILE_ACCESS_UPDATE_EXISTING;
}
}
@ -69,27 +69,17 @@ RFILE* rfopen(const char *path, const char *mode)
int rfclose(RFILE* stream)
{
if (!stream)
return EOF;
return filestream_close(stream);
}
int64_t rftell(RFILE* stream)
{
if (!stream)
return -1;
return filestream_tell(stream);
}
int64_t rfseek(RFILE* stream, int64_t offset, int origin)
{
int seek_position = -1;
if (!stream)
return -1;
switch (origin)
{
case SEEK_SET:
@ -109,65 +99,38 @@ int64_t rfseek(RFILE* stream, int64_t offset, int origin)
int64_t rfread(void* buffer,
size_t elem_size, size_t elem_count, RFILE* stream)
{
if (!stream || (elem_size == 0) || (elem_count == 0))
return 0;
return (filestream_read(stream, buffer, elem_size * elem_count) / elem_size);
return filestream_read(stream, buffer, elem_size * elem_count);
}
char *rfgets(char *buffer, int maxCount, RFILE* stream)
{
if (!stream)
return NULL;
return filestream_gets(stream, buffer, maxCount);
}
int rfgetc(RFILE* stream)
{
if (!stream)
return EOF;
return filestream_getc(stream);
return filestream_getc(stream);
}
int64_t rfwrite(void const* buffer,
size_t elem_size, size_t elem_count, RFILE* stream)
{
if (!stream || (elem_size == 0) || (elem_count == 0))
return 0;
return (filestream_write(stream, buffer, elem_size * elem_count) / elem_size);
return filestream_write(stream, buffer, elem_size * elem_count);
}
int rfputc(int character, RFILE * stream)
{
if (!stream)
return EOF;
return filestream_putc(stream, character);
}
int64_t rfflush(RFILE * stream)
{
if (!stream)
return EOF;
return filestream_flush(stream);
return filestream_putc(stream, character);
}
int rfprintf(RFILE * stream, const char * format, ...)
{
int result;
va_list vl;
if (!stream)
return -1;
va_start(vl, format);
result = filestream_vprintf(stream, format, vl);
va_end(vl);
return result;
va_list vl;
va_start(vl, format);
result = filestream_vprintf(stream, format, vl);
va_end(vl);
return result;
}
int rferror(RFILE* stream)
@ -179,17 +142,3 @@ int rfeof(RFILE* stream)
{
return filestream_eof(stream);
}
int rfscanf(RFILE * stream, const char * format, ...)
{
int result;
va_list vl;
if (!stream)
return 0;
va_start(vl, format);
result = filestream_vscanf(stream, format, &vl);
va_end(vl);
return result;
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2018 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (stdstring.c).
@ -22,44 +22,10 @@
#include <stdint.h>
#include <ctype.h>
#include <string.h>
#include <compat/strl.h>
#include <string/stdstring.h>
#include <encodings/utf.h>
const uint8_t lr_char_props[256] = {
/*x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x80,0x00,0x00, /* 0x */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 1x */
0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 2x !"#$%&'()*+,-./ */
0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x00,0x00,0x00,0x00,0x00,0x00, /* 3x 0123456789:;<=>? */
0x00,0x23,0x23,0x23,0x23,0x23,0x23,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22, /* 4x @ABCDEFGHIJKLMNO */
0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x22,0x00,0x00,0x00,0x00,0x08, /* 5x PQRSTUVWXYZ[\]^_ */
0x00,0x25,0x25,0x25,0x25,0x25,0x25,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24, /* 6x `abcdefghijklmno */
0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x00,0x00,0x00,0x00,0x00, /* 7x pqrstuvwxyz{|}~ */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 8x */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 9x */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Ax */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Bx */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Cx */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Dx */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Ex */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* Fx */
};
char *string_init(const char *src)
{
return src ? strdup(src) : NULL;
}
void string_set(char **string, const char *src)
{
free(*string);
*string = string_init(src);
}
char *string_to_upper(char *s)
{
char *cs = (char *)s;
@ -90,11 +56,9 @@ char *string_ucwords(char *s)
}
char *string_replace_substring(const char *in,
const char *pattern, size_t pattern_len,
const char *replacement, size_t replacement_len)
const char *pattern, const char *replacement)
{
size_t outlen;
size_t numhits = 0;
size_t numhits, pattern_len, replacement_len, outlen;
const char *inat = NULL;
const char *inprev = NULL;
char *out = NULL;
@ -105,6 +69,9 @@ char *string_replace_substring(const char *in,
if (!pattern || !replacement)
return strdup(in);
pattern_len = strlen(pattern);
replacement_len = strlen(replacement);
numhits = 0;
inat = in;
while ((inat = strstr(inat, pattern)))
@ -114,8 +81,9 @@ char *string_replace_substring(const char *in,
}
outlen = strlen(in) - pattern_len*numhits + replacement_len*numhits;
out = (char *)malloc(outlen+1);
if (!(out = (char *)malloc(outlen+1)))
if (!out)
return NULL;
outat = out;
@ -128,7 +96,7 @@ char *string_replace_substring(const char *in,
outat += inat-inprev;
memcpy(outat, replacement, replacement_len);
outat += replacement_len;
inat += pattern_len;
inat += pattern_len;
inprev = inat;
}
strcpy(outat, inprev);
@ -136,60 +104,48 @@ char *string_replace_substring(const char *in,
return out;
}
/**
* string_trim_whitespace_left:
*
* Remove leading whitespaces
**/
/* Remove leading whitespaces */
char *string_trim_whitespace_left(char *const s)
{
if (s && *s)
if(s && *s)
{
size_t len = strlen(s);
char *current = s;
while (*current && ISSPACE((unsigned char)*current))
while(*current && isspace((unsigned char)*current))
{
++current;
--len;
}
if (s != current)
if(s != current)
memmove(s, current, len + 1);
}
return s;
}
/**
* string_trim_whitespace_right:
*
* Remove trailing whitespaces
**/
/* Remove trailing whitespaces */
char *string_trim_whitespace_right(char *const s)
{
if (s && *s)
if(s && *s)
{
size_t len = strlen(s);
char *current = s + len - 1;
while (current != s && ISSPACE((unsigned char)*current))
while(current != s && isspace((unsigned char)*current))
{
--current;
--len;
}
current[ISSPACE((unsigned char)*current) ? 0 : 1] = '\0';
current[isspace((unsigned char)*current) ? 0 : 1] = '\0';
}
return s;
}
/**
* string_trim_whitespace:
*
* Remove leading and trailing whitespaces
**/
/* Remove leading and trailing whitespaces */
char *string_trim_whitespace(char *const s)
{
string_trim_whitespace_right(s); /* order matters */
@ -198,512 +154,86 @@ char *string_trim_whitespace(char *const s)
return s;
}
/**
* word_wrap:
* @dst : pointer to destination buffer.
* @dst_size : size of destination buffer.
* @src : pointer to input string.
* @line_width : max number of characters per line.
* @wideglyph_width : not used, but is necessary to keep
* compatibility with word_wrap_wideglyph().
* @max_lines : max lines of destination string.
* 0 means no limit.
*
* Wraps string specified by 'src' to destination buffer
* specified by 'dst' and 'dst_size'.
* This function assumes that all glyphs in the string
* have an on-screen pixel width similar to that of
* regular Latin characters - i.e. it will not wrap
* correctly any text containing so-called 'wide' Unicode
* characters (e.g. CJK languages, emojis, etc.).
**/
size_t word_wrap(
char *dst, size_t dst_size,
const char *src, size_t src_len,
int line_width, int wideglyph_width, unsigned max_lines)
char *word_wrap(char* buffer, const char *string, int line_width, bool unicode, unsigned max_lines)
{
char *last_space = NULL;
unsigned counter = 0;
unsigned lines = 1;
const char *src_end = src + src_len;
unsigned i = 0;
unsigned len = (unsigned)strlen(string);
unsigned lines = 1;
/* Prevent buffer overflow */
if (dst_size < src_len + 1)
return 0;
/* Early return if src string length is less
* than line width */
if (src_len < (size_t)line_width)
return strlcpy(dst, src, dst_size);
while (*src != '\0')
while (i < len)
{
unsigned char_len = (unsigned)(utf8skip(src, 1) - src);
counter++;
unsigned counter;
int pos = (int)(&buffer[i] - buffer);
if (*src == ' ')
last_space = dst; /* Remember the location of the whitespace */
else if (*src == '\n')
/* copy string until the end of the line is reached */
for (counter = 1; counter <= (unsigned)line_width; counter++)
{
/* If newlines embedded in the input,
* reset the index */
lines++;
counter = 0;
const char *character;
unsigned char_len;
unsigned j = i;
/* Early return if remaining src string
* length is less than line width */
if (src_end - src <= line_width)
return strlcpy(dst, src, dst_size);
}
while (char_len--)
*dst++ = *src++;
if (counter >= (unsigned)line_width)
{
counter = 0;
if (last_space && (max_lines == 0 || lines < max_lines))
/* check if end of string reached */
if (i == len)
{
buffer[i] = 0;
return buffer;
}
character = utf8skip(&string[i], 1);
char_len = (unsigned)(character - &string[i]);
if (!unicode)
counter += char_len - 1;
do
{
buffer[i] = string[i];
char_len--;
i++;
} while(char_len);
/* check for newlines embedded in the original input
* and reset the index */
if (buffer[j] == '\n')
{
/* Replace nearest (previous) whitespace
* with newline character */
*last_space = '\n';
lines++;
src -= dst - last_space - 1;
dst = last_space + 1;
last_space = NULL;
/* Early return if remaining src string
* length is less than line width */
if (src_end - src < line_width)
return strlcpy(dst, src, dst_size);
counter = 1;
}
}
}
*dst = '\0';
return 0;
}
/**
* word_wrap_wideglyph:
* @dst : pointer to destination buffer.
* @dst_size : size of destination buffer.
* @src : pointer to input string.
* @line_width : max number of characters per line.
* @wideglyph_width : effective width of 'wide' Unicode glyphs.
* the value here is normalised relative to the
* typical on-screen pixel width of a regular
* Latin character:
* - a regular Latin character is defined to
* have an effective width of 100
* - wideglyph_width = 100 * (wide_character_pixel_width / latin_character_pixel_width)
* - e.g. if 'wide' Unicode characters in 'src'
* have an on-screen pixel width twice that of
* regular Latin characters, wideglyph_width
* would be 200
* @max_lines : max lines of destination string.
* 0 means no limit.
*
* Wraps string specified by @src to destination buffer
* specified by @dst and @dst_size.
* This function assumes that all glyphs in the string
* are:
* - EITHER 'non-wide' Unicode glyphs, with an on-screen
* pixel width similar to that of regular Latin characters
* - OR 'wide' Unicode glyphs (e.g. CJK languages, emojis, etc.)
* with an on-screen pixel width defined by @wideglyph_width
* Note that wrapping may occur in inappropriate locations
* if @src string contains 'wide' Unicode characters whose
* on-screen pixel width deviates greatly from the set
* @wideglyph_width value.
**/
size_t word_wrap_wideglyph(char *dst, size_t dst_size,
const char *src, size_t src_len, int line_width,
int wideglyph_width, unsigned max_lines)
{
char *lastspace = NULL;
char *lastwideglyph = NULL;
const char *src_end = src + src_len;
unsigned lines = 1;
/* 'line_width' means max numbers of characters per line,
* but this metric is only meaningful when dealing with
* 'regular' glyphs that have an on-screen pixel width
* similar to that of regular Latin characters.
* When handing so-called 'wide' Unicode glyphs, it is
* necessary to consider the actual on-screen pixel width
* of each character.
* In order to do this, we create a distinction between
* regular Latin 'non-wide' glyphs and 'wide' glyphs, and
* normalise all values relative to the on-screen pixel
* width of regular Latin characters:
* - Regular 'non-wide' glyphs have a normalised width of 100
* - 'line_width' is therefore normalised to 100 * (width_in_characters)
* - 'wide' glyphs have a normalised width of
* 100 * (wide_character_pixel_width / latin_character_pixel_width)
* - When a character is detected, the position in the current
* line is incremented by the regular normalised width of 100
* - If that character is then determined to be a 'wide'
* glyph, the position in the current line is further incremented
* by the difference between the normalised 'wide' and 'non-wide'
* width values */
unsigned counter_normalized = 0;
int line_width_normalized = line_width * 100;
int additional_counter_normalized = wideglyph_width - 100;
/* Early return if src string length is less
* than line width */
if (src_end - src < line_width)
return strlcpy(dst, src, dst_size);
while (*src != '\0')
{
unsigned char_len = (unsigned)(utf8skip(src, 1) - src);
counter_normalized += 100;
/* Prevent buffer overflow */
if (char_len >= dst_size)
break;
if (*src == ' ')
lastspace = dst; /* Remember the location of the whitespace */
else if (*src == '\n')
/* check for whitespace */
if (string[i] == ' ')
{
/* If newlines embedded in the input,
* reset the index */
lines++;
counter_normalized = 0;
/* Early return if remaining src string
* length is less than line width */
if (src_end - src <= line_width)
return strlcpy(dst, src, dst_size);
}
else if (char_len >= 3)
{
/* Remember the location of the first byte
* whose length as UTF-8 >= 3*/
lastwideglyph = dst;
counter_normalized += additional_counter_normalized;
}
dst_size -= char_len;
while (char_len--)
*dst++ = *src++;
if (counter_normalized >= (unsigned)line_width_normalized)
{
counter_normalized = 0;
if (max_lines != 0 && lines >= max_lines)
continue;
else if (lastwideglyph && (!lastspace || lastwideglyph > lastspace))
if ((max_lines == 0 || lines < max_lines))
{
/* Insert newline character */
*lastwideglyph = '\n';
buffer[i] = '\n';
i++;
lines++;
src -= dst - lastwideglyph;
dst = lastwideglyph + 1;
lastwideglyph = NULL;
/* Early return if remaining src string
* length is less than line width */
if (src_end - src <= line_width)
return strlcpy(dst, src, dst_size);
}
else if (lastspace)
{
/* Replace nearest (previous) whitespace
* with newline character */
*lastspace = '\n';
lines++;
src -= dst - lastspace - 1;
dst = lastspace + 1;
lastspace = NULL;
/* Early return if remaining src string
* length is less than line width */
if (src_end - src < line_width)
return strlcpy(dst, src, dst_size);
}
}
}
*dst = '\0';
return 0;
}
/**
* string_tokenize:
*
* Splits string into tokens seperated by @delim
* > Returned token string must be free()'d
* > Returns NULL if token is not found
* > After each call, @str is set to the position after the
* last found token
* > Tokens *include* empty strings
* Usage example:
* char *str = "1,2,3,4,5,6,7,,,10,";
* char **str_ptr = &str;
* char *token = NULL;
* while ((token = string_tokenize(str_ptr, ",")))
* {
* printf("%s\n", token);
* free(token);
* token = NULL;
* }
**/
char* string_tokenize(char **str, const char *delim)
{
/* Taken from https://codereview.stackexchange.com/questions/216956/strtok-function-thread-safe-supports-empty-tokens-doesnt-change-string# */
char *str_ptr = NULL;
char *delim_ptr = NULL;
char *token = NULL;
size_t token_len = 0;
/* Sanity checks */
if (!str || string_is_empty(delim))
return NULL;
/* Note: we don't check string_is_empty() here,
* empty strings are valid */
if (!(str_ptr = *str))
return NULL;
/* Search for delimiter */
if ((delim_ptr = strstr(str_ptr, delim)))
token_len = delim_ptr - str_ptr;
else
token_len = strlen(str_ptr);
/* Allocate token string */
if (!(token = (char *)malloc((token_len + 1) * sizeof(char))))
return NULL;
/* Copy token */
strlcpy(token, str_ptr, (token_len + 1) * sizeof(char));
token[token_len] = '\0';
/* Update input string pointer */
*str = delim_ptr ? delim_ptr + strlen(delim) : NULL;
return token;
}
/**
* string_remove_all_chars:
* @str : input string (must be non-NULL, otherwise UB)
*
* Leaf function.
*
* Removes every instance of character @c from @str
**/
void string_remove_all_chars(char *str, char c)
{
char *read_ptr = str;
char *write_ptr = str;
while (*read_ptr != '\0')
{
*write_ptr = *read_ptr++;
if (*write_ptr != c)
write_ptr++;
}
*write_ptr = '\0';
}
/**
* string_replace_all_chars:
* @str : input string (must be non-NULL, otherwise UB)
* @find : character to find
* @replace : character to replace @find with
*
* Replaces every instance of character @find in @str
* with character @replace
**/
void string_replace_all_chars(char *str, char find, char replace)
{
char *str_ptr = str;
while ((str_ptr = strchr(str_ptr, find)))
*str_ptr++ = replace;
}
/**
* string_to_unsigned:
* @str : input string
*
* Converts string to unsigned integer.
*
* @return 0 if string is invalid, otherwise > 0
**/
unsigned string_to_unsigned(const char *str)
{
const char *ptr = NULL;
if (string_is_empty(str))
return 0;
for (ptr = str; *ptr != '\0'; ptr++)
{
if (!ISDIGIT((unsigned char)*ptr))
return 0;
}
return (unsigned)strtoul(str, NULL, 10);
}
/**
* string_hex_to_unsigned:
* @str : input string (must be non-NULL, otherwise UB)
*
* Converts hexadecimal string to unsigned integer.
* Handles optional leading '0x'.
*
* @return 0 if string is invalid, otherwise > 0
**/
unsigned string_hex_to_unsigned(const char *str)
{
const char *hex_str = str;
const char *ptr = NULL;
/* Remove leading '0x', if required */
if (str[0] != '\0' && str[1] != '\0')
{
if ( (str[0] == '0') &&
((str[1] == 'x') ||
(str[1] == 'X')))
else
{
hex_str = str + 2;
if (string_is_empty(hex_str))
return 0;
int k;
/* check for nearest whitespace back in string */
for (k = i; k > 0; k--)
{
if (string[k] != ' ' || (max_lines != 0 && lines >= max_lines))
continue;
buffer[k] = '\n';
/* set string index back to character after this one */
i = k + 1;
lines++;
break;
}
if (&buffer[i] - buffer == pos)
return buffer;
}
}
else
return 0;
/* Check for valid characters */
for (ptr = hex_str; *ptr != '\0'; ptr++)
{
if (!isxdigit((unsigned char)*ptr))
return 0;
}
buffer[i] = 0;
return (unsigned)strtoul(hex_str, NULL, 16);
}
/**
* string_count_occurrences_single_character:
*
* Leaf function.
*
* Get the total number of occurrences of character @c in @str.
*
* @return Total number of occurrences of character @c
*/
int string_count_occurrences_single_character(const char *str, char c)
{
int count = 0;
for (; *str; str++)
if (*str == c)
count++;
return count;
}
/**
* string_replace_whitespace_with_single_character:
*
* Leaf function.
*
* Replaces all spaces with given character @c.
**/
void string_replace_whitespace_with_single_character(char *str, char c)
{
for (; *str; str++)
if (ISSPACE(*str))
*str = c;
}
/**
* string_replace_multi_space_with_single_space:
*
* Leaf function.
*
* Replaces multiple spaces with a single space in a string.
**/
void string_replace_multi_space_with_single_space(char *str)
{
char *str_trimmed = str;
bool prev_is_space = false;
bool curr_is_space = false;
for (; *str; str++)
{
curr_is_space = ISSPACE(*str);
if (prev_is_space && curr_is_space)
continue;
*str_trimmed++ = *str;
prev_is_space = curr_is_space;
}
*str_trimmed = '\0';
}
/**
* string_remove_all_whitespace:
*
* Leaf function.
*
* Remove all spaces from the given string.
**/
void string_remove_all_whitespace(char *str_trimmed, const char *str)
{
for (; *str; str++)
if (!ISSPACE(*str))
*str_trimmed++ = *str;
*str_trimmed = '\0';
}
/**
* Retrieve the last occurance of the given character in a string.
*/
int string_index_last_occurance(const char *str, char c)
{
const char *pos = strrchr(str, c);
if (pos)
return (int)(pos - str);
return -1;
}
/**
* string_find_index_substring_string:
* @str : input string (must be non-NULL, otherwise UB)
* @substr : substring to find in @str
*
* Find the position of substring @substr in string @str.
**/
int string_find_index_substring_string(const char *str, const char *substr)
{
const char *pos = strstr(str, substr);
if (pos)
return (int)(pos - str);
return -1;
}
/**
* string_copy_only_ascii:
*
* Leaf function.
*
* Strips non-ASCII characters from a string.
**/
void string_copy_only_ascii(char *str_stripped, const char *str)
{
for (; *str; str++)
if (*str > 0x1F && *str < 0x7F)
*str_stripped++ = *str;
*str_stripped = '\0';
return buffer;
}

View File

@ -1,78 +0,0 @@
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (rtime.c).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifdef HAVE_THREADS
#include <rthreads/rthreads.h>
#include <stdlib.h>
#endif
#include <string.h>
#include <time/rtime.h>
#ifdef HAVE_THREADS
/* TODO/FIXME - global */
slock_t *rtime_localtime_lock = NULL;
#endif
/* Must be called before using rtime_localtime() */
void rtime_init(void)
{
rtime_deinit();
#ifdef HAVE_THREADS
if (!rtime_localtime_lock)
rtime_localtime_lock = slock_new();
#endif
}
/* Must be called upon program termination */
void rtime_deinit(void)
{
#ifdef HAVE_THREADS
if (rtime_localtime_lock)
{
slock_free(rtime_localtime_lock);
rtime_localtime_lock = NULL;
}
#endif
}
/* Thread-safe wrapper for localtime() */
struct tm *rtime_localtime(const time_t *timep, struct tm *result)
{
struct tm *time_info = NULL;
/* Lock mutex */
#ifdef HAVE_THREADS
slock_lock(rtime_localtime_lock);
#endif
time_info = localtime(timep);
if (time_info)
memcpy(result, time_info, sizeof(struct tm));
/* Unlock mutex */
#ifdef HAVE_THREADS
slock_unlock(rtime_localtime_lock);
#endif
return result;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2010-2020 The RetroArch team
/* Copyright (C) 2010-2019 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (vfs_implementation_cdrom.c).
@ -30,7 +30,6 @@
#include <windows.h>
#endif
/* TODO/FIXME - static global variable */
static cdrom_toc_t vfs_cdrom_toc = {0};
const cdrom_toc_t* retro_vfs_file_get_cdrom_toc(void)
@ -38,9 +37,7 @@ const cdrom_toc_t* retro_vfs_file_get_cdrom_toc(void)
return &vfs_cdrom_toc;
}
int64_t retro_vfs_file_seek_cdrom(
libretro_vfs_implementation_file *stream,
int64_t offset, int whence)
int64_t retro_vfs_file_seek_cdrom(libretro_vfs_implementation_file *stream, int64_t offset, int whence)
{
const char *ext = path_get_extension(stream->orig_path);
@ -55,84 +52,68 @@ int64_t retro_vfs_file_seek_cdrom(
stream->cdrom.byte_pos += offset;
break;
case SEEK_END:
stream->cdrom.byte_pos = (stream->cdrom.cue_len - 1) + offset;
stream->cdrom.byte_pos = (stream->cdrom.cue_len - 1) + offset;
break;
}
#ifdef CDROM_DEBUG
printf("[CDROM] Seek: Path %s Offset %" PRIu64 " is now at %" PRIu64 "\n",
stream->orig_path,
offset,
stream->cdrom.byte_pos);
printf("[CDROM] Seek: Path %s Offset %" PRIu64 " is now at %" PRIu64 "\n", stream->orig_path, offset, stream->cdrom.byte_pos);
fflush(stdout);
#endif
}
else if (string_is_equal_noncase(ext, "bin"))
{
int lba = (offset / 2352);
unsigned char min = 0;
unsigned char sec = 0;
unsigned char frame = 0;
#ifdef CDROM_DEBUG
int lba = (offset / 2352);
unsigned char min = 0;
unsigned char sec = 0;
unsigned char frame = 0;
const char *seek_type = "SEEK_SET";
#endif
(void)seek_type;
switch (whence)
{
case SEEK_CUR:
{
unsigned new_lba;
#ifdef CDROM_DEBUG
seek_type = "SEEK_CUR";
#endif
stream->cdrom.byte_pos += offset;
new_lba = vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba + (stream->cdrom.byte_pos / 2352);
{
unsigned new_lba;
stream->cdrom.byte_pos += offset;
new_lba = vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba + (stream->cdrom.byte_pos / 2352);
seek_type = "SEEK_CUR";
cdrom_lba_to_msf(new_lba, &min, &sec, &frame);
cdrom_lba_to_msf(new_lba, &min, &sec, &frame);
}
break;
}
case SEEK_END:
{
ssize_t pregap_lba_len = (vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].audio
? 0
: (vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba - vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba_start));
ssize_t lba_len = vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].track_size - pregap_lba_len;
#ifdef CDROM_DEBUG
seek_type = "SEEK_END";
#endif
{
ssize_t pregap_lba_len = (vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].audio ? 0 : (vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba - vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba_start));
ssize_t lba_len = vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].track_size - pregap_lba_len;
cdrom_lba_to_msf(lba_len + lba, &min, &sec, &frame);
stream->cdrom.byte_pos = lba_len * 2352;
seek_type = "SEEK_END";
cdrom_lba_to_msf(lba_len + lba, &min, &sec, &frame);
stream->cdrom.byte_pos = lba_len * 2352;
}
break;
}
case SEEK_SET:
default:
{
#ifdef CDROM_DEBUG
seek_type = "SEEK_SET";
#endif
stream->cdrom.byte_pos = offset;
cdrom_lba_to_msf(vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba + (stream->cdrom.byte_pos / 2352), &min, &sec, &frame);
}
{
seek_type = "SEEK_SET";
stream->cdrom.byte_pos = offset;
cdrom_lba_to_msf(vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba + (stream->cdrom.byte_pos / 2352), &min, &sec, &frame);
break;
}
}
stream->cdrom.cur_min = min;
stream->cdrom.cur_sec = sec;
stream->cdrom.cur_min = min;
stream->cdrom.cur_sec = sec;
stream->cdrom.cur_frame = frame;
stream->cdrom.cur_lba = cdrom_msf_to_lba(min, sec, frame);
stream->cdrom.cur_lba = cdrom_msf_to_lba(min, sec, frame);
#ifdef CDROM_DEBUG
printf(
"[CDROM] Seek %s: Path %s Offset %" PRIu64 " is now at %" PRIu64 " (MSF %02u:%02u:%02u) (LBA %u)...\n",
seek_type,
stream->orig_path,
offset,
stream->cdrom.byte_pos,
(unsigned)stream->cdrom.cur_min,
(unsigned)stream->cdrom.cur_sec,
(unsigned)stream->cdrom.cur_frame,
stream->cdrom.cur_lba);
printf("[CDROM] Seek %s: Path %s Offset %" PRIu64 " is now at %" PRIu64 " (MSF %02u:%02u:%02u) (LBA %u)...\n", seek_type, stream->orig_path, offset, stream->cdrom.byte_pos, (unsigned)stream->cdrom.cur_min, (unsigned)stream->cdrom.cur_sec, (unsigned)stream->cdrom.cur_frame, stream->cdrom.cur_lba);
fflush(stdout);
#endif
}
@ -147,21 +128,20 @@ void retro_vfs_file_open_cdrom(
const char *path, unsigned mode, unsigned hints)
{
#if defined(__linux__) && !defined(ANDROID)
char cdrom_path[] = "/dev/sg1";
size_t path_len = strlen(path);
const char *ext = path_get_extension(path);
char cdrom_path[] = "/dev/sg1";
size_t path_len = strlen(path);
const char *ext = path_get_extension(path);
stream->cdrom.cur_track = 1;
if ( !string_is_equal_noncase(ext, "cue")
&& !string_is_equal_noncase(ext, "bin"))
if (!string_is_equal_noncase(ext, "cue") && !string_is_equal_noncase(ext, "bin"))
return;
if (path_len >= STRLEN_CONST("drive1-track01.bin"))
if (path_len >= strlen("drive1-track01.bin"))
{
if (!memcmp(path, "drive", STRLEN_CONST("drive")))
if (!memcmp(path, "drive", strlen("drive")))
{
if (!memcmp(path + 6, "-track", STRLEN_CONST("-track")))
if (!memcmp(path + 6, "-track", strlen("-track")))
{
if (sscanf(path + 12, "%02u", (unsigned*)&stream->cdrom.cur_track))
{
@ -174,13 +154,13 @@ void retro_vfs_file_open_cdrom(
}
}
if (path_len >= STRLEN_CONST("drive1.cue"))
if (path_len >= strlen("drive1.cue"))
{
if (!memcmp(path, "drive", STRLEN_CONST("drive")))
if (!memcmp(path, "drive", strlen("drive")))
{
if (path[5] >= '0' && path[5] <= '9')
{
cdrom_path[7] = path[5];
cdrom_path[7] = path[5];
stream->cdrom.drive = path[5];
vfs_cdrom_toc.drive = stream->cdrom.drive;
}
@ -204,12 +184,7 @@ void retro_vfs_file_open_cdrom(
stream->cdrom.cue_buf = NULL;
}
cdrom_write_cue(stream,
&stream->cdrom.cue_buf,
&stream->cdrom.cue_len,
stream->cdrom.drive,
&vfs_cdrom_toc.num_tracks,
&vfs_cdrom_toc);
cdrom_write_cue(stream, &stream->cdrom.cue_buf, &stream->cdrom.cue_len, stream->cdrom.drive, &vfs_cdrom_toc.num_tracks, &vfs_cdrom_toc);
cdrom_get_timeouts(stream, &vfs_cdrom_toc.timeouts);
#ifdef CDROM_DEBUG
@ -228,16 +203,15 @@ void retro_vfs_file_open_cdrom(
#endif
#if defined(_WIN32) && !defined(_XBOX)
char cdrom_path[] = "\\\\.\\D:";
size_t path_len = strlen(path);
const char *ext = path_get_extension(path);
size_t path_len = strlen(path);
const char *ext = path_get_extension(path);
if ( !string_is_equal_noncase(ext, "cue")
&& !string_is_equal_noncase(ext, "bin"))
if (!string_is_equal_noncase(ext, "cue") && !string_is_equal_noncase(ext, "bin"))
return;
if (path_len >= STRLEN_CONST("d:/drive-track01.bin"))
if (path_len >= strlen("d:/drive-track01.bin"))
{
if (!memcmp(path + 1, ":/drive-track", STRLEN_CONST(":/drive-track")))
if (!memcmp(path + 1, ":/drive-track", strlen(":/drive-track")))
{
if (sscanf(path + 14, "%02u", (unsigned*)&stream->cdrom.cur_track))
{
@ -249,13 +223,13 @@ void retro_vfs_file_open_cdrom(
}
}
if (path_len >= STRLEN_CONST("d:/drive.cue"))
if (path_len >= strlen("d:/drive.cue"))
{
if (!memcmp(path + 1, ":/drive", STRLEN_CONST(":/drive")))
if (!memcmp(path + 1, ":/drive", strlen(":/drive")))
{
if ((path[0] >= 'A' && path[0] <= 'Z') || (path[0] >= 'a' && path[0] <= 'z'))
{
cdrom_path[4] = path[0];
cdrom_path[4] = path[0];
stream->cdrom.drive = path[0];
vfs_cdrom_toc.drive = stream->cdrom.drive;
}
@ -266,13 +240,7 @@ void retro_vfs_file_open_cdrom(
printf("[CDROM] Open: Path %s URI %s\n", cdrom_path, path);
fflush(stdout);
#endif
stream->fh = CreateFile(cdrom_path,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
stream->fh = CreateFile(cdrom_path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (stream->fh == INVALID_HANDLE_VALUE)
return;
@ -285,14 +253,8 @@ void retro_vfs_file_open_cdrom(
stream->cdrom.cue_buf = NULL;
}
cdrom_write_cue(stream,
&stream->cdrom.cue_buf,
&stream->cdrom.cue_len,
stream->cdrom.drive,
&vfs_cdrom_toc.num_tracks,
&vfs_cdrom_toc);
cdrom_get_timeouts(stream,
&vfs_cdrom_toc.timeouts);
cdrom_write_cue(stream, &stream->cdrom.cue_buf, &stream->cdrom.cue_len, stream->cdrom.drive, &vfs_cdrom_toc.num_tracks, &vfs_cdrom_toc);
cdrom_get_timeouts(stream, &vfs_cdrom_toc.timeouts);
#ifdef CDROM_DEBUG
if (string_is_empty(stream->cdrom.cue_buf))
@ -310,17 +272,17 @@ void retro_vfs_file_open_cdrom(
#endif
if (vfs_cdrom_toc.num_tracks > 1 && stream->cdrom.cur_track)
{
stream->cdrom.cur_min = vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].min;
stream->cdrom.cur_sec = vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].sec;
stream->cdrom.cur_min = vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].min;
stream->cdrom.cur_sec = vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].sec;
stream->cdrom.cur_frame = vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].frame;
stream->cdrom.cur_lba = cdrom_msf_to_lba(stream->cdrom.cur_min, stream->cdrom.cur_sec, stream->cdrom.cur_frame);
stream->cdrom.cur_lba = cdrom_msf_to_lba(stream->cdrom.cur_min, stream->cdrom.cur_sec, stream->cdrom.cur_frame);
}
else
{
stream->cdrom.cur_min = vfs_cdrom_toc.track[0].min;
stream->cdrom.cur_sec = vfs_cdrom_toc.track[0].sec;
stream->cdrom.cur_min = vfs_cdrom_toc.track[0].min;
stream->cdrom.cur_sec = vfs_cdrom_toc.track[0].sec;
stream->cdrom.cur_frame = vfs_cdrom_toc.track[0].frame;
stream->cdrom.cur_lba = cdrom_msf_to_lba(stream->cdrom.cur_min, stream->cdrom.cur_sec, stream->cdrom.cur_frame);
stream->cdrom.cur_lba = cdrom_msf_to_lba(stream->cdrom.cur_min, stream->cdrom.cur_sec, stream->cdrom.cur_frame);
}
}
@ -378,69 +340,52 @@ int64_t retro_vfs_file_read_cdrom(libretro_vfs_implementation_file *stream,
if (string_is_equal_noncase(ext, "cue"))
{
if ((int64_t)len >= (int64_t)stream->cdrom.cue_len
- stream->cdrom.byte_pos)
len = stream->cdrom.cue_len - stream->cdrom.byte_pos - 1;
if (len < stream->cdrom.cue_len - stream->cdrom.byte_pos)
{
#ifdef CDROM_DEBUG
printf(
"[CDROM] Read: Reading %" PRIu64 " bytes from cuesheet starting at %" PRIu64 "...\n",
len,
stream->cdrom.byte_pos);
fflush(stdout);
printf("[CDROM] Read: Reading %" PRIu64 " bytes from cuesheet starting at %" PRIu64 "...\n", len, stream->cdrom.byte_pos);
fflush(stdout);
#endif
memcpy(s, stream->cdrom.cue_buf + stream->cdrom.byte_pos, len);
stream->cdrom.byte_pos += len;
memcpy(s, stream->cdrom.cue_buf + stream->cdrom.byte_pos, len);
stream->cdrom.byte_pos += len;
return len;
return len;
}
else
{
#ifdef CDROM_DEBUG
printf("[CDROM] Read: Reading %" PRIu64 " bytes from cuesheet starting at %" PRIu64 " failed.\n", len, stream->cdrom.byte_pos);
fflush(stdout);
#endif
return 0;
}
}
else if (string_is_equal_noncase(ext, "bin"))
{
unsigned char min = 0;
unsigned char sec = 0;
unsigned char frame = 0;
unsigned char rmin = 0;
unsigned char rsec = 0;
size_t skip = stream->cdrom.byte_pos % 2352;
unsigned char min = 0;
unsigned char sec = 0;
unsigned char frame = 0;
unsigned char rmin = 0;
unsigned char rsec = 0;
unsigned char rframe = 0;
size_t skip = stream->cdrom.byte_pos % 2352;
if (stream->cdrom.byte_pos >=
vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].track_bytes)
if (stream->cdrom.byte_pos >= vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].track_bytes)
return 0;
if (stream->cdrom.byte_pos + len >
vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].track_bytes)
len -= (stream->cdrom.byte_pos + len)
- vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].track_bytes;
if (stream->cdrom.byte_pos + len > vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].track_bytes)
len -= (stream->cdrom.byte_pos + len) - vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].track_bytes;
cdrom_lba_to_msf(stream->cdrom.cur_lba, &min, &sec, &frame);
cdrom_lba_to_msf(stream->cdrom.cur_lba
- vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba,
&rmin, &rsec, &rframe);
cdrom_lba_to_msf(stream->cdrom.cur_lba - vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba, &rmin, &rsec, &rframe);
#ifdef CDROM_DEBUG
printf(
"[CDROM] Read: Reading %" PRIu64 " bytes from %s starting at byte offset %" PRIu64 " (rMSF %02u:%02u:%02u aMSF %02u:%02u:%02u) (LBA %u) skip %" PRIu64 "...\n",
len,
stream->orig_path,
stream->cdrom.byte_pos,
(unsigned)rmin,
(unsigned)rsec,
(unsigned)rframe,
(unsigned)min,
(unsigned)sec,
(unsigned)frame,
stream->cdrom.cur_lba,
skip);
printf("[CDROM] Read: Reading %" PRIu64 " bytes from %s starting at byte offset %" PRIu64 " (rMSF %02u:%02u:%02u aMSF %02u:%02u:%02u) (LBA %u) skip %" PRIu64 "...\n", len, stream->orig_path, stream->cdrom.byte_pos, (unsigned)rmin, (unsigned)rsec, (unsigned)rframe, (unsigned)min, (unsigned)sec, (unsigned)frame, stream->cdrom.cur_lba, skip);
fflush(stdout);
#endif
#if 1
rv = cdrom_read(stream, &vfs_cdrom_toc.timeouts, min, sec,
frame, s, (size_t)len, skip);
#else
rv = cdrom_read_lba(stream, stream->cdrom.cur_lba, s,
(size_t)len, skip);
#endif
rv = cdrom_read(stream, &vfs_cdrom_toc.timeouts, min, sec, frame, s, (size_t)len, skip);
/*rv = cdrom_read_lba(stream, stream->cdrom.cur_lba, s, (size_t)len, skip);*/
if (rv)
{
@ -452,28 +397,12 @@ int64_t retro_vfs_file_read_cdrom(libretro_vfs_implementation_file *stream,
}
stream->cdrom.byte_pos += len;
stream->cdrom.cur_lba =
vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba
+ (stream->cdrom.byte_pos / 2352);
stream->cdrom.cur_lba = vfs_cdrom_toc.track[stream->cdrom.cur_track - 1].lba + (stream->cdrom.byte_pos / 2352);
cdrom_lba_to_msf(stream->cdrom.cur_lba,
&stream->cdrom.cur_min,
&stream->cdrom.cur_sec,
&stream->cdrom.cur_frame);
cdrom_lba_to_msf(stream->cdrom.cur_lba, &stream->cdrom.cur_min, &stream->cdrom.cur_sec, &stream->cdrom.cur_frame);
#ifdef CDROM_DEBUG
printf(
"[CDROM] read %" PRIu64 " bytes, position is now: %" PRIu64 " (MSF %02u:%02u:%02u) (LBA %u)\n",
len,
stream->cdrom.byte_pos,
(unsigned)stream->cdrom.cur_min,
(unsigned)stream->cdrom.cur_sec,
(unsigned)stream->cdrom.cur_frame,
cdrom_msf_to_lba(
stream->cdrom.cur_min,
stream->cdrom.cur_sec,
stream->cdrom.cur_frame)
);
printf("[CDROM] read %" PRIu64 " bytes, position is now: %" PRIu64 " (MSF %02u:%02u:%02u) (LBA %u)\n", len, stream->cdrom.byte_pos, (unsigned)stream->cdrom.cur_min, (unsigned)stream->cdrom.cur_sec, (unsigned)stream->cdrom.cur_frame, cdrom_msf_to_lba(stream->cdrom.cur_min, stream->cdrom.cur_sec, stream->cdrom.cur_frame));
fflush(stdout);
#endif
@ -488,8 +417,7 @@ int retro_vfs_file_error_cdrom(libretro_vfs_implementation_file *stream)
return 0;
}
const vfs_cdrom_t* retro_vfs_file_get_cdrom_position(
const libretro_vfs_implementation_file *stream)
const vfs_cdrom_t* retro_vfs_file_get_cdrom_position(const libretro_vfs_implementation_file *stream)
{
return &stream->cdrom;
}

File diff suppressed because it is too large Load Diff