ifeq "$(PLATFORM)" "libretro"
OBJS += platform/libretro/libretro.o
ifeq "$(USE_LIBRETRO_VFS)" "1"
+OBJS += platform/libretro/libretro-common/compat/compat_strcasestr.o
OBJS += platform/libretro/libretro-common/compat/compat_posix_string.o
OBJS += platform/libretro/libretro-common/compat/compat_strl.o
OBJS += platform/libretro/libretro-common/compat/fopen_utf8.o
+OBJS += platform/libretro/libretro-common/memmap/memmap.o
OBJS += platform/libretro/libretro-common/encodings/encoding_utf.o
+OBJS += platform/libretro/libretro-common/string/stdstring.o
OBJS += platform/libretro/libretro-common/streams/file_stream.o
OBJS += platform/libretro/libretro-common/streams/file_stream_transforms.o
OBJS += platform/libretro/libretro-common/vfs/vfs_implementation.o
AR = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-ar.exe
CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ -DFAMEC_NO_GOTOS
STATIC_LINKING = 1
- NO_MMAP = 1
# PS3 has memory mapped in a way not suitable for DRC
use_sh2drc = 0
use_svpdrc = 0
AR = $(CELL_SDK)/host-win32/sn/bin/ps3snarl.exe
CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ -DFAMEC_NO_GOTOS
STATIC_LINKING = 1
- NO_MMAP = 1
# PS3 has memory mapped in a way not suitable for DRC
use_sh2drc = 0
use_svpdrc = 0
AR = $(PS3DEV)/ppu/bin/ppu-ar$(EXE_EXT)
CFLAGS += -DBLARGG_BIG_ENDIAN=1 -D__ppc__ -DFAMEC_NO_GOTOS
STATIC_LINKING = 1
- NO_MMAP = 1
# PS3 has memory mapped in a way not suitable for DRC
use_sh2drc = 0
use_svpdrc = 0
CFLAGS += -G0 -ftracer
CFLAGS += -DPSP
STATIC_LINKING = 1
- NO_MMAP = 1
# PS2
else ifeq ($(platform), ps2)
CFLAGS += -I$(PS2DEV)/gsKit/include -I$(PS2SDK)/ee/include -I$(PS2SDK)/common/include
CFLAGS += -DHAVE_NO_LANGEXTRA
STATIC_LINKING = 1
- NO_MMAP = 1
# CTR (3DS)
else ifeq ($(platform), ctr)
CFLAGS += -Wall -mword-relocations
CFLAGS += -fomit-frame-pointer -ffast-math
STATIC_LINKING = 1
- NO_MMAP = 1
OBJS += platform/libretro/3ds/3ds_utils.o platform/libretro/3ds/utils.o
CFLAGS += -mword-relocations -fno-unwind-tables
CFLAGS += -fno-optimize-sibling-calls
STATIC_LINKING = 1
- NO_MMAP = 1
# Xbox 360
else ifeq ($(platform), xenon)
AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT)
CFLAGS += -DGEKKO -DHW_DOL -mrvl -mcpu=750 -meabi -mhard-float -D__ppc__ -DMSB_FIRST
STATIC_LINKING = 1
- NO_MMAP = 1
# Nintendo Wii
else ifeq ($(platform), wii)
AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT)
CFLAGS += -DGEKKO -DHW_RVL -mrvl -mcpu=750 -meabi -mhard-float -D__ppc__ -DMSB_FIRST
STATIC_LINKING = 1
- NO_MMAP = 1
# Nintendo Wii U
else ifeq ($(platform), wiiu)
AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT)
CFLAGS += -DGEKKO -DWIIU -DHW_RVL -DHW_WUP -mwup -mcpu=750 -meabi -mhard-float -D__ppc__ -DMSB_FIRST
STATIC_LINKING = 1
- NO_MMAP = 1
# Nintendo Switch (libtransistor)
else ifeq ($(platform), switch)
TARGET := $(TARGET_NAME)_libretro_$(platform).a
include $(LIBTRANSISTOR_HOME)/libtransistor.mk
STATIC_LINKING=1
- NO_MMAP = 1
# Nintendo Switch (libnx)
else ifeq ($(platform), libnx)
CFLAGS += -DNO_ZLIB -D__LIBRETRO__
ifeq ($(USE_LIBRETRO_VFS),1)
- NO_MMAP = 1
CFLAGS += -DUSE_LIBRETRO_VFS
endif
-ifeq ($(NO_MMAP),1)
- CFLAGS += -DNO_MMAP
-endif
-
ifeq ($(NO_ARM_ASM),1)
use_cyclone = 0
use_fame = 1
-/* Copyright (C) 2010-2018 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (compat_posix_string.c).
--- /dev/null
+/* Copyright (C) 2010-2020 The RetroArch team
+ *
+ * ---------------------------------------------------------------------------------------
+ * The following license statement only applies to this file (compat_strcasestr.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.
+ */
+
+#include <ctype.h>
+
+#include <compat/strcasestr.h>
+
+/* Pretty much strncasecmp. */
+static int casencmp(const char *a, const char *b, size_t n)
+{
+ size_t i;
+
+ for (i = 0; i < n; i++)
+ {
+ int a_lower = tolower(a[i]);
+ int b_lower = tolower(b[i]);
+ if (a_lower != b_lower)
+ return a_lower - b_lower;
+ }
+
+ return 0;
+}
+
+char *strcasestr_retro__(const char *haystack, const char *needle)
+{
+ size_t i, search_off;
+ size_t hay_len = strlen(haystack);
+ size_t needle_len = strlen(needle);
+
+ if (needle_len > hay_len)
+ return NULL;
+
+ search_off = hay_len - needle_len;
+ for (i = 0; i <= search_off; i++)
+ if (!casencmp(haystack + i, needle, needle_len))
+ return (char*)haystack + i;
+
+ return NULL;
+}
-/* Copyright (C) 2010-2018 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (compat_strl.c).
-/* Copyright (C) 2010-2018 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (fopen_utf8.c).
#else
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);
+ FILE* ret = NULL;
+
+ if (filename_w && mode_w)
+ ret = _wfopen(filename_w, mode_w);
+ if (filename_w)
+ free(filename_w);
+ if (mode_w)
+ free(mode_w);
return ret;
#endif
}
-/* Copyright (C) 2010-2018 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (encoding_utf.c).
#include <xtl.h>
#endif
+#define UTF8_WALKBYTE(string) (*((*(string))++))
+
static unsigned leading_ones(uint8_t c)
{
unsigned ones = 0;
bool utf16_conv_utf8(uint8_t *out, size_t *out_chars,
const uint16_t *in, size_t in_size)
{
- static uint8_t kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
- size_t out_pos = 0;
- size_t in_pos = 0;
+ size_t out_pos = 0;
+ size_t in_pos = 0;
+ static const
+ uint8_t utf8_limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
for (;;)
{
- unsigned numAdds;
+ unsigned num_adds;
uint32_t value;
if (in_pos == in_size)
value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000;
}
- for (numAdds = 1; numAdds < 5; numAdds++)
- if (value < (((uint32_t)1) << (numAdds * 5 + 6)))
+ for (num_adds = 1; num_adds < 5; num_adds++)
+ if (value < (((uint32_t)1) << (num_adds * 5 + 6)))
break;
if (out)
- out[out_pos] = (char)(kUtf8Limits[numAdds - 1]
- + (value >> (6 * numAdds)));
+ out[out_pos] = (char)(utf8_limits[num_adds - 1]
+ + (value >> (6 * num_adds)));
out_pos++;
do
{
- numAdds--;
+ num_adds--;
if (out)
out[out_pos] = (char)(0x80
- + ((value >> (6 * numAdds)) & 0x3F));
+ + ((value >> (6 * num_adds)) & 0x3F));
out_pos++;
- }while (numAdds != 0);
+ }while (num_adds != 0);
}
*out_chars = out_pos;
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);
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;
}
return ret;
}
-#define utf8_walkbyte(string) (*((*(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);
+ ret = (ret << 6) | (UTF8_WALKBYTE(string) & 0x3F);
if (first >= 0xF0)
{
- ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F);
+ ret = (ret << 6) | (UTF8_WALKBYTE(string) & 0x3F);
return ret | (first & 7) << 18;
}
return ret | (first & 15) << 12;
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_len = 0;
int path_buf_wide_len = MultiByteToWideChar(cp_in, 0, str, -1, NULL, 0);
/* Windows 95 will return 0 from these functions with
* MultiByteToWideChar also supports CP_UTF7 and CP_UTF8.
*/
- if (path_buf_wide_len)
+ if (!path_buf_wide_len)
+ return strdup(str);
+
+ path_buf_wide = (wchar_t*)
+ calloc(path_buf_wide_len + sizeof(wchar_t), sizeof(wchar_t));
+
+ if (path_buf_wide)
{
- 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)
+ if (*path_buf_wide)
{
- MultiByteToWideChar(cp_in, 0,
- str, -1, path_buf_wide, path_buf_wide_len);
+ int path_buf_len = WideCharToMultiByte(cp_out, 0,
+ path_buf_wide, -1, NULL, 0, NULL, NULL);
- if (*path_buf_wide)
+ if (path_buf_len)
{
- path_buf_len = WideCharToMultiByte(cp_out, 0,
- path_buf_wide, -1, NULL, 0, NULL, NULL);
+ char *path_buf = (char*)
+ calloc(path_buf_len + sizeof(char), sizeof(char));
- if (path_buf_len)
+ if (path_buf)
{
- path_buf = (char*)
- calloc(path_buf_len + sizeof(char), sizeof(char));
+ WideCharToMultiByte(cp_out, 0,
+ path_buf_wide, -1, path_buf,
+ path_buf_len, NULL, NULL);
- if (path_buf)
- {
- WideCharToMultiByte(cp_out, 0,
- path_buf_wide, -1, path_buf,
- path_buf_len, NULL, NULL);
-
- free(path_buf_wide);
+ free(path_buf_wide);
- if (*path_buf)
- return path_buf;
+ if (*path_buf)
+ return path_buf;
- free(path_buf);
- return NULL;
- }
- }
- else
- {
- free(path_buf_wide);
- return strdup(str);
+ free(path_buf);
+ return NULL;
}
}
+ else
+ {
+ free(path_buf_wide);
+ return strdup(str);
+ }
}
- }
- else
- return strdup(str);
- if (path_buf_wide)
free(path_buf_wide);
+ }
return NULL;
}
wchar_t* utf8_to_utf16_string_alloc(const char *str)
{
#ifdef _WIN32
- int len = 0;
- int out_len = 0;
+ int len = 0;
+ int out_len = 0;
#else
- size_t len = 0;
+ size_t len = 0;
size_t out_len = 0;
#endif
- wchar_t *buf = NULL;
+ wchar_t *buf = NULL;
if (!str || !*str)
return NULL;
-/* Copyright (C) 2010-2018 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (boolean.h).
-/* Copyright (C) 2010-2018 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (apple_compat.h).
-/* Copyright (C) 2010-2018 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (fnmatch.h).
-/* Copyright (C) 2010-2018 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (fopen_utf8.h).
-/* Copyright (C) 2010-2018 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (getopt.h).
-/* Copyright (C) 2010-2018 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (intrinsics.h).
/* Count Leading Zero, unsigned 16bit input value */
static INLINE unsigned compat_clz_u16(uint16_t val)
{
-#if defined(__GNUC__) && !defined(PS2)
+#if defined(__GNUC__)
return __builtin_clz(val << 16 | 0x8000);
#else
unsigned ret = 0;
return __builtin_ctz(x);
#elif _MSC_VER >= 1400 && !defined(_XBOX) && !defined(__WINRT__)
unsigned long r = 0;
- _BitScanReverse((unsigned long*)&r, x);
+ _BitScanForward((unsigned long*)&r, x);
return (int)r;
#else
-/* 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;
+ 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;
#endif
}
-/* Copyright (C) 2010-2018 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (msvc.h).
extern "C" {
#endif
-/* Pre-MSVC 2015 compilers don't implement snprintf in a cross-platform manner. */
+/* Pre-MSVC 2015 compilers don't implement snprintf, vsnprintf 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, ...);
-#endif
-/* Pre-MSVC 2008 compilers don't implement vsnprintf in a cross-platform manner? Not sure about this one. */
-#if _MSC_VER < 1500
- #include <stdio.h>
- #include <stdarg.h>
- #include <stdlib.h>
#ifndef vsnprintf
#define vsnprintf c99_vsnprintf_retro__
#endif
-/* Copyright (C) 2010-2018 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (posix_string.h).
#include <compat/msvc.h>
#endif
-#if defined(PS2)
-#include <compat_ctype.h>
-#endif
-
RETRO_BEGIN_DECLS
#ifdef _WIN32
-/* Copyright (C) 2010-2018 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (strcasestr.h).
#include <string.h>
-#if defined(PS2)
-#include <compat_ctype.h>
-#endif
-
#if defined(RARCH_INTERNAL) && defined(HAVE_CONFIG_H)
#include "../../../config.h"
#endif
-/* Copyright (C) 2010-2018 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (strl.h).
-/* Copyright (C) 2010-2018 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (utf.h).
enum CodePage
{
CODEPAGE_LOCAL = 0, /* CP_ACP */
- CODEPAGE_UTF8 = 65001 /* CP_UTF8 */
+ CODEPAGE_UTF8 = 65001 /* CP_UTF8 */
};
size_t utf8_conv_utf32(uint32_t *out, size_t out_chars,
-/* Copyright (C) 2010-2019 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (file_path.h).
* Returns: basename from path.
**/
const char *path_basename(const char *path);
+const char *path_basename_nocompression(const char *path);
/**
* path_basedir:
*
* E.g. path /a/b/e/f.cgp with base /a/b/c/d/ turns into ../../e/f.cgp
**/
-void path_relative_to(char *out, const char *path, const char *base, size_t size);
+size_t path_relative_to(char *out, const char *path, const char *base, size_t size);
/**
* path_is_absolute:
* E.g.:
* out_filename = "RetroArch-{month}{day}-{Hours}{Minutes}.{@ext}"
**/
-void fill_dated_filename(char *out_filename,
+size_t fill_dated_filename(char *out_filename,
const char *ext, size_t size);
/**
* present in 'in_path', it will be ignored.
*
*/
-void fill_pathname_noext(char *out_path, const char *in_path,
+size_t fill_pathname_noext(char *out_path, const char *in_path,
const char *replace, size_t size);
/**
* E.g..: in_dir = "/tmp/some_dir", in_basename = "/some_content/foo.c",
* replace = ".asm" => in_dir = "/tmp/some_dir/foo.c.asm"
**/
-void fill_pathname_dir(char *in_dir, const char *in_basename,
+size_t fill_pathname_dir(char *in_dir, const char *in_basename,
const char *replace, size_t size);
/**
*
* Copies basename of @in_path into @out_path.
**/
-void fill_pathname_base(char *out_path, const char *in_path, size_t size);
+size_t 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,
+size_t fill_pathname_base_ext(char *out,
const char *in_path, const char *ext,
size_t size);
* Makes sure not to get two consecutive slashes
* between directory and path.
**/
-void fill_pathname_join(char *out_path, const char *dir,
+size_t fill_pathname_join(char *out_path, const char *dir,
const char *path, size_t size);
-void fill_pathname_join_special_ext(char *out_path,
+size_t 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,
+size_t 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,
+size_t fill_pathname_join_concat(char *out_path,
const char *dir, const char *path,
const char *concat,
size_t size);
* Joins a directory (@dir) and path (@path) together
* using the given delimiter (@delim).
**/
-void fill_pathname_join_delim(char *out_path, const char *dir,
+size_t fill_pathname_join_delim(char *out_path, const char *dir,
const char *path, const char delim, size_t size);
-void fill_pathname_join_delim_concat(char *out_path, const char *dir,
+size_t fill_pathname_join_delim_concat(char *out_path, const char *dir,
const char *path, const char delim, const char *concat,
size_t size);
* 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,
+size_t fill_short_pathname_representation(char* out_rep,
const char *in_path, size_t size);
void fill_short_pathname_representation_noext(char* out_rep,
void fill_pathname_abbreviate_special(char *out_path,
const char *in_path, size_t size);
+void fill_pathname_abbreviated_or_relative(char *out_path, const char *in_refpath, const char *in_path, size_t size);
+
+void pathname_conform_slashes_to_os(char *path);
+
+void pathname_make_slashes_portable(char *path);
+
/**
* path_basedir:
* @path : path
* 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
/**
* 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
/**
RETRO_LANGUAGE_HEBREW = 21,
RETRO_LANGUAGE_ASTURIAN = 22,
RETRO_LANGUAGE_FINNISH = 23,
+ RETRO_LANGUAGE_INDONESIAN = 24,
+ RETRO_LANGUAGE_SWEDISH = 25,
+ RETRO_LANGUAGE_UKRAINIAN = 26,
RETRO_LANGUAGE_LAST,
/* Ensure sizeof(enum) == sizeof(int) */
const char *default_value;
};
+#ifdef __PS3__
+#undef local
+#endif
+
struct retro_core_options_intl
{
/* Pointer to an array of retro_core_option_definition structs
-/* Copyright (C) 2010-2018 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (memmap.h).
#include <stdio.h>
#include <stdint.h>
-#if defined(__CELLOS_LV2__) || defined(PSP) || defined(PS2) || defined(GEKKO) || defined(VITA) || defined(_XBOX) || defined(_3DS) || defined(WIIU) || defined(SWITCH) || defined(HAVE_LIBNX)
+#if defined(PSP) || defined(PS2) || defined(GEKKO) || defined(VITA) || defined(_XBOX) || defined(_3DS) || defined(WIIU) || defined(SWITCH) || defined(HAVE_LIBNX) || defined(__PS3__) || defined(__PSL1GHT__)
/* No mman available */
#elif defined(_WIN32) && !defined(_XBOX)
#include <windows.h>
-/* Copyright (C) 2010-2018 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_common.h).
-/* Copyright (C) 2010-2018 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_common_api.h).
-/* Copyright (C) 2010-2019 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_dirent.h).
#include <libretro.h>
#include <retro_common_api.h>
-#include <retro_miscellaneous.h>
#include <boolean.h>
-/* Copyright (C) 2010-2018 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_endianness.h).
#define SWAP16 _byteswap_ushort
#define SWAP32 _byteswap_ulong
#else
-#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) \
- ))
+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);
+}
+
#endif
#if defined(_MSC_VER) && _MSC_VER <= 1200
-#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))
+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);
+}
#else
-#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))
+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);
+}
#endif
+
+#if defined (LSB_FIRST) || defined (MSB_FIRST)
+# warning Defining MSB_FIRST and LSB_FIRST in compile options is deprecated
+# undef LSB_FIRST
+# undef MSB_FIRST
+#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)
+#define LSB_FIRST 1
+#elif _M_PPC
+#define MSB_FIRST 1
+#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__
+#define MSB_FIRST 1
+#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#define LSB_FIRST 1
+#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:
*
* Returns: greater than 0 if little-endian,
* otherwise big-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
-static INLINE uint8_t is_little_endian(void)
-{
- union
- {
- uint16_t x;
- uint8_t y[2];
- } u;
-
- u.x = 1;
- return u.y[0];
-}
-#endif
+#define is_little_endian() RETRO_IS_LITTLE_ENDIAN
/**
* swap_if_big64:
* otherwise returns same value.
**/
-#if defined(MSB_FIRST)
+#if RETRO_IS_BIG_ENDIAN
#define swap_if_big64(val) (SWAP64(val))
-#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
+#elif RETRO_IS_LITTLE_ENDIAN
#define swap_if_big64(val) (val)
-#else
-static INLINE uint64_t swap_if_big64(uint64_t val)
-{
- if (is_little_endian())
- return val;
- return SWAP64(val);
-}
#endif
/**
* otherwise returns same value.
**/
-#if defined(MSB_FIRST)
+#if RETRO_IS_BIG_ENDIAN
#define swap_if_big32(val) (SWAP32(val))
-#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
+#elif RETRO_IS_LITTLE_ENDIAN
#define swap_if_big32(val) (val)
-#else
-static INLINE uint32_t swap_if_big32(uint32_t val)
-{
- if (is_little_endian())
- return val;
- return SWAP32(val);
-}
#endif
/**
* otherwise returns same value.
**/
-#if defined(MSB_FIRST)
+#if RETRO_IS_BIG_ENDIAN
#define swap_if_little64(val) (val)
-#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
+#elif RETRO_IS_LITTLE_ENDIAN
#define swap_if_little64(val) (SWAP64(val))
-#else
-static INLINE uint64_t swap_if_little64(uint64_t val)
-{
- if (is_little_endian())
- return SWAP64(val);
- return val;
-}
#endif
/**
* otherwise returns same value.
**/
-#if defined(MSB_FIRST)
+#if RETRO_IS_BIG_ENDIAN
#define swap_if_little32(val) (val)
-#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
+#elif RETRO_IS_LITTLE_ENDIAN
#define swap_if_little32(val) (SWAP32(val))
-#else
-static INLINE uint32_t swap_if_little32(uint32_t val)
-{
- if (is_little_endian())
- return SWAP32(val);
- return val;
-}
#endif
/**
* otherwise returns same value.
**/
-#if defined(MSB_FIRST)
+#if RETRO_IS_BIG_ENDIAN
#define swap_if_big16(val) (SWAP16(val))
-#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
+#elif RETRO_IS_LITTLE_ENDIAN
#define swap_if_big16(val) (val)
-#else
-static INLINE uint16_t swap_if_big16(uint16_t val)
-{
- if (is_little_endian())
- return val;
- return SWAP16(val);
-}
#endif
/**
* otherwise returns same value.
**/
-#if defined(MSB_FIRST)
+#if RETRO_IS_BIG_ENDIAN
#define swap_if_little16(val) (val)
-#elif defined(__x86_64) || defined(__i386) || defined(_M_IX86) || defined(_M_X64)
+#elif RETRO_IS_LITTLE_ENDIAN
#define swap_if_little16(val) (SWAP16(val))
-#else
-static INLINE uint16_t swap_if_little16(uint16_t val)
-{
- if (is_little_endian())
- return SWAP16(val);
- return val;
-}
#endif
/**
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
-/* Copyright (C) 2010-2018 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_environment.h).
-/* Copyright (C) 2010-2018 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_inline.h).
-/* Copyright (C) 2010-2018 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (retro_miscellaneous.h).
#include <boolean.h>
#include <retro_inline.h>
-#if defined(_WIN32) && !defined(_XBOX)
+#if defined(_WIN32)
+
+#if defined(_XBOX)
+#include <Xtl.h>
+#else
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
-#elif defined(_WIN32) && defined(_XBOX)
-#include <Xtl.h>
#endif
-#if defined(__CELLOS_LV2__)
-#include <sys/fs_external.h>
#endif
#include <limits.h>
}
#ifndef PATH_MAX_LENGTH
-#if defined(__CELLOS_LV2__)
-#define PATH_MAX_LENGTH CELL_FS_MAX_FS_PATH_LENGTH
-#elif defined(_XBOX1) || defined(_3DS) || defined(PSP) || defined(PS2) || defined(GEKKO)|| defined(WIIU) || defined(ORBIS)
+#if defined(_XBOX1) || defined(_3DS) || defined(PSP) || defined(PS2) || defined(GEKKO)|| defined(WIIU) || defined(ORBIS) || defined(__PSL1GHT__) || defined(__PS3__)
#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
#define BIT16_GET(a, bit) (((a) >> ((bit) & 15)) & 1)
#define BIT16_CLEAR_ALL(a) ((a) = 0)
-#define BIT32_SET(a, bit) ((a) |= (1 << ((bit) & 31)))
-#define BIT32_CLEAR(a, bit) ((a) &= ~(1 << ((bit) & 31)))
+#define BIT32_SET(a, bit) ((a) |= (UINT32_C(1) << ((bit) & 31)))
+#define BIT32_CLEAR(a, bit) ((a) &= ~(UINT32_C(1) << ((bit) & 31)))
#define BIT32_GET(a, bit) (((a) >> ((bit) & 31)) & 1)
#define BIT32_CLEAR_ALL(a) ((a) = 0)
#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] |= (1 << ((bit) & 31)))
-#define BIT128_CLEAR(a, bit) ((a).data[(bit) >> 5] &= ~(1 << ((bit) & 31)))
+#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_GET(a, bit) (((a).data[(bit) >> 5] >> ((bit) & 31)) & 1)
#define BIT128_CLEAR_ALL(a) memset(&(a), 0, sizeof(a))
#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); \
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
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
# define PRI_SIZET "u"
# endif
# endif
-#elif PS2
+#elif defined(PS2)
# define PRI_SIZET "u"
#else
# if (SIZE_MAX == 0xFFFF)
-/* Copyright (C) 2010-2018 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (file_stream.h).
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);
-/* Copyright (C) 2010-2018 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (file_stream_transforms.h).
-/* Copyright (C) 2010-2019 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (stdstring.h).
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)
{
return !data || (*data == '\0');
return (a && b) ? !strcmp(a, b) : false;
}
-#define STRLEN_CONST(x) ((sizeof((x))-1))
+static INLINE bool string_starts_with_size(const char *str, const char *prefix,
+ size_t size)
+{
+ return (str && prefix) ? !strncmp(prefix, str, size) : false;
+}
-#define string_is_not_equal(a, b) !string_is_equal((a), (b))
+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)
+{
+ if (!str || !suffix)
+ return false;
+ return string_ends_with_size(str, suffix, strlen(str), strlen(suffix));
+}
+
+/* Returns 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;
+}
-#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)
static INLINE bool string_is_equal_case_insensitive(const char *a,
const char *b)
return (result == 0);
}
-static INLINE bool string_is_equal_noncase(const char *a, const char *b)
+static INLINE bool string_starts_with_case_insensitive(const char *str,
+ const char *prefix)
{
int result = 0;
- const unsigned char *p1 = (const unsigned char*)a;
- const unsigned char *p2 = (const unsigned char*)b;
+ const unsigned char *p1 = (const unsigned char*)str;
+ const unsigned char *p2 = (const unsigned char*)prefix;
- if (!a || !b)
+ if (!str || !prefix)
return false;
if (p1 == p2)
- return false;
+ return true;
- while ((result = tolower (*p1) - tolower (*p2++)) == 0)
- if (*p1++ == '\0')
+ while ((result = tolower (*p1++) - tolower (*p2)) == 0)
+ if (*p2++ == '\0')
break;
- return (result == 0);
+ return (result == 0 || *p2 == '\0');
}
char *string_to_upper(char *s);
/* Remove leading and trailing whitespaces */
char *string_trim_whitespace(char *const s);
-/* max_lines == 0 means no limit */
-char *word_wrap(char *buffer, const char *string,
- int line_width, bool unicode, unsigned max_lines);
+/*
+ * 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.).
+ *
+ * @param dst pointer to destination buffer.
+ * @param dst_size size of destination buffer.
+ * @param src pointer to input string.
+ * @param line_width max number of characters per line.
+ * @param wideglyph_width not used, but is necessary to keep
+ * compatibility with word_wrap_wideglyph().
+ * @param max_lines max lines of destination string.
+ * 0 means no limit.
+ */
+void word_wrap(char *dst, size_t dst_size, const char *src,
+ int line_width, int wideglyph_width, unsigned max_lines);
+
+/*
+ * 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.
+ *
+ * @param dst pointer to destination buffer.
+ * @param dst_size size of destination buffer.
+ * @param src pointer to input string.
+ * @param line_width max number of characters per line.
+ * @param 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
+ * @param max_lines max lines of destination string.
+ * 0 means no limit.
+ */
+void word_wrap_wideglyph(char *dst, size_t dst_size, const char *src,
+ int line_width, int wideglyph_width, unsigned max_lines);
/* Splits string into tokens seperated by 'delim'
* > Returned token string must be free()'d
* char *str = "1,2,3,4,5,6,7,,,10,";
* char **str_ptr = &str;
* char *token = NULL;
- * while((token = string_tokenize(str_ptr, ",")))
+ * while ((token = string_tokenize(str_ptr, ",")))
* {
* printf("%s\n", token);
* free(token);
* Returns 0 if string is invalid */
unsigned string_hex_to_unsigned(const char *str);
+char *string_init(const char *src);
+
+void string_set(char **string, const char *src);
+
+extern const unsigned char lr_char_props[256];
+
+/* Get the total number of occurrences of a character in the given string. */
+int string_count_occurrences_single_character(char *str, char t);
+
+/* Replaces all spaces with the given character. */
+void string_replace_whitespace_with_single_character(char *str, char t);
+
+/* Replaces multiple spaces with a single space in a string. */
+void string_replace_multi_space_with_single_space(char *str);
+
+/* Remove all spaces from the given string. */
+void string_remove_all_whitespace(char* str_trimmed, const char* str_untrimmed);
+
+/* Retrieve the last occurance of the given character in a string. */
+int string_index_last_occurance(char str[], char t);
+
+/* Find the position of a substring in a string. */
+int string_find_index_substring_string(const char* str1, const char* str2);
+
RETRO_END_DECLS
#endif
-/* Copyright (C) 2010-2019 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (vfs_implementation.h).
#ifdef HAVE_CDROM
typedef struct
{
+ int64_t byte_pos;
char *cue_buf;
size_t cue_len;
- int64_t byte_pos;
- char drive;
+ unsigned cur_lba;
+ unsigned last_frame_lba;
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
VFS_SCHEME_CDROM
};
-#ifndef __WINRT__
+#if !(defined(__WINRT__) && defined(__cplusplus_winrt))
#ifdef VFS_FRONTEND
struct retro_vfs_file_handle
#else
struct libretro_vfs_implementation_file
#endif
{
- int fd;
- unsigned hints;
+#ifdef HAVE_CDROM
+ vfs_cdrom_t cdrom; /* int64_t alignment */
+#endif
int64_t size;
- char *buf;
+ uint64_t mappos;
+ uint64_t mapsize;
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
-/* Copyright (C) 2010-2019 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (vfs_implementation.h).
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
--- /dev/null
+/* Copyright (C) 2010-2020 The RetroArch team
+ *
+ * ---------------------------------------------------------------------------------------
+ * The following license statement only applies to this file (memmap.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.
+ */
+
+#include <stdint.h>
+#include <memmap.h>
+
+#ifndef PROT_READ
+#define PROT_READ 0x1 /* Page can be read */
+#endif
+
+#ifndef PROT_WRITE
+#define PROT_WRITE 0x2 /* Page can be written. */
+#endif
+
+#ifndef PROT_READWRITE
+#define PROT_READWRITE 0x3 /* Page can be written to and read from. */
+#endif
+
+#ifndef PROT_EXEC
+#define PROT_EXEC 0x4 /* Page can be executed. */
+#endif
+
+#ifndef PROT_NONE
+#define PROT_NONE 0x0 /* Page can not be accessed. */
+#endif
+
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *) -1)
+#endif
+
+#ifdef _WIN32
+void* mmap(void *addr, size_t len, int prot, int flags,
+ int fildes, size_t offset)
+{
+ void *map = (void*)NULL;
+ HANDLE handle = INVALID_HANDLE_VALUE;
+
+ switch (prot)
+ {
+ case PROT_READ:
+ default:
+ handle = CreateFileMapping((HANDLE)
+ _get_osfhandle(fildes), 0, PAGE_READONLY, 0,
+ len, 0);
+ if (!handle)
+ break;
+ map = (void*)MapViewOfFile(handle, FILE_MAP_READ, 0, 0, len);
+ CloseHandle(handle);
+ break;
+ case PROT_WRITE:
+ handle = CreateFileMapping((HANDLE)
+ _get_osfhandle(fildes),0,PAGE_READWRITE,0,
+ len, 0);
+ if (!handle)
+ break;
+ map = (void*)MapViewOfFile(handle, FILE_MAP_WRITE, 0, 0, len);
+ CloseHandle(handle);
+ break;
+ case PROT_READWRITE:
+ handle = CreateFileMapping((HANDLE)
+ _get_osfhandle(fildes),0,PAGE_READWRITE,0,
+ len, 0);
+ if (!handle)
+ break;
+ map = (void*)MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, len);
+ CloseHandle(handle);
+ break;
+ }
+
+ if (map == (void*)NULL)
+ return((void*)MAP_FAILED);
+ return((void*) ((int8_t*)map + offset));
+}
+
+int munmap(void *addr, size_t length)
+{
+ if (!UnmapViewOfFile(addr))
+ return -1;
+ return 0;
+}
+
+int mprotect(void *addr, size_t len, int prot)
+{
+ /* Incomplete, just assumes PAGE_EXECUTE_READWRITE right now
+ * instead of correctly handling prot */
+ prot = 0;
+ if (prot & (PROT_READ | PROT_WRITE | PROT_EXEC))
+ prot = PAGE_EXECUTE_READWRITE;
+ return VirtualProtect(addr, len, prot, 0);
+}
+
+#elif !defined(HAVE_MMAN)
+void* mmap(void *addr, size_t len, int prot, int flags,
+ int fildes, size_t offset)
+{
+ return malloc(len);
+}
+
+int munmap(void *addr, size_t len)
+{
+ free(addr);
+ return 0;
+}
+
+int mprotect(void *addr, size_t len, int prot)
+{
+ /* stub - not really needed at this point
+ * since this codepath has no dynarecs. */
+ return 0;
+}
+
+#endif
+
+#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__)
+ sys_dcache_flush(start ,len);
+ sys_icache_invalidate(start, len);
+ return 0;
+#elif defined(__arm__) && !defined(__QNX__)
+ (void)len;
+ __clear_cache(start, end);
+ return 0;
+#elif defined(HAVE_MMAN)
+ return msync(start, len, MS_SYNC | MS_INVALIDATE
+#ifdef __QNX__
+ MS_CACHE_ONLY
+#endif
+ );
+#else
+ (void)len;
+ return 0;
+#endif
+}
+
+int memprotect(void *addr, size_t len)
+{
+ return mprotect(addr, len, PROT_READ | PROT_WRITE | PROT_EXEC);
+}
-/* Copyright (C) 2010-2018 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (file_stream.c).
#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>
-static const int64_t vfs_error_return_value = -1;
+#define VFS_ERROR_RETURN_VALUE -1
+
+struct RFILE
+{
+ struct retro_vfs_file_handle *hfile;
+ bool error_flag;
+ bool eof_flag;
+};
static retro_vfs_get_path_t filestream_get_path_cb = NULL;
static retro_vfs_open_t filestream_open_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;
+ const struct retro_vfs_interface *
+ vfs_iface = vfs_info->iface;
filestream_get_path_cb = NULL;
filestream_open_cb = NULL;
filestream_remove_cb = NULL;
filestream_rename_cb = NULL;
- vfs_iface = vfs_info->iface;
-
- if (vfs_info->required_interface_version < FILESTREAM_REQUIRED_VFS_VERSION
+ if (
+ (vfs_info->required_interface_version <
+ FILESTREAM_REQUIRED_VFS_VERSION)
|| !vfs_iface)
return;
/* Callback wrappers */
bool filestream_exists(const char *path)
{
- RFILE *dummy = NULL;
+ RFILE *dummy = NULL;
if (!path || !*path)
return false;
- dummy = filestream_open(path,
+ dummy = filestream_open(
+ path,
RETRO_VFS_FILE_ACCESS_READ,
RETRO_VFS_FILE_ACCESS_HINT_NONE);
if (!dummy)
return false;
- filestream_close(dummy);
+ if (filestream_close(dummy) != 0)
+ if (dummy)
+ free(dummy);
+
+ dummy = NULL;
return true;
}
{
int64_t output;
- if (filestream_size_cb != NULL)
+ if (filestream_size_cb)
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;
{
int64_t output;
- if (filestream_truncate_cb != NULL)
+ if (filestream_truncate_cb)
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;
struct retro_vfs_file_handle *fp = NULL;
RFILE* output = NULL;
- if (filestream_open_cb != NULL)
+ if (filestream_open_cb)
fp = (struct retro_vfs_file_handle*)
filestream_open_cb(path, mode, hints);
else
int filestream_getc(RFILE *stream)
{
char c = 0;
- if (!stream)
- return EOF;
- if (filestream_read(stream, &c, 1) == 1)
+ if (stream && filestream_read(stream, &c, 1) == 1)
return (int)(unsigned char)c;
return EOF;
}
-int filestream_scanf(RFILE *stream, const char* format, ...)
+int filestream_vscanf(RFILE *stream, const char* format, va_list *args)
{
char buf[4096];
char subfmt[64];
- va_list args;
-
+ va_list args_copy;
const char * bufiter = buf;
- int64_t startpos = filestream_tell(stream);
int ret = 0;
+ int64_t startpos = filestream_tell(stream);
int64_t maxlen = filestream_read(stream, buf, sizeof(buf)-1);
if (maxlen <= 0)
buf[maxlen] = '\0';
- va_start(args, format);
+ /* 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
while (*format)
{
if (*format == '%')
{
int sublen;
-
char* subfmtiter = subfmt;
bool asterisk = false;
if (*format == '*')
{
- asterisk = true;
+ asterisk = true;
*subfmtiter++ = *format++;
}
- while (isdigit(*format)) *subfmtiter++ = *format++; /* width */
+ while (ISDIGIT((unsigned char)*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++;
}
/* 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';
+ *subfmtiter++ = '%';
+ *subfmtiter++ = 'n';
+ *subfmtiter++ = '\0';
+
+ if (sizeof(void*) != sizeof(long*))
+ abort(); /* all pointers must have the same size */
- if (sizeof(void*) != sizeof(long*)) abort(); /* all pointers must have the same size */
if (asterisk)
{
- if (sscanf(bufiter, subfmt, &sublen) != 0) break;
+ int v = sscanf(bufiter, subfmt, &sublen);
+ if (v == EOF)
+ return EOF;
+ if (v != 0)
+ break;
}
else
{
- if (sscanf(bufiter, subfmt, va_arg(args, void*), &sublen) != 1) break;
+ int v = sscanf(bufiter, subfmt, va_arg(args_copy, void*), &sublen);
+ if (v == EOF)
+ return EOF;
+ if (v != 1)
+ break;
}
ret++;
bufiter += sublen;
}
- else if (isspace(*format))
+ else if (isspace((unsigned char)*format))
{
- while (isspace(*bufiter)) bufiter++;
+ while (isspace((unsigned char)*bufiter))
+ bufiter++;
format++;
}
else
}
}
- va_end(args);
- filestream_seek(stream, startpos+(bufiter-buf), RETRO_VFS_SEEK_POSITION_START);
+ va_end(args_copy);
+ 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 != NULL)
+ if (filestream_seek_cb)
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;
+
+ stream->eof_flag = false;
return output;
}
{
int64_t output;
- if (filestream_size_cb != NULL)
+ if (filestream_size_cb)
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;
return;
filestream_seek(stream, 0L, RETRO_VFS_SEEK_POSITION_START);
stream->error_flag = false;
- stream->eof_flag = false;
+ stream->eof_flag = false;
}
int64_t filestream_read(RFILE *stream, void *s, int64_t len)
{
int64_t output;
- if (filestream_read_cb != NULL)
+ if (filestream_read_cb)
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;
+ stream->eof_flag = true;
return output;
}
{
int output;
- if (filestream_flush_cb != NULL)
+ if (filestream_flush_cb)
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;
int filestream_delete(const char *path)
{
- if (filestream_remove_cb != NULL)
+ if (filestream_remove_cb)
return filestream_remove_cb(path);
return retro_vfs_file_remove_impl(path);
int filestream_rename(const char *old_path, const char *new_path)
{
- if (filestream_rename_cb != NULL)
+ if (filestream_rename_cb)
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)
{
- if (filestream_get_path_cb != NULL)
+ if (filestream_get_path_cb)
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 != NULL)
+ if (filestream_write_cb)
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;
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 = vsprintf(buffer, format, args);
+ int64_t num_chars = vsnprintf(buffer, sizeof(buffer),
+ format, args);
if (num_chars < 0)
return -1;
int output;
struct retro_vfs_file_handle* fp = stream->hfile;
- if (filestream_close_cb != NULL)
+ if (filestream_close_cb)
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);
* @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.
*
- * Returns: number of items read, -1 on error.
+ * Returns: non zero on success.
*/
int64_t filestream_read_file(const char *path, void **buf, int64_t *len)
{
if (!file)
{
- fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
- goto error;
+ *buf = NULL;
+ return 0;
}
content_buf_size = filestream_get_size(file);
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;
- }
- filestream_close(file);
+ if (filestream_close(file) != 0)
+ if (file)
+ free(file);
*buf = content_buf;
error:
if (file)
- filestream_close(file);
+ if (filestream_close(file) != 0)
+ free(file);
if (content_buf)
free(content_buf);
if (len)
return false;
ret = filestream_write(file, data, size);
- filestream_close(file);
+ if (filestream_close(file) != 0)
+ if (file)
+ free(file);
if (ret != size)
return false;
-/* Copyright (C) 2010-2018 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (file_stream_transforms.c).
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:
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);
}
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);
}
int64_t rfwrite(void const* buffer,
size_t elem_size, size_t elem_count, RFILE* stream)
{
- return filestream_write(stream, buffer, elem_size * elem_count);
+ if (!stream || (elem_size == 0) || (elem_count == 0))
+ return 0;
+
+ return (filestream_write(stream, buffer, elem_size * elem_count) / elem_size);
}
int rfputc(int character, RFILE * stream)
{
- return filestream_putc(stream, character);
+ if (!stream)
+ return EOF;
+
+ return filestream_putc(stream, character);
}
int64_t rfflush(RFILE * stream)
{
- return filestream_flush(stream);
+ if (!stream)
+ return EOF;
+
+ return filestream_flush(stream);
}
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);
{
int result;
va_list vl;
+
+ if (!stream)
+ return 0;
+
va_start(vl, format);
- result = filestream_scanf(stream, format, vl);
+ result = filestream_vscanf(stream, format, &vl);
va_end(vl);
return result;
}
-/* Copyright (C) 2010-2018 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (stdstring.c).
#include <stdint.h>
#include <ctype.h>
+#include <string.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;
/* 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);
}
/* 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;
return s;
}
-char *word_wrap(char* buffer, const char *string, int line_width, bool unicode, unsigned max_lines)
+void word_wrap(char *dst, size_t dst_size, const char *src, int line_width, int wideglyph_width, unsigned max_lines)
{
- unsigned i = 0;
- unsigned len = (unsigned)strlen(string);
- unsigned lines = 1;
+ char *lastspace = NULL;
+ unsigned counter = 0;
+ unsigned lines = 1;
+ size_t src_len = strlen(src);
+ const char *src_end = src + src_len;
+
+ /* Prevent buffer overflow */
+ if (dst_size < src_len + 1)
+ return;
- while (i < len)
+ /* Early return if src string length is less
+ * than line width */
+ if (src_len < line_width)
{
- unsigned counter;
- int pos = (int)(&buffer[i] - buffer);
+ strcpy(dst, src);
+ return;
+ }
- /* copy string until the end of the line is reached */
- for (counter = 1; counter <= (unsigned)line_width; counter++)
- {
- const char *character;
- unsigned char_len;
- unsigned j = i;
+ while (*src != '\0')
+ {
+ unsigned char_len;
+
+ char_len = (unsigned)(utf8skip(src, 1) - src);
+ counter++;
- /* check if end of string reached */
- if (i == len)
+ if (*src == ' ')
+ lastspace = dst; /* Remember the location of the whitespace */
+ else if (*src == '\n')
+ {
+ /* If newlines embedded in the input,
+ * reset the index */
+ lines++;
+ counter = 0;
+
+ /* Early return if remaining src string
+ * length is less than line width */
+ if (src_end - src <= line_width)
{
- buffer[i] = 0;
- return buffer;
+ strcpy(dst, src);
+ return;
}
+ }
- character = utf8skip(&string[i], 1);
- char_len = (unsigned)(character - &string[i]);
+ while (char_len--)
+ *dst++ = *src++;
- if (!unicode)
- counter += char_len - 1;
+ if (counter >= (unsigned)line_width)
+ {
+ counter = 0;
- 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')
+ if (lastspace && (max_lines == 0 || lines < max_lines))
{
+ /* Replace nearest (previous) whitespace
+ * with newline character */
+ *lastspace = '\n';
lines++;
- counter = 1;
+
+ 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)
+ {
+ strcpy(dst, src);
+ return;
+ }
}
}
+ }
+
+ *dst = '\0';
+}
- /* check for whitespace */
- if (string[i] == ' ')
+void word_wrap_wideglyph(char *dst, size_t dst_size, const char *src, int line_width, int wideglyph_width, unsigned max_lines)
+{
+ char *lastspace = NULL;
+ char *lastwideglyph = NULL;
+ const char *src_end = src + strlen(src);
+ 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)
+ {
+ strlcpy(dst, src, dst_size);
+ return;
+ }
+
+ while (*src != '\0')
+ {
+ unsigned char_len;
+
+ 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')
{
- if ((max_lines == 0 || lines < max_lines))
+ /* 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)
{
- buffer[i] = '\n';
- i++;
- lines++;
+ strlcpy(dst, src, dst_size);
+ return;
}
}
- else
+ else if (char_len >= 3)
{
- int k;
+ /* Remember the location of the first byte
+ * whose length as UTF-8 >= 3*/
+ lastwideglyph = dst;
+ counter_normalized += additional_counter_normalized;
+ }
- /* check for nearest whitespace back in string */
- for (k = i; k > 0; k--)
- {
- if (string[k] != ' ' || (max_lines != 0 && lines >= max_lines))
- continue;
+ dst_size -= char_len;
+ while (char_len--)
+ *dst++ = *src++;
- buffer[k] = '\n';
- /* set string index back to character after this one */
- i = k + 1;
+ if (counter_normalized >= (unsigned)line_width_normalized)
+ {
+ counter_normalized = 0;
+
+ if (max_lines != 0 && lines >= max_lines)
+ continue;
+ else if (lastwideglyph && (!lastspace || lastwideglyph > lastspace))
+ {
+ /* Insert newline character */
+ *lastwideglyph = '\n';
lines++;
- break;
+ 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)
+ {
+ strlcpy(dst, src, dst_size);
+ return;
+ }
+ }
+ 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)
+ {
+ strlcpy(dst, src, dst_size);
+ return;
+ }
}
-
- if (&buffer[i] - buffer == pos)
- return buffer;
}
}
- buffer[i] = 0;
-
- return buffer;
+ *dst = '\0';
}
/* Splits string into tokens seperated by 'delim'
* char *str = "1,2,3,4,5,6,7,,,10,";
* char **str_ptr = &str;
* char *token = NULL;
- * while((token = string_tokenize(str_ptr, ",")))
+ * while ((token = string_tokenize(str_ptr, ",")))
* {
* printf("%s\n", token);
* free(token);
if (string_is_empty(str))
return;
- while((str_ptr = strchr(str_ptr, find)) != NULL)
+ while ((str_ptr = strchr(str_ptr, find)))
*str_ptr++ = replace;
}
for (ptr = str; *ptr != '\0'; ptr++)
{
- if (!isdigit(*ptr))
+ if (!ISDIGIT((unsigned char)*ptr))
return 0;
}
/* Check for valid characters */
for (ptr = hex_str; *ptr != '\0'; ptr++)
{
- if (!isxdigit(*ptr))
+ if (!isxdigit((unsigned char)*ptr))
return 0;
}
return (unsigned)strtoul(hex_str, NULL, 16);
}
+
+/**
+ * Get the total number of occurrences of a character in the given string.
+ */
+int string_count_occurrences_single_character(char *str, char t)
+{
+ int ctr = 0;
+ int i;
+
+ for (i = 0; str[i] != '\0'; ++i) {
+ if (t == str[i])
+ ++ctr;
+ }
+
+ return ctr;
+}
+
+/**
+ * Replaces all spaces with the given character.
+ */
+void string_replace_whitespace_with_single_character(char *str, char t)
+{
+
+ while (*str) {
+ if (isspace(*str))
+ *str = t;
+ str++;
+ }
+}
+
+/**
+ * Replaces multiple spaces with a single space in a string.
+ */
+void string_replace_multi_space_with_single_space(char *str)
+{
+ char *dest = str;
+
+ while (*str != '\0')
+ {
+ while (*str == ' ' && *(str + 1) == ' ')
+ str++;
+
+ *dest++ = *str++;
+ }
+
+ *dest = '\0';
+}
+
+/**
+ * Remove all spaces from the given string.
+ */
+void string_remove_all_whitespace(char* str_trimmed, const char* str_untrimmed)
+{
+ while (*str_untrimmed != '\0')
+ {
+ if(!isspace(*str_untrimmed))
+ {
+ *str_trimmed = *str_untrimmed;
+ str_trimmed++;
+ }
+ str_untrimmed++;
+ }
+ *str_trimmed = '\0';
+}
+
+/**
+ * Retrieve the last occurance of the given character in a string.
+ */
+int string_index_last_occurance(char *str, char t)
+{
+ const char * ret = strrchr(str, t);
+ if (ret)
+ return ret-str;
+
+ return -1;
+}
+
+/**
+ * Find the position of a substring in a string.
+ */
+int string_find_index_substring_string(const char* str1, const char* str2)
+{
+ int index;
+
+ if (str1[0] != '\0')
+ {
+ const char *pfound = strstr(str1, str2);
+ if (pfound != NULL)
+ {
+ index = (pfound - str1);
+ return index;
+ }
+ }
+
+ return -1;
+}
-/* Copyright (C) 2010-2019 The RetroArch team
+/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (vfs_implementation.c).
# if defined(PSP)
# include <pspiofilemgr.h>
# endif
-# if defined(PS2)
-# include <fileXio_rpc.h>
-# include <fileXio_cdvd.h>
-# endif
# include <sys/types.h>
# include <sys/stat.h>
# if !defined(VITA)
# include <sys/dirent.h>
# include <orbisFile.h>
# endif
+# if defined(WIIU)
+# include <malloc.h>
+# endif
#endif
-#ifdef __CELLOS_LV2__
-#include <cell/cell_fs.h>
-#define O_RDONLY CELL_FS_O_RDONLY
-#define O_WRONLY CELL_FS_O_WRONLY
-#define O_CREAT CELL_FS_O_CREAT
-#define O_TRUNC CELL_FS_O_TRUNC
-#define O_RDWR CELL_FS_O_RDWR
-#else
#include <fcntl.h>
-#endif
/* TODO: Some things are duplicated but I'm really afraid of breaking other platforms by touching this */
#if defined(VITA)
# if defined(PSP)
# include <pspiofilemgr.h>
# endif
-# if defined(PS2)
-# include <fileXio_rpc.h>
-# endif
# include <sys/types.h>
# include <sys/stat.h>
# include <dirent.h>
# include <unistd.h>
#endif
-#if (defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)) || defined(__QNX__) || defined(PSP) || defined(PS2)
+#if defined(__QNX__) || defined(PSP)
#include <unistd.h> /* stat() is defined here */
#endif
#include <pspkernel.h>
#endif
-#if defined(PS2)
-#include <fileXio_rpc.h>
-#include <fileXio.h>
+#if defined(__PS3__) || defined(__PSL1GHT__)
+#include <defines/ps3_defines.h>
+#if defined(__PSL1GHT__)
+#include <lv2/sysfs.h>
#endif
-
-#if defined(__CELLOS_LV2__)
-#include <cell/cell_fs.h>
#endif
#if defined(VITA)
#define FIO_S_ISDIR SCE_S_ISDIR
#endif
-#if (defined(__CELLOS_LV2__) && !defined(__PSL1GHT__)) || defined(__QNX__) || defined(PSP)
+#if defined(__QNX__) || defined(PSP)
#include <unistd.h> /* stat() is defined here */
#endif
#endif
#if defined(_WIN32)
-#if !defined(_MSC_VER) || (defined(_MSC_VER) && _MSC_VER >= 1400)
+#if defined(_MSC_VER) && _MSC_VER >= 1400
#define ATLEAST_VC2005
#endif
#endif
#include <vfs/vfs_implementation.h>
#include <libretro.h>
+#if defined(HAVE_MMAP)
#include <memmap.h>
+#endif
#include <encodings/utf.h>
#include <compat/fopen_utf8.h>
#include <file/file_path.h>
#include <vfs/vfs_implementation_cdrom.h>
#endif
+#if (defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE - 0) >= 200112) || (defined(__POSIX_VISIBLE) && __POSIX_VISIBLE >= 200112) || (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112) || __USE_LARGEFILE || (defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64)
+#ifndef HAVE_64BIT_OFFSETS
+#define HAVE_64BIT_OFFSETS
+#endif
+#endif
+
#define RFILE_HINT_UNBUFFERED (1 << 8)
-int64_t retro_vfs_file_seek_internal(libretro_vfs_implementation_file *stream, int64_t offset, int whence)
+int64_t retro_vfs_file_seek_internal(
+ libretro_vfs_implementation_file *stream,
+ int64_t offset, int whence)
{
if (!stream)
return -1;
if (stream->scheme == VFS_SCHEME_CDROM)
return retro_vfs_file_seek_cdrom(stream, offset, whence);
#endif
-/* VC2005 and up have a special 64-bit fseek */
#ifdef ATLEAST_VC2005
+ /* VC2005 and up have a special 64-bit fseek */
return _fseeki64(stream->fp, offset, whence);
-#elif defined(__CELLOS_LV2__) || defined(_MSC_VER) && _MSC_VER <= 1310
- return fseek(stream->fp, (long)offset, whence);
-#elif defined(PS2)
- {
- int64_t ret = fileXioLseek(fileno(stream->fp), (off_t)offset, whence);
- /* fileXioLseek could return positive numbers */
- if (ret > 0)
- return 0;
- return ret;
- }
#elif defined(ORBIS)
{
int ret = orbisLseek(stream->fd, offset, whence);
return -1;
return 0;
}
-#else
+#elif defined(HAVE_64BIT_OFFSETS)
return fseeko(stream->fp, (off_t)offset, whence);
+#else
+ return fseek(stream->fp, (long)offset, whence);
#endif
}
#ifdef HAVE_MMAP
}
#endif
- if (lseek(stream->fd, offset, whence) < 0)
+ if (lseek(stream->fd, (off_t)offset, whence) < 0)
return -1;
return 0;
libretro_vfs_implementation_file *retro_vfs_file_open_impl(
const char *path, unsigned mode, unsigned hints)
{
- int flags = 0;
- const char *mode_str = NULL;
- libretro_vfs_implementation_file *stream = (libretro_vfs_implementation_file*)
- calloc(1, sizeof(*stream));
#if defined(VFS_FRONTEND) || defined(HAVE_CDROM)
int path_len = (int)strlen(path);
#endif
-
#ifdef VFS_FRONTEND
const char *dumb_prefix = "vfsonly://";
- size_t dumb_prefix_siz = strlen(dumb_prefix);
+ size_t dumb_prefix_siz = STRLEN_CONST("vfsonly://");
int dumb_prefix_len = (int)dumb_prefix_siz;
+#endif
+#ifdef HAVE_CDROM
+ const char *cdrom_prefix = "cdrom://";
+ size_t cdrom_prefix_siz = STRLEN_CONST("cdrom://");
+ int cdrom_prefix_len = (int)cdrom_prefix_siz;
+#endif
+ int flags = 0;
+ const char *mode_str = NULL;
+ libretro_vfs_implementation_file *stream =
+ (libretro_vfs_implementation_file*)
+ malloc(sizeof(*stream));
+ if (!stream)
+ return NULL;
+
+ stream->fd = 0;
+ stream->hints = hints;
+ stream->size = 0;
+ stream->buf = NULL;
+ stream->fp = NULL;
+#ifdef _WIN32
+ stream->fh = 0;
+#endif
+ stream->orig_path = NULL;
+ stream->mappos = 0;
+ stream->mapsize = 0;
+ stream->mapped = NULL;
+ stream->scheme = VFS_SCHEME_NONE;
+
+#ifdef VFS_FRONTEND
if (path_len >= dumb_prefix_len)
- {
if (!memcmp(path, dumb_prefix, dumb_prefix_len))
- path += dumb_prefix_siz;
- }
+ path += dumb_prefix_siz;
#endif
#ifdef HAVE_CDROM
+ stream->cdrom.cue_buf = NULL;
+ stream->cdrom.cue_len = 0;
+ stream->cdrom.byte_pos = 0;
+ stream->cdrom.drive = 0;
+ stream->cdrom.cur_min = 0;
+ stream->cdrom.cur_sec = 0;
+ stream->cdrom.cur_frame = 0;
+ stream->cdrom.cur_track = 0;
+ stream->cdrom.cur_lba = 0;
+ stream->cdrom.last_frame_lba = 0;
+ stream->cdrom.last_frame[0] = '\0';
+ stream->cdrom.last_frame_valid = false;
+
+ if (path_len > cdrom_prefix_len)
{
- const char *cdrom_prefix = "cdrom://";
- size_t cdrom_prefix_siz = strlen(cdrom_prefix);
- int cdrom_prefix_len = (int)cdrom_prefix_siz;
-
- if (path_len > cdrom_prefix_len)
+ if (!memcmp(path, cdrom_prefix, cdrom_prefix_len))
{
- if (!memcmp(path, cdrom_prefix, cdrom_prefix_len))
- {
- path += cdrom_prefix_siz;
- stream->scheme = VFS_SCHEME_CDROM;
- }
+ path += cdrom_prefix_siz;
+ stream->scheme = VFS_SCHEME_CDROM;
}
}
#endif
- if (!stream)
- return NULL;
-
- (void)flags;
-
- stream->hints = hints;
stream->orig_path = strdup(path);
#ifdef HAVE_MMAP
flags = O_WRONLY | O_CREAT | O_TRUNC;
#if !defined(ORBIS)
-#if defined(PS2)
- flags |= FIO_S_IRUSR | FIO_S_IWUSR;
-#elif !defined(_WIN32)
+#if !defined(_WIN32)
flags |= S_IRUSR | S_IWUSR;
#else
flags |= O_BINARY;
mode_str = "w+b";
flags = O_RDWR | O_CREAT | O_TRUNC;
#if !defined(ORBIS)
-#if defined(PS2)
- flags |= FIO_S_IRUSR | FIO_S_IWUSR;
-#elif !defined(_WIN32)
+#if !defined(_WIN32)
flags |= S_IRUSR | S_IWUSR;
#else
flags |= O_BINARY;
flags = O_RDWR;
#if !defined(ORBIS)
-#if defined(PS2)
- flags |= FIO_S_IRUSR | FIO_S_IWUSR;
-#elif !defined(_WIN32)
+#if !defined(_WIN32)
flags |= S_IRUSR | S_IWUSR;
#else
flags |= O_BINARY;
stream->fd = -1;
goto error;
}
- stream->fd = fd;
+ stream->fd = fd;
#else
FILE *fp;
#ifdef HAVE_CDROM
*
* https://www.freebsd.org/cgi/man.cgi?query=setvbuf&apropos=0&sektion=0&manpath=FreeBSD+11.1-RELEASE&arch=default&format=html
*
- * If the size argument is not zero but buf is NULL, a buffer of the given size will be allocated immediately, and
+ * If the size argument is not zero but buf is NULL,
+ * a buffer of the given size will be allocated immediately, and
* released on close. This is an extension to ANSI C.
*
- * Since C89 does not support specifying a null buffer with a non-zero size, we create and track our own buffer for it.
+ * Since C89 does not support specifying a NULL buffer
+ * with a non-zero size, we create and track our own buffer for it.
*/
- /* TODO: this is only useful for a few platforms, find which and add ifdef */
-#if !defined(PS2) && !defined(PSP)
+ /* TODO: this is only useful for a few platforms,
+ * find which and add ifdef */
+#if defined(_3DS)
+ if (stream->scheme != VFS_SCHEME_CDROM)
+ {
+ stream->buf = (char*)calloc(1, 0x10000);
+ if (stream->fp)
+ setvbuf(stream->fp, stream->buf, _IOFBF, 0x10000);
+ }
+#elif defined(WIIU)
+ if (stream->scheme != VFS_SCHEME_CDROM)
+ {
+ const int bufsize = 128*1024;
+ stream->buf = (char*)memalign(0x40, bufsize);
+ if (stream->fp)
+ setvbuf(stream->fp, stream->buf, _IOFBF, bufsize);
+ }
if (stream->scheme != VFS_SCHEME_CDROM)
{
stream->buf = (char*)calloc(1, 0x4000);
if ((stream->hints & RFILE_HINT_UNBUFFERED) == 0)
{
if (stream->fp)
- {
fclose(stream->fp);
- }
}
else
{
if (_chsize(_fileno(stream->fp), length) != 0)
return -1;
#elif !defined(VITA) && !defined(PSP) && !defined(PS2) && !defined(ORBIS) && (!defined(SWITCH) || defined(HAVE_LIBNX))
- if (ftruncate(fileno(stream->fp), length) != 0)
+ if (ftruncate(fileno(stream->fp), (off_t)length) != 0)
return -1;
#endif
return ret;
}
#else
- /* VC2005 and up have a special 64-bit ftell */
#ifdef ATLEAST_VC2005
+ /* VC2005 and up have a special 64-bit ftell */
return _ftelli64(stream->fp);
+#elif defined(HAVE_64BIT_OFFSETS)
+ return ftello(stream->fp);
#else
return ftell(stream->fp);
#endif
#ifdef HAVE_MMAP
/* Need to check stream->mapped because this function
* is called in filestream_open() */
- if (stream->mapped && stream->hints & RETRO_VFS_FILE_ACCESS_HINT_FREQUENT_ACCESS)
+ if (stream->mapped && stream->hints &
+ RETRO_VFS_FILE_ACCESS_HINT_FREQUENT_ACCESS)
return stream->mappos;
#endif
if (lseek(stream->fd, 0, SEEK_CUR) < 0)
int retro_vfs_stat_impl(const char *path, int32_t *size)
{
-#if defined(VITA) || defined(PSP)
- /* Vita / PSP */
- SceIoStat buf;
- int stat_ret;
bool is_dir = false;
bool is_character_special = false;
+#if defined(VITA)
+ /* Vita / PSP */
+ SceIoStat buf;
+ int dir_ret;
char *tmp = NULL;
size_t len = 0;
if (tmp[len-1] == '/')
tmp[len-1] = '\0';
- stat_ret = sceIoGetstat(tmp, &buf);
+ dir_ret = sceIoGetstat(tmp, &buf);
free(tmp);
- if (stat_ret < 0)
+ if (dir_ret < 0)
return 0;
if (size)
- *size = (int32_t)buf.st_size;
-
- is_dir = FIO_S_ISDIR(buf.st_mode);
-
- return RETRO_VFS_STAT_IS_VALID | (is_dir ? RETRO_VFS_STAT_IS_DIRECTORY : 0) | (is_character_special ? RETRO_VFS_STAT_IS_CHARACTER_SPECIAL : 0);
+ *size = (int32_t)buf.st_size;
+ is_dir = FIO_S_ISDIR(buf.st_mode);
#elif defined(ORBIS)
/* Orbis */
- bool is_dir, is_character_special;
- int dir_ret;
+ int dir_ret = 0;
if (!path || !*path)
return 0;
if (size)
- *size = (int32_t)buf.st_size;
+ *size = (int32_t)buf.st_size;
- dir_ret = orbisDopen(path);
- is_dir = dir_ret > 0;
+ dir_ret = orbisDopen(path);
+ is_dir = dir_ret > 0;
orbisDclose(dir_ret);
- is_character_special = S_ISCHR(buf.st_mode);
-
- return RETRO_VFS_STAT_IS_VALID | (is_dir ? RETRO_VFS_STAT_IS_DIRECTORY : 0) | (is_character_special ? RETRO_VFS_STAT_IS_CHARACTER_SPECIAL : 0);
-
-#elif defined(PS2)
- /* PS2 */
- iox_stat_t buf;
- bool is_dir;
- bool is_character_special = false;
- char *tmp = NULL;
- size_t len = 0;
+ is_character_special = S_ISCHR(buf.st_mode);
+#elif defined(__PSL1GHT__) || defined(__PS3__)
+ /* Lowlevel Lv2 */
+ sysFSStat buf;
if (!path || !*path)
return 0;
-
- tmp = strdup(path);
- len = strlen(tmp);
- if (tmp[len-1] == '/')
- tmp[len-1] = '\0';
-
- fileXioGetStat(tmp, &buf);
- free(tmp);
-
- if (size)
- *size = (int32_t)buf.size;
-
- if (!buf.mode)
- {
- /* if fileXioGetStat fails */
- int dir_ret = fileXioDopen(path);
- is_dir = dir_ret > 0;
- if (is_dir) {
- fileXioDclose(dir_ret);
- }
- }
- else
- is_dir = FIO_S_ISDIR(buf.mode);
-
- return RETRO_VFS_STAT_IS_VALID | (is_dir ? RETRO_VFS_STAT_IS_DIRECTORY : 0) | (is_character_special ? RETRO_VFS_STAT_IS_CHARACTER_SPECIAL : 0);
-
-#elif defined(__CELLOS_LV2__)
- /* CellOS Lv2 */
- bool is_dir;
- bool is_character_special = false;
- CellFsStat buf;
-
- if (!path || !*path)
- return 0;
- if (cellFsStat(path, &buf) < 0)
+ if (sysFsStat(path, &buf) < 0)
return 0;
if (size)
- *size = (int32_t)buf.st_size;
-
- is_dir = ((buf.st_mode & S_IFMT) == S_IFDIR);
-
- return RETRO_VFS_STAT_IS_VALID | (is_dir ? RETRO_VFS_STAT_IS_DIRECTORY : 0) | (is_character_special ? RETRO_VFS_STAT_IS_CHARACTER_SPECIAL : 0);
+ *size = (int32_t)buf.st_size;
+ is_dir = ((buf.st_mode & S_IFMT) == S_IFDIR);
#elif defined(_WIN32)
/* Windows */
- bool is_dir;
DWORD file_info;
struct _stat buf;
- bool is_character_special = false;
#if defined(LEGACY_WIN32)
char *path_local = NULL;
#else
return 0;
#if defined(LEGACY_WIN32)
- path_local = utf8_to_local_string_alloc(path);
- file_info = GetFileAttributes(path_local);
+ path_local = utf8_to_local_string_alloc(path);
+ file_info = GetFileAttributes(path_local);
if (!string_is_empty(path_local))
_stat(path_local, &buf);
if (path_local)
free(path_local);
#else
- path_wide = utf8_to_utf16_string_alloc(path);
- file_info = GetFileAttributesW(path_wide);
+ path_wide = utf8_to_utf16_string_alloc(path);
+ file_info = GetFileAttributesW(path_wide);
_wstat(path_wide, &buf);
is_dir = (file_info & FILE_ATTRIBUTE_DIRECTORY);
- return RETRO_VFS_STAT_IS_VALID | (is_dir ? RETRO_VFS_STAT_IS_DIRECTORY : 0) | (is_character_special ? RETRO_VFS_STAT_IS_CHARACTER_SPECIAL : 0);
+#elif defined(GEKKO)
+ /* On GEKKO platforms, paths cannot have
+ * trailing slashes - we must therefore
+ * remove them */
+ char *path_buf = NULL;
+ int stat_ret = -1;
+ struct stat stat_buf;
+ size_t len;
+
+ if (string_is_empty(path))
+ return 0;
+
+ path_buf = strdup(path);
+ if (!path_buf)
+ return 0;
+
+ len = strlen(path_buf);
+ if (len > 0)
+ if (path_buf[len - 1] == '/')
+ path_buf[len - 1] = '\0';
+
+ stat_ret = stat(path_buf, &stat_buf);
+ free(path_buf);
+
+ if (stat_ret < 0)
+ return 0;
+
+ if (size)
+ *size = (int32_t)stat_buf.st_size;
+
+ is_dir = S_ISDIR(stat_buf.st_mode);
+ is_character_special = S_ISCHR(stat_buf.st_mode);
#else
/* Every other platform */
- bool is_dir, is_character_special;
struct stat buf;
if (!path || !*path)
is_dir = S_ISDIR(buf.st_mode);
is_character_special = S_ISCHR(buf.st_mode);
-
- return RETRO_VFS_STAT_IS_VALID | (is_dir ? RETRO_VFS_STAT_IS_DIRECTORY : 0) | (is_character_special ? RETRO_VFS_STAT_IS_CHARACTER_SPECIAL : 0);
#endif
+ return RETRO_VFS_STAT_IS_VALID | (is_dir ? RETRO_VFS_STAT_IS_DIRECTORY : 0) | (is_character_special ? RETRO_VFS_STAT_IS_CHARACTER_SPECIAL : 0);
}
#if defined(VITA)
{
#if defined(_WIN32)
#ifdef LEGACY_WIN32
- int ret = _mkdir(dir);
+ int ret = _mkdir(dir);
#else
- wchar_t *dirW = utf8_to_utf16_string_alloc(dir);
- int ret = -1;
+ wchar_t *dir_w = utf8_to_utf16_string_alloc(dir);
+ int ret = -1;
- if (dirW)
+ if (dir_w)
{
- ret = _wmkdir(dirW);
- free(dirW);
+ ret = _wmkdir(dir_w);
+ free(dir_w);
}
#endif
#elif defined(IOS)
int ret = mkdir(dir, 0755);
-#elif defined(VITA) || defined(PSP)
+#elif defined(VITA)
int ret = sceIoMkdir(dir, 0777);
-#elif defined(PS2)
- int ret = fileXioMkdir(dir, 0777);
#elif defined(ORBIS)
int ret = orbisMkdir(dir, 0755);
#elif defined(__QNX__)
int ret = mkdir(dir, 0777);
+#elif defined(GEKKO)
+ /* On GEKKO platforms, mkdir() fails if
+ * the path has a trailing slash. We must
+ * therefore remove it. */
+ int ret = -1;
+ if (!string_is_empty(dir))
+ {
+ char *dir_buf = strdup(dir);
+
+ if (dir_buf)
+ {
+ size_t len = strlen(dir_buf);
+
+ if (len > 0)
+ if (dir_buf[len - 1] == '/')
+ dir_buf[len - 1] = '\0';
+
+ ret = mkdir(dir_buf, 0750);
+
+ free(dir_buf);
+ }
+ }
#else
int ret = mkdir(dir, 0750);
#endif
HANDLE directory;
bool next;
char path[PATH_MAX_LENGTH];
-#elif defined(VITA) || defined(PSP)
+#elif defined(VITA)
SceUID directory;
SceIoDirent entry;
-#elif defined(PS2)
+#elif defined(__PSL1GHT__) || defined(__PS3__)
+ int error;
int directory;
- iox_dirent_t entry;
-#elif defined(__CELLOS_LV2__)
- CellFsErrno error;
- int directory;
- CellFsDirent entry;
+ sysFSDirent entry;
#elif defined(ORBIS)
int directory;
struct dirent entry;
{
#if defined(_WIN32)
return (rdir->directory == INVALID_HANDLE_VALUE);
-#elif defined(VITA) || defined(PSP) || defined(PS2) || defined(ORBIS)
+#elif defined(VITA) || defined(ORBIS)
return (rdir->directory < 0);
-#elif defined(__CELLOS_LV2__)
- return (rdir->error != CELL_FS_SUCCEEDED);
+#elif defined(__PSL1GHT__) || defined(__PS3__)
+ return (rdir->error != FS_SUCCEEDED);
#else
return !(rdir->directory);
#endif
free(path_wide);
#endif
-#elif defined(VITA) || defined(PSP)
+#elif defined(VITA)
rdir->directory = sceIoDopen(name);
-#elif defined(PS2)
- rdir->directory = ps2fileXioDopen(name);
#elif defined(_3DS)
rdir->directory = !string_is_empty(name) ? opendir(name) : NULL;
rdir->entry = NULL;
-#elif defined(__CELLOS_LV2__)
- rdir->error = cellFsOpendir(name, &rdir->directory);
+#elif defined(__PSL1GHT__) || defined(__PS3__)
+ rdir->error = sysFsOpendir(name, &rdir->directory);
#elif defined(ORBIS)
rdir->directory = orbisDopen(name);
#else
rdir->next = true;
return (rdir->directory != INVALID_HANDLE_VALUE);
-#elif defined(VITA) || defined(PSP)
+#elif defined(VITA)
return (sceIoDread(rdir->directory, &rdir->entry) > 0);
-#elif defined(PS2)
- iox_dirent_t record;
- int ret = ps2fileXioDread(rdir->directory, &record);
- rdir->entry = record;
- return ( ret > 0);
-#elif defined(__CELLOS_LV2__)
+#elif defined(__PSL1GHT__) || defined(__PS3__)
uint64_t nread;
- rdir->error = cellFsReaddir(rdir->directory, &rdir->entry, &nread);
+ rdir->error = sysFsReaddir(rdir->directory, &rdir->entry, &nread);
return (nread != 0);
#elif defined(ORBIS)
return (orbisDread(rdir->directory, &rdir->entry) > 0);
{
#if defined(_WIN32)
#if defined(LEGACY_WIN32)
- {
- char *name_local = local_to_utf8_string_alloc(rdir->entry.cFileName);
- memset(rdir->entry.cFileName, 0, sizeof(rdir->entry.cFileName));
- strlcpy(rdir->entry.cFileName, name_local, sizeof(rdir->entry.cFileName));
-
- if (name_local)
- free(name_local);
- }
+ char *name = local_to_utf8_string_alloc(rdir->entry.cFileName);
#else
- {
- char *name = utf16_to_utf8_string_alloc(rdir->entry.cFileName);
- memset(rdir->entry.cFileName, 0, sizeof(rdir->entry.cFileName));
- strlcpy((char*)rdir->entry.cFileName, name, sizeof(rdir->entry.cFileName));
-
- if (name)
- free(name);
- }
+ char *name = utf16_to_utf8_string_alloc(rdir->entry.cFileName);
#endif
+ memset(rdir->entry.cFileName, 0, sizeof(rdir->entry.cFileName));
+ strlcpy((char*)rdir->entry.cFileName, name, sizeof(rdir->entry.cFileName));
+ if (name)
+ free(name);
return (char*)rdir->entry.cFileName;
-#elif defined(VITA) || defined(PSP) || defined(__CELLOS_LV2__) || defined(ORBIS)
+#elif defined(VITA) || defined(ORBIS) || defined(__PSL1GHT__) || defined(__PS3__)
return rdir->entry.d_name;
-#elif defined(PS2)
- return rdir->entry.name;
#else
if (!rdir || !rdir->entry)
return NULL;
#if defined(_WIN32)
const WIN32_FIND_DATA *entry = (const WIN32_FIND_DATA*)&rdir->entry;
return entry->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
-#elif defined(PSP) || defined(VITA)
- const SceIoDirent *entry = (const SceIoDirent*)&rdir->entry;
-#if defined(PSP)
- return (entry->d_stat.st_attr & FIO_SO_IFDIR) == FIO_SO_IFDIR;
#elif defined(VITA)
+ const SceIoDirent *entry = (const SceIoDirent*)&rdir->entry;
return SCE_S_ISDIR(entry->d_stat.st_mode);
-#endif
-#elif defined(PS2)
- const iox_dirent_t *entry = (const iox_dirent_t*)&rdir->entry;
- return FIO_S_ISDIR(entry->stat.mode);
-#elif defined(__CELLOS_LV2__)
- CellFsDirent *entry = (CellFsDirent*)&rdir->entry;
- return (entry->d_type == CELL_FS_TYPE_DIRECTORY);
+#elif defined(__PSL1GHT__) || defined(__PS3__)
+ sysFSDirent *entry = (sysFSDirent*)&rdir->entry;
+ return (entry->d_type == FS_TYPE_DIR);
#elif defined(ORBIS)
- const struct dirent *entry = &rdir->entry;
+ const struct dirent *entry = &rdir->entry;
if (entry->d_type == DT_DIR)
return true;
if (!(entry->d_type == DT_UNKNOWN || entry->d_type == DT_LNK))
#if defined(_WIN32)
if (rdir->directory != INVALID_HANDLE_VALUE)
FindClose(rdir->directory);
-#elif defined(VITA) || defined(PSP)
+#elif defined(VITA)
sceIoDclose(rdir->directory);
-#elif defined(PS2)
- ps2fileXioDclose(rdir->directory);
-#elif defined(__CELLOS_LV2__)
- rdir->error = cellFsClosedir(rdir->directory);
+#elif defined(__PSL1GHT__) || defined(__PS3__)
+ rdir->error = sysFsClosedir(rdir->directory);
#elif defined(ORBIS)
orbisDclose(rdir->directory);
#else
#include <stdarg.h>
#include <string.h>
#ifndef _WIN32
-#ifndef NO_MMAP
#ifdef __SWITCH__
#include "switch/mman.h"
#else
#include <sys/mman.h>
#endif
-#endif
#else
#include <io.h>
#include <windows.h>
UnmapViewOfFile(addr);
/* ruh-ro, we leaked handle from CreateFileMapping() ... */
}
-#elif defined(NO_MMAP)
-#define PROT_EXEC 0x04
-#define MAP_FAILED 0
-#define PROT_READ 0
-#define PROT_WRITE 0
-#define MAP_PRIVATE 0
-#define MAP_ANONYMOUS 0
-
-void* mmap(void *desired_addr, size_t len, int mmap_prot, int mmap_flags, int fildes, size_t off)
-{
- return calloc(1, len);
-}
-
-void munmap(void *base_addr, size_t len)
-{
- free(base_addr);
-}
-
-int mprotect(void *addr, size_t len, int prot)
-{
- /* stub - not really needed at this point since this codepath has no dynarecs */
- return 0;
-}
-
#endif
#ifndef MAP_ANONYMOUS