Files
ppsspp/libretro/libretro-common/compat/fopen_utf8.c
T
libretroadmin cf9d102864 libretro: vendor libretro-common from RetroArch in-tree
The libretro-common submodule pinned the standalone repository at
76a3d54. It is replaced by an in-tree copy of RetroArch master
(b655a20) holding only what the core uses: the VFS, file, string,
encoding, compat and time sources it already built, the headers they and
the core include, the threading set - rthreads, retro_atomic, retro_spsc
and retro_waitable_spsc, mpsc_stack, retro_triple_buffer,
retro_eventcount, retro_asym_eventcount, retro_procbarrier and tpool,
with features_cpu and rstrtod, which they need - and the codecs that
replace the bundled zlib, zstd, libchdr, libzip and libpng: rinflate and
rdeflate, rzstd, rchd with its LZMA and FLAC decoders, rzip_archive,
rpng and crc32.

stdstring.c, which nothing calls, is no longer built. The threading sources are always built, by both the static Makefile and
CMake; the VFS set stays behind HAVE_LIBRETRO_VFS as before. The codecs
are built by the change that switches the core over to them.
2026-10-08 14:14:37 +02:00

150 lines
4.5 KiB
C

/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (fopen_utf8.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 <compat/fopen_utf8.h>
#include <encodings/utf.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <boolean.h>
#if defined(__WINRT__)
#include <stdint.h>
#include <windows.h>
#include <fileapifromapp.h>
#include <io.h>
#include <fcntl.h>
#endif
#ifdef _WIN32
#undef fopen
#if defined(LEGACY_WIN32) || defined(LEGACY_WIN32_RUNTIME)
static void *fopen_utf8_ansi(const char * filename, const char * mode)
{
char * filename_local = utf8_to_local_string_alloc(filename);
if (filename_local)
{
FILE *ret = fopen(filename_local, mode);
free(filename_local);
return ret;
}
return NULL;
}
#endif
#if !defined(LEGACY_WIN32) || defined(LEGACY_WIN32_RUNTIME)
static void *fopen_utf8_wide(const char * filename, const char * mode)
{
wchar_t * filename_w = utf8_to_utf16_string_alloc(filename);
if (filename_w)
{
FILE *ret = NULL;
#if defined(__WINRT__)
HANDLE file_handle = INVALID_HANDLE_VALUE;
DWORD desired_access = 0;
DWORD creation_disposition = OPEN_EXISTING;
int open_flags = O_BINARY;
int fd = -1;
bool append = mode && strchr(mode, 'a');
bool write = mode && strchr(mode, 'w');
bool plus = mode && strchr(mode, '+');
wchar_t *path = filename_w;
while (*path)
{
if (*path == L'/')
*path = L'\\';
path++;
}
if (mode && strchr(mode, 'r'))
desired_access |= GENERIC_READ;
if (write || append || plus)
desired_access |= GENERIC_WRITE;
if (plus)
desired_access |= GENERIC_READ;
if (append)
creation_disposition = OPEN_ALWAYS;
else if (write)
creation_disposition = CREATE_ALWAYS;
if (plus)
open_flags |= O_RDWR;
else if (append || write)
open_flags |= O_WRONLY;
else
open_flags |= O_RDONLY;
if (append)
open_flags |= O_APPEND;
if (write || append)
open_flags |= O_CREAT;
if (write)
open_flags |= O_TRUNC;
file_handle = CreateFile2FromAppW(filename_w, desired_access,
FILE_SHARE_READ | FILE_SHARE_WRITE,
creation_disposition, NULL);
if (file_handle != INVALID_HANDLE_VALUE)
{
fd = _open_osfhandle((intptr_t)file_handle, open_flags);
if (fd != -1)
ret = _fdopen(fd, mode);
if (!ret)
{
if (fd != -1)
_close(fd);
else
CloseHandle(file_handle);
}
}
#else
wchar_t *mode_w = utf8_to_utf16_string_alloc(mode);
if (mode_w)
{
ret = _wfopen(filename_w, mode_w);
free(mode_w);
}
#endif
free(filename_w);
return ret;
}
return NULL;
}
#endif
void *fopen_utf8(const char * filename, const char * mode)
{
#if defined(LEGACY_WIN32_RUNTIME)
if (win32_needs_local_encoding())
return fopen_utf8_ansi(filename, mode);
return fopen_utf8_wide(filename, mode);
#elif defined(LEGACY_WIN32)
return fopen_utf8_ansi(filename, mode);
#else
return fopen_utf8_wide(filename, mode);
#endif
}
#endif