Update libretro api headers
This commit is contained in:
@@ -46,7 +46,10 @@ SOURCES_C += \
|
|||||||
ifeq ($(STATIC_LINKING),1)
|
ifeq ($(STATIC_LINKING),1)
|
||||||
else
|
else
|
||||||
SOURCES_C += $(CORE_DIR)/drivers/libretro/libretro-common/streams/memory_stream.c \
|
SOURCES_C += $(CORE_DIR)/drivers/libretro/libretro-common/streams/memory_stream.c \
|
||||||
$(CORE_DIR)/drivers/libretro/libretro-common/compat/compat_snprintf.c
|
$(CORE_DIR)/drivers/libretro/libretro-common/compat/compat_snprintf.c \
|
||||||
|
$(CORE_DIR)/drivers/libretro/libretro-common/string/stdstring.c \
|
||||||
|
$(CORE_DIR)/drivers/libretro/libretro-common/encodings/encoding_utf.c \
|
||||||
|
$(CORE_DIR)/drivers/libretro/libretro-common/compat/compat_strl.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(DEBUG),1)
|
ifeq ($(DEBUG),1)
|
||||||
|
|||||||
@@ -4,6 +4,9 @@
|
|||||||
|
|
||||||
#ifndef STATIC_LINKING
|
#ifndef STATIC_LINKING
|
||||||
#include "drivers/libretro/libretro-common/streams/memory_stream.c"
|
#include "drivers/libretro/libretro-common/streams/memory_stream.c"
|
||||||
|
#include "drivers/libretro/libretro-common/string/stdstring.c"
|
||||||
|
#include "drivers/libretro/libretro-common/encodings/encoding_utf.c"
|
||||||
|
#include "drivers/libretro/libretro-common/compat/compat_strl.c"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "cart.c"
|
#include "cart.c"
|
||||||
|
|||||||
69
src/drivers/libretro/libretro-common/compat/compat_strl.c
Normal file
69
src/drivers/libretro/libretro-common/compat/compat_strl.c
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
/* Copyright (C) 2010-2018 The RetroArch team
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
* The following license statement only applies to this file (compat_strl.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 <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include <compat/strl.h>
|
||||||
|
|
||||||
|
/* Implementation of strlcpy()/strlcat() based on OpenBSD. */
|
||||||
|
|
||||||
|
#ifndef __MACH__
|
||||||
|
|
||||||
|
size_t strlcpy(char *dest, const char *source, size_t size)
|
||||||
|
{
|
||||||
|
size_t src_size = 0;
|
||||||
|
size_t n = size;
|
||||||
|
|
||||||
|
if (n)
|
||||||
|
while (--n && (*dest++ = *source++)) src_size++;
|
||||||
|
|
||||||
|
if (!n)
|
||||||
|
{
|
||||||
|
if (size) *dest = '\0';
|
||||||
|
while (*source++) src_size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return src_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t strlcat(char *dest, const char *source, size_t size)
|
||||||
|
{
|
||||||
|
size_t len = strlen(dest);
|
||||||
|
|
||||||
|
dest += len;
|
||||||
|
|
||||||
|
if (len > size)
|
||||||
|
size = 0;
|
||||||
|
else
|
||||||
|
size -= len;
|
||||||
|
|
||||||
|
return len + strlcpy(dest, source, size);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char *strldup(const char *s, size_t n)
|
||||||
|
{
|
||||||
|
char *dst = (char*)malloc(sizeof(char) * (n + 1));
|
||||||
|
strlcpy(dst, s, n);
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
510
src/drivers/libretro/libretro-common/encodings/encoding_utf.c
Normal file
510
src/drivers/libretro/libretro-common/encodings/encoding_utf.c
Normal file
@@ -0,0 +1,510 @@
|
|||||||
|
/* Copyright (C) 2010-2018 The RetroArch team
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
* The following license statement only applies to this file (encoding_utf.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 <stdlib.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <boolean.h>
|
||||||
|
#include <compat/strl.h>
|
||||||
|
#include <retro_inline.h>
|
||||||
|
|
||||||
|
#include <encodings/utf.h>
|
||||||
|
|
||||||
|
#if defined(_WIN32) && !defined(_XBOX)
|
||||||
|
#include <windows.h>
|
||||||
|
#elif defined(_XBOX)
|
||||||
|
#include <xtl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static unsigned leading_ones(uint8_t c)
|
||||||
|
{
|
||||||
|
unsigned ones = 0;
|
||||||
|
while (c & 0x80)
|
||||||
|
{
|
||||||
|
ones++;
|
||||||
|
c <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ones;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Simple implementation. Assumes the sequence is
|
||||||
|
* properly synchronized and terminated. */
|
||||||
|
|
||||||
|
size_t utf8_conv_utf32(uint32_t *out, size_t out_chars,
|
||||||
|
const char *in, size_t in_size)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
size_t ret = 0;
|
||||||
|
while (in_size && out_chars)
|
||||||
|
{
|
||||||
|
unsigned extra, shift;
|
||||||
|
uint32_t c;
|
||||||
|
uint8_t first = *in++;
|
||||||
|
unsigned ones = leading_ones(first);
|
||||||
|
|
||||||
|
if (ones > 6 || ones == 1) /* Invalid or desync. */
|
||||||
|
break;
|
||||||
|
|
||||||
|
extra = ones ? ones - 1 : ones;
|
||||||
|
if (1 + extra > in_size) /* Overflow. */
|
||||||
|
break;
|
||||||
|
|
||||||
|
shift = (extra - 1) * 6;
|
||||||
|
c = (first & ((1 << (7 - ones)) - 1)) << (6 * extra);
|
||||||
|
|
||||||
|
for (i = 0; i < extra; i++, in++, shift -= 6)
|
||||||
|
c |= (*in & 0x3f) << shift;
|
||||||
|
|
||||||
|
*out++ = c;
|
||||||
|
in_size -= 1 + extra;
|
||||||
|
out_chars--;
|
||||||
|
ret++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
unsigned numAdds;
|
||||||
|
uint32_t value;
|
||||||
|
|
||||||
|
if (in_pos == in_size)
|
||||||
|
{
|
||||||
|
*out_chars = out_pos;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
value = in[in_pos++];
|
||||||
|
if (value < 0x80)
|
||||||
|
{
|
||||||
|
if (out)
|
||||||
|
out[out_pos] = (char)value;
|
||||||
|
out_pos++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value >= 0xD800 && value < 0xE000)
|
||||||
|
{
|
||||||
|
uint32_t c2;
|
||||||
|
|
||||||
|
if (value >= 0xDC00 || in_pos == in_size)
|
||||||
|
break;
|
||||||
|
c2 = in[in_pos++];
|
||||||
|
if (c2 < 0xDC00 || c2 >= 0xE000)
|
||||||
|
break;
|
||||||
|
value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (numAdds = 1; numAdds < 5; numAdds++)
|
||||||
|
if (value < (((uint32_t)1) << (numAdds * 5 + 6)))
|
||||||
|
break;
|
||||||
|
if (out)
|
||||||
|
out[out_pos] = (char)(kUtf8Limits[numAdds - 1]
|
||||||
|
+ (value >> (6 * numAdds)));
|
||||||
|
out_pos++;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
numAdds--;
|
||||||
|
if (out)
|
||||||
|
out[out_pos] = (char)(0x80
|
||||||
|
+ ((value >> (6 * numAdds)) & 0x3F));
|
||||||
|
out_pos++;
|
||||||
|
}while (numAdds != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_chars = out_pos;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Acts mostly like strlcpy.
|
||||||
|
*
|
||||||
|
* Copies the given number of UTF-8 characters,
|
||||||
|
* but at most d_len bytes.
|
||||||
|
*
|
||||||
|
* Always NULL terminates.
|
||||||
|
* Does not copy half a character.
|
||||||
|
*
|
||||||
|
* Returns number of bytes. 's' is assumed valid UTF-8.
|
||||||
|
* Use only if 'chars' is considerably less than 'd_len'. */
|
||||||
|
size_t utf8cpy(char *d, size_t d_len, const char *s, size_t chars)
|
||||||
|
{
|
||||||
|
const uint8_t *sb = (const uint8_t*)s;
|
||||||
|
const uint8_t *sb_org = sb;
|
||||||
|
|
||||||
|
if (!s)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
while (*sb && chars-- > 0)
|
||||||
|
{
|
||||||
|
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--;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(d, sb_org, sb-sb_org);
|
||||||
|
d[sb-sb_org] = '\0';
|
||||||
|
|
||||||
|
return 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++;
|
||||||
|
chars--;
|
||||||
|
} while(chars);
|
||||||
|
return (const char*)strb;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t utf8len(const char *string)
|
||||||
|
{
|
||||||
|
size_t ret = 0;
|
||||||
|
|
||||||
|
if (!string)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
while (*string)
|
||||||
|
{
|
||||||
|
if ((*string & 0xC0) != 0x80)
|
||||||
|
ret++;
|
||||||
|
string++;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
uint32_t ret = 0;
|
||||||
|
|
||||||
|
if (first < 128)
|
||||||
|
return first;
|
||||||
|
|
||||||
|
ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F);
|
||||||
|
if (first >= 0xE0)
|
||||||
|
{
|
||||||
|
ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F);
|
||||||
|
if (first >= 0xF0)
|
||||||
|
{
|
||||||
|
ret = (ret << 6) | (utf8_walkbyte(string) & 0x3F);
|
||||||
|
return ret | (first & 7) << 18;
|
||||||
|
}
|
||||||
|
return ret | (first & 15) << 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret | (first & 31) << 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool utf16_to_char(uint8_t **utf_data,
|
||||||
|
size_t *dest_len, const uint16_t *in)
|
||||||
|
{
|
||||||
|
unsigned len = 0;
|
||||||
|
|
||||||
|
while (in[len] != '\0')
|
||||||
|
len++;
|
||||||
|
|
||||||
|
utf16_conv_utf8(NULL, dest_len, in, len);
|
||||||
|
*dest_len += 1;
|
||||||
|
*utf_data = (uint8_t*)malloc(*dest_len);
|
||||||
|
if (*utf_data == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return utf16_conv_utf8(*utf_data, dest_len, in, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool utf16_to_char_string(const uint16_t *in, char *s, size_t len)
|
||||||
|
{
|
||||||
|
size_t dest_len = 0;
|
||||||
|
uint8_t *utf16_data = NULL;
|
||||||
|
bool ret = utf16_to_char(&utf16_data, &dest_len, in);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
utf16_data[dest_len] = 0;
|
||||||
|
strlcpy(s, (const char*)utf16_data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(utf16_data);
|
||||||
|
utf16_data = NULL;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_WIN32) && !defined(_XBOX) && !defined(UNICODE)
|
||||||
|
/* Returned pointer MUST be freed by the caller if non-NULL. */
|
||||||
|
static char *mb_to_mb_string_alloc(const char *str,
|
||||||
|
enum CodePage cp_in, enum CodePage cp_out)
|
||||||
|
{
|
||||||
|
char *path_buf = NULL;
|
||||||
|
wchar_t *path_buf_wide = NULL;
|
||||||
|
int path_buf_len = 0;
|
||||||
|
int path_buf_wide_len = MultiByteToWideChar(cp_in, 0, str, -1, NULL, 0);
|
||||||
|
|
||||||
|
/* Windows 95 will return 0 from these functions with
|
||||||
|
* a UTF8 codepage set without MSLU.
|
||||||
|
*
|
||||||
|
* From an unknown MSDN version (others omit this info):
|
||||||
|
* - CP_UTF8 Windows 98/Me, Windows NT 4.0 and later:
|
||||||
|
* Translate using UTF-8. When this is set, dwFlags must be zero.
|
||||||
|
* - Windows 95: Under the Microsoft Layer for Unicode,
|
||||||
|
* MultiByteToWideChar also supports CP_UTF7 and CP_UTF8.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (path_buf_wide_len)
|
||||||
|
{
|
||||||
|
path_buf_wide = (wchar_t*)
|
||||||
|
calloc(path_buf_wide_len + sizeof(wchar_t), sizeof(wchar_t));
|
||||||
|
|
||||||
|
if (path_buf_wide)
|
||||||
|
{
|
||||||
|
MultiByteToWideChar(cp_in, 0,
|
||||||
|
str, -1, path_buf_wide, path_buf_wide_len);
|
||||||
|
|
||||||
|
if (*path_buf_wide)
|
||||||
|
{
|
||||||
|
path_buf_len = WideCharToMultiByte(cp_out, 0,
|
||||||
|
path_buf_wide, -1, NULL, 0, NULL, NULL);
|
||||||
|
|
||||||
|
if (path_buf_len)
|
||||||
|
{
|
||||||
|
path_buf = (char*)
|
||||||
|
calloc(path_buf_len + sizeof(char), sizeof(char));
|
||||||
|
|
||||||
|
if (path_buf)
|
||||||
|
{
|
||||||
|
WideCharToMultiByte(cp_out, 0,
|
||||||
|
path_buf_wide, -1, path_buf,
|
||||||
|
path_buf_len, NULL, NULL);
|
||||||
|
|
||||||
|
free(path_buf_wide);
|
||||||
|
|
||||||
|
if (*path_buf)
|
||||||
|
return path_buf;
|
||||||
|
|
||||||
|
free(path_buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
free(path_buf_wide);
|
||||||
|
return strdup(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return strdup(str);
|
||||||
|
|
||||||
|
if (path_buf_wide)
|
||||||
|
free(path_buf_wide);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Returned pointer MUST be freed by the caller if non-NULL. */
|
||||||
|
char* utf8_to_local_string_alloc(const char *str)
|
||||||
|
{
|
||||||
|
if (str && *str)
|
||||||
|
{
|
||||||
|
#if defined(_WIN32) && !defined(_XBOX) && !defined(UNICODE)
|
||||||
|
return mb_to_mb_string_alloc(str, CODEPAGE_UTF8, CODEPAGE_LOCAL);
|
||||||
|
#else
|
||||||
|
/* assume string needs no modification if not on Windows */
|
||||||
|
return strdup(str);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returned pointer MUST be freed by the caller if non-NULL. */
|
||||||
|
char* local_to_utf8_string_alloc(const char *str)
|
||||||
|
{
|
||||||
|
if (str && *str)
|
||||||
|
{
|
||||||
|
#if defined(_WIN32) && !defined(_XBOX) && !defined(UNICODE)
|
||||||
|
return mb_to_mb_string_alloc(str, CODEPAGE_LOCAL, CODEPAGE_UTF8);
|
||||||
|
#else
|
||||||
|
/* assume string needs no modification if not on Windows */
|
||||||
|
return strdup(str);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returned pointer MUST be freed by the caller if non-NULL. */
|
||||||
|
wchar_t* utf8_to_utf16_string_alloc(const char *str)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
int len = 0;
|
||||||
|
int out_len = 0;
|
||||||
|
#else
|
||||||
|
size_t len = 0;
|
||||||
|
size_t out_len = 0;
|
||||||
|
#endif
|
||||||
|
wchar_t *buf = NULL;
|
||||||
|
|
||||||
|
if (!str || !*str)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
len = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
|
||||||
|
|
||||||
|
if (len)
|
||||||
|
{
|
||||||
|
buf = (wchar_t*)calloc(len, sizeof(wchar_t));
|
||||||
|
|
||||||
|
if (!buf)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
out_len = MultiByteToWideChar(CP_UTF8, 0, str, -1, buf, len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* fallback to ANSI codepage instead */
|
||||||
|
len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
|
||||||
|
|
||||||
|
if (len)
|
||||||
|
{
|
||||||
|
buf = (wchar_t*)calloc(len, sizeof(wchar_t));
|
||||||
|
|
||||||
|
if (!buf)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
out_len = MultiByteToWideChar(CP_ACP, 0, str, -1, buf, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out_len < 0)
|
||||||
|
{
|
||||||
|
free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* NOTE: For now, assume non-Windows platforms' locale is already UTF-8. */
|
||||||
|
len = mbstowcs(NULL, str, 0) + 1;
|
||||||
|
|
||||||
|
if (len)
|
||||||
|
{
|
||||||
|
buf = (wchar_t*)calloc(len, sizeof(wchar_t));
|
||||||
|
|
||||||
|
if (!buf)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
out_len = mbstowcs(buf, str, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out_len == (size_t)-1)
|
||||||
|
{
|
||||||
|
free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returned pointer MUST be freed by the caller if non-NULL. */
|
||||||
|
char* utf16_to_utf8_string_alloc(const wchar_t *str)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
int len = 0;
|
||||||
|
#else
|
||||||
|
size_t len = 0;
|
||||||
|
#endif
|
||||||
|
char *buf = NULL;
|
||||||
|
|
||||||
|
if (!str || !*str)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
{
|
||||||
|
UINT code_page = CP_UTF8;
|
||||||
|
len = WideCharToMultiByte(code_page,
|
||||||
|
0, str, -1, NULL, 0, NULL, NULL);
|
||||||
|
|
||||||
|
/* fallback to ANSI codepage instead */
|
||||||
|
if (!len)
|
||||||
|
{
|
||||||
|
code_page = CP_ACP;
|
||||||
|
len = WideCharToMultiByte(code_page,
|
||||||
|
0, str, -1, NULL, 0, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = (char*)calloc(len, sizeof(char));
|
||||||
|
|
||||||
|
if (!buf)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (WideCharToMultiByte(code_page,
|
||||||
|
0, str, -1, buf, len, NULL, NULL) < 0)
|
||||||
|
{
|
||||||
|
free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* NOTE: For now, assume non-Windows platforms'
|
||||||
|
* locale is already UTF-8. */
|
||||||
|
len = wcstombs(NULL, str, 0) + 1;
|
||||||
|
|
||||||
|
if (len)
|
||||||
|
{
|
||||||
|
buf = (char*)calloc(len, sizeof(char));
|
||||||
|
|
||||||
|
if (!buf)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (wcstombs(buf, str, len) == (size_t)-1)
|
||||||
|
{
|
||||||
|
free(buf);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
39
src/drivers/libretro/libretro-common/include/boolean.h
Normal file
39
src/drivers/libretro/libretro-common/include/boolean.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/* Copyright (C) 2010-2018 The RetroArch team
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
* The following license statement only applies to this file (boolean.h).
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge,
|
||||||
|
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||||
|
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LIBRETRO_SDK_BOOLEAN_H
|
||||||
|
#define __LIBRETRO_SDK_BOOLEAN_H
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER < 1800 && !defined(SN_TARGET_PS3)
|
||||||
|
/* Hack applied for MSVC when compiling in C89 mode as it isn't C99 compliant. */
|
||||||
|
#define bool unsigned char
|
||||||
|
#define true 1
|
||||||
|
#define false 0
|
||||||
|
#else
|
||||||
|
#include <stdbool.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -31,6 +31,7 @@ extern "C" {
|
|||||||
|
|
||||||
/* Pre-MSVC 2015 compilers don't implement snprintf in a cross-platform manner. */
|
/* Pre-MSVC 2015 compilers don't implement snprintf in a cross-platform manner. */
|
||||||
#if _MSC_VER < 1900
|
#if _MSC_VER < 1900
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#ifndef snprintf
|
#ifndef snprintf
|
||||||
#define snprintf c99_snprintf_retro__
|
#define snprintf c99_snprintf_retro__
|
||||||
@@ -41,6 +42,7 @@ extern "C" {
|
|||||||
|
|
||||||
/* Pre-MSVC 2008 compilers don't implement vsnprintf in a cross-platform manner? Not sure about this one. */
|
/* Pre-MSVC 2008 compilers don't implement vsnprintf in a cross-platform manner? Not sure about this one. */
|
||||||
#if _MSC_VER < 1500
|
#if _MSC_VER < 1500
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#ifndef vsnprintf
|
#ifndef vsnprintf
|
||||||
|
|||||||
59
src/drivers/libretro/libretro-common/include/compat/strl.h
Normal file
59
src/drivers/libretro/libretro-common/include/compat/strl.h
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/* Copyright (C) 2010-2018 The RetroArch team
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
* The following license statement only applies to this file (strl.h).
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge,
|
||||||
|
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||||
|
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LIBRETRO_SDK_COMPAT_STRL_H
|
||||||
|
#define __LIBRETRO_SDK_COMPAT_STRL_H
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#if defined(RARCH_INTERNAL) && defined(HAVE_CONFIG_H)
|
||||||
|
#include "../../../config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <retro_common_api.h>
|
||||||
|
|
||||||
|
RETRO_BEGIN_DECLS
|
||||||
|
|
||||||
|
#ifdef __MACH__
|
||||||
|
#ifndef HAVE_STRL
|
||||||
|
#define HAVE_STRL
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_STRL
|
||||||
|
/* Avoid possible naming collisions during link since
|
||||||
|
* we prefer to use the actual name. */
|
||||||
|
#define strlcpy(dst, src, size) strlcpy_retro__(dst, src, size)
|
||||||
|
|
||||||
|
#define strlcat(dst, src, size) strlcat_retro__(dst, src, size)
|
||||||
|
|
||||||
|
size_t strlcpy(char *dest, const char *source, size_t size);
|
||||||
|
size_t strlcat(char *dest, const char *source, size_t size);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char *strldup(const char *s, size_t n);
|
||||||
|
|
||||||
|
RETRO_END_DECLS
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
#ifndef _LIBRETRO_ENCODINGS_BASE64_H
|
||||||
|
#define _LIBRETRO_ENCODINGS_BASE64_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include <retro_common_api.h>
|
||||||
|
|
||||||
|
RETRO_BEGIN_DECLS
|
||||||
|
|
||||||
|
const static char* b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
|
|
||||||
|
/* maps A=>0,B=>1.. */
|
||||||
|
const static unsigned char unb64[]={
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 62, 0, 0, 0, 63, 52, 53,
|
||||||
|
54, 55, 56, 57, 58, 59, 60, 61, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 1, 2, 3, 4,
|
||||||
|
5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||||
|
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
|
||||||
|
25, 0, 0, 0, 0, 0, 0, 26, 27, 28,
|
||||||
|
29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
|
||||||
|
39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
|
||||||
|
49, 50, 51, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0,
|
||||||
|
}; /* This array has 256 elements */
|
||||||
|
|
||||||
|
char* base64(const void* binaryData, int len, int *flen);
|
||||||
|
unsigned char* unbase64(const char* ascii, int len, int *flen);
|
||||||
|
|
||||||
|
RETRO_END_DECLS
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/* Copyright (C) 2010-2018 The RetroArch team
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
* The following license statement only applies to this file (crc32.h).
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge,
|
||||||
|
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||||
|
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LIBRETRO_ENCODINGS_CRC32_H
|
||||||
|
#define _LIBRETRO_ENCODINGS_CRC32_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include <retro_common_api.h>
|
||||||
|
|
||||||
|
RETRO_BEGIN_DECLS
|
||||||
|
|
||||||
|
uint32_t encoding_crc32(uint32_t crc, const uint8_t *buf, size_t len);
|
||||||
|
uint32_t file_crc32(uint32_t crc, const char *path);
|
||||||
|
|
||||||
|
RETRO_END_DECLS
|
||||||
|
|
||||||
|
#endif
|
||||||
67
src/drivers/libretro/libretro-common/include/encodings/utf.h
Normal file
67
src/drivers/libretro/libretro-common/include/encodings/utf.h
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
/* Copyright (C) 2010-2018 The RetroArch team
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
* The following license statement only applies to this file (utf.h).
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge,
|
||||||
|
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||||
|
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LIBRETRO_ENCODINGS_UTF_H
|
||||||
|
#define _LIBRETRO_ENCODINGS_UTF_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include <boolean.h>
|
||||||
|
|
||||||
|
#include <retro_common_api.h>
|
||||||
|
|
||||||
|
RETRO_BEGIN_DECLS
|
||||||
|
|
||||||
|
enum CodePage
|
||||||
|
{
|
||||||
|
CODEPAGE_LOCAL = 0, /* CP_ACP */
|
||||||
|
CODEPAGE_UTF8 = 65001 /* CP_UTF8 */
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t utf8_conv_utf32(uint32_t *out, size_t out_chars,
|
||||||
|
const char *in, size_t in_size);
|
||||||
|
|
||||||
|
bool utf16_conv_utf8(uint8_t *out, size_t *out_chars,
|
||||||
|
const uint16_t *in, size_t in_size);
|
||||||
|
|
||||||
|
size_t utf8len(const char *string);
|
||||||
|
|
||||||
|
size_t utf8cpy(char *d, size_t d_len, const char *s, size_t chars);
|
||||||
|
|
||||||
|
const char *utf8skip(const char *str, size_t chars);
|
||||||
|
|
||||||
|
uint32_t utf8_walk(const char **string);
|
||||||
|
|
||||||
|
bool utf16_to_char_string(const uint16_t *in, char *s, size_t len);
|
||||||
|
|
||||||
|
char* utf8_to_local_string_alloc(const char *str);
|
||||||
|
|
||||||
|
char* local_to_utf8_string_alloc(const char *str);
|
||||||
|
|
||||||
|
wchar_t* utf8_to_utf16_string_alloc(const char *str);
|
||||||
|
|
||||||
|
char* utf16_to_utf8_string_alloc(const wchar_t *str);
|
||||||
|
|
||||||
|
RETRO_END_DECLS
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
/* Copyright (C) 2010-2018 The RetroArch team
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
* The following license statement only applies to this file (utf.h).
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge,
|
||||||
|
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||||
|
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LIBRETRO_ENCODINGS_WIN32_H
|
||||||
|
#define _LIBRETRO_ENCODINGS_WIN32_H
|
||||||
|
|
||||||
|
#ifndef _XBOX
|
||||||
|
#ifdef _WIN32
|
||||||
|
/*#define UNICODE
|
||||||
|
#include <tchar.h>
|
||||||
|
#include <wchar.h>*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <encodings/utf.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef UNICODE
|
||||||
|
#define CHAR_TO_WCHAR_ALLOC(s, ws) \
|
||||||
|
size_t ws##_size = (NULL != s && s[0] ? strlen(s) : 0) + 1; \
|
||||||
|
wchar_t *ws = (wchar_t*)calloc(ws##_size, 2); \
|
||||||
|
if (NULL != s && s[0]) \
|
||||||
|
MultiByteToWideChar(CP_UTF8, 0, s, -1, ws, ws##_size / sizeof(wchar_t));
|
||||||
|
|
||||||
|
#define WCHAR_TO_CHAR_ALLOC(ws, s) \
|
||||||
|
size_t s##_size = ((NULL != ws && ws[0] ? wcslen((const wchar_t*)ws) : 0) / 2) + 1; \
|
||||||
|
char *s = (char*)calloc(s##_size, 1); \
|
||||||
|
if (NULL != ws && ws[0]) \
|
||||||
|
utf16_to_char_string((const uint16_t*)ws, s, s##_size);
|
||||||
|
|
||||||
|
#else
|
||||||
|
#define CHAR_TO_WCHAR_ALLOC(s, ws) char *ws = (NULL != s && s[0] ? strdup(s) : NULL);
|
||||||
|
#define WCHAR_TO_CHAR_ALLOC(ws, s) char *s = (NULL != ws && ws[0] ? strdup(ws) : NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1117,7 +1117,7 @@ enum retro_mod
|
|||||||
* This may be still be done regardless of the core options
|
* This may be still be done regardless of the core options
|
||||||
* interface version.
|
* interface version.
|
||||||
*
|
*
|
||||||
* If version is 1 however, core options may instead be set by
|
* If version is >= 1 however, core options may instead be set by
|
||||||
* passing an array of retro_core_option_definition structs to
|
* passing an array of retro_core_option_definition structs to
|
||||||
* RETRO_ENVIRONMENT_SET_CORE_OPTIONS, or a 2D array of
|
* RETRO_ENVIRONMENT_SET_CORE_OPTIONS, or a 2D array of
|
||||||
* retro_core_option_definition structs to RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL.
|
* retro_core_option_definition structs to RETRO_ENVIRONMENT_SET_CORE_OPTIONS_INTL.
|
||||||
@@ -1132,8 +1132,8 @@ enum retro_mod
|
|||||||
* GET_VARIABLE.
|
* GET_VARIABLE.
|
||||||
* This allows the frontend to present these variables to
|
* This allows the frontend to present these variables to
|
||||||
* a user dynamically.
|
* a user dynamically.
|
||||||
* This should only be called if RETRO_ENVIRONMENT_GET_ENHANCED_CORE_OPTIONS
|
* This should only be called if RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION
|
||||||
* returns an API version of 1.
|
* returns an API version of >= 1.
|
||||||
* This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES.
|
* This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES.
|
||||||
* This should be called the first time as early as
|
* This should be called the first time as early as
|
||||||
* possible (ideally in retro_set_environment).
|
* possible (ideally in retro_set_environment).
|
||||||
@@ -1169,8 +1169,6 @@ enum retro_mod
|
|||||||
* i.e. it should be feasible to cycle through options
|
* i.e. it should be feasible to cycle through options
|
||||||
* without a keyboard.
|
* without a keyboard.
|
||||||
*
|
*
|
||||||
* First entry should be treated as a default.
|
|
||||||
*
|
|
||||||
* Example entry:
|
* Example entry:
|
||||||
* {
|
* {
|
||||||
* "foo_option",
|
* "foo_option",
|
||||||
@@ -1196,8 +1194,8 @@ enum retro_mod
|
|||||||
* GET_VARIABLE.
|
* GET_VARIABLE.
|
||||||
* This allows the frontend to present these variables to
|
* This allows the frontend to present these variables to
|
||||||
* a user dynamically.
|
* a user dynamically.
|
||||||
* This should only be called if RETRO_ENVIRONMENT_GET_ENHANCED_CORE_OPTIONS
|
* This should only be called if RETRO_ENVIRONMENT_GET_CORE_OPTIONS_VERSION
|
||||||
* returns an API version of 1.
|
* returns an API version of >= 1.
|
||||||
* This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES.
|
* This should be called instead of RETRO_ENVIRONMENT_SET_VARIABLES.
|
||||||
* This should be called the first time as early as
|
* This should be called the first time as early as
|
||||||
* possible (ideally in retro_set_environment).
|
* possible (ideally in retro_set_environment).
|
||||||
@@ -1248,6 +1246,47 @@ enum retro_mod
|
|||||||
* default when calling SET_VARIABLES/SET_CORE_OPTIONS.
|
* default when calling SET_VARIABLES/SET_CORE_OPTIONS.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define RETRO_ENVIRONMENT_GET_PREFERRED_HW_RENDER 56
|
||||||
|
/* unsigned * --
|
||||||
|
*
|
||||||
|
* Allows an implementation to ask frontend preferred hardware
|
||||||
|
* context to use. Core should use this information to deal
|
||||||
|
* with what specific context to request with SET_HW_RENDER.
|
||||||
|
*
|
||||||
|
* 'data' points to an unsigned variable
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define RETRO_ENVIRONMENT_GET_DISK_CONTROL_INTERFACE_VERSION 57
|
||||||
|
/* unsigned * --
|
||||||
|
* Unsigned value is the API version number of the disk control
|
||||||
|
* interface supported by the frontend. If callback return false,
|
||||||
|
* API version is assumed to be 0.
|
||||||
|
*
|
||||||
|
* In legacy code, the disk control interface is defined by passing
|
||||||
|
* a struct of type retro_disk_control_callback to
|
||||||
|
* RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE.
|
||||||
|
* This may be still be done regardless of the disk control
|
||||||
|
* interface version.
|
||||||
|
*
|
||||||
|
* If version is >= 1 however, the disk control interface may
|
||||||
|
* instead be defined by passing a struct of type
|
||||||
|
* retro_disk_control_ext_callback to
|
||||||
|
* RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE.
|
||||||
|
* This allows the core to provide additional information about
|
||||||
|
* disk images to the frontend and/or enables extra
|
||||||
|
* disk control functionality by the frontend.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE 58
|
||||||
|
/* const struct retro_disk_control_ext_callback * --
|
||||||
|
* Sets an interface which frontend can use to eject and insert
|
||||||
|
* disk images, and also obtain information about individual
|
||||||
|
* disk image files registered by the core.
|
||||||
|
* This is used for games which consist of multiple images and
|
||||||
|
* must be manually swapped out by the user (e.g. PSX, floppy disk
|
||||||
|
* based systems).
|
||||||
|
*/
|
||||||
|
|
||||||
/* VFS functionality */
|
/* VFS functionality */
|
||||||
|
|
||||||
/* File paths:
|
/* File paths:
|
||||||
@@ -1924,6 +1963,10 @@ enum retro_sensor_action
|
|||||||
{
|
{
|
||||||
RETRO_SENSOR_ACCELEROMETER_ENABLE = 0,
|
RETRO_SENSOR_ACCELEROMETER_ENABLE = 0,
|
||||||
RETRO_SENSOR_ACCELEROMETER_DISABLE,
|
RETRO_SENSOR_ACCELEROMETER_DISABLE,
|
||||||
|
RETRO_SENSOR_GYROSCOPE_ENABLE,
|
||||||
|
RETRO_SENSOR_GYROSCOPE_DISABLE,
|
||||||
|
RETRO_SENSOR_ILLUMINANCE_ENABLE,
|
||||||
|
RETRO_SENSOR_ILLUMINANCE_DISABLE,
|
||||||
|
|
||||||
RETRO_SENSOR_DUMMY = INT_MAX
|
RETRO_SENSOR_DUMMY = INT_MAX
|
||||||
};
|
};
|
||||||
@@ -1932,6 +1975,10 @@ enum retro_sensor_action
|
|||||||
#define RETRO_SENSOR_ACCELEROMETER_X 0
|
#define RETRO_SENSOR_ACCELEROMETER_X 0
|
||||||
#define RETRO_SENSOR_ACCELEROMETER_Y 1
|
#define RETRO_SENSOR_ACCELEROMETER_Y 1
|
||||||
#define RETRO_SENSOR_ACCELEROMETER_Z 2
|
#define RETRO_SENSOR_ACCELEROMETER_Z 2
|
||||||
|
#define RETRO_SENSOR_GYROSCOPE_X 3
|
||||||
|
#define RETRO_SENSOR_GYROSCOPE_Y 4
|
||||||
|
#define RETRO_SENSOR_GYROSCOPE_Z 5
|
||||||
|
#define RETRO_SENSOR_ILLUMINANCE 6
|
||||||
|
|
||||||
typedef bool (RETRO_CALLCONV *retro_set_sensor_state_t)(unsigned port,
|
typedef bool (RETRO_CALLCONV *retro_set_sensor_state_t)(unsigned port,
|
||||||
enum retro_sensor_action action, unsigned rate);
|
enum retro_sensor_action action, unsigned rate);
|
||||||
@@ -2289,7 +2336,8 @@ struct retro_keyboard_callback
|
|||||||
retro_keyboard_event_t callback;
|
retro_keyboard_event_t callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Callbacks for RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE.
|
/* Callbacks for RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE &
|
||||||
|
* RETRO_ENVIRONMENT_SET_DISK_CONTROL_EXT_INTERFACE.
|
||||||
* Should be set for implementations which can swap out multiple disk
|
* Should be set for implementations which can swap out multiple disk
|
||||||
* images in runtime.
|
* images in runtime.
|
||||||
*
|
*
|
||||||
@@ -2347,6 +2395,53 @@ typedef bool (RETRO_CALLCONV *retro_replace_image_index_t)(unsigned index,
|
|||||||
* with replace_image_index. */
|
* with replace_image_index. */
|
||||||
typedef bool (RETRO_CALLCONV *retro_add_image_index_t)(void);
|
typedef bool (RETRO_CALLCONV *retro_add_image_index_t)(void);
|
||||||
|
|
||||||
|
/* Sets initial image to insert in drive when calling
|
||||||
|
* core_load_game().
|
||||||
|
* Since we cannot pass the initial index when loading
|
||||||
|
* content (this would require a major API change), this
|
||||||
|
* is set by the frontend *before* calling the core's
|
||||||
|
* retro_load_game()/retro_load_game_special() implementation.
|
||||||
|
* A core should therefore cache the index/path values and handle
|
||||||
|
* them inside retro_load_game()/retro_load_game_special().
|
||||||
|
* - If 'index' is invalid (index >= get_num_images()), the
|
||||||
|
* core should ignore the set value and instead use 0
|
||||||
|
* - 'path' is used purely for error checking - i.e. when
|
||||||
|
* content is loaded, the core should verify that the
|
||||||
|
* disk specified by 'index' has the specified file path.
|
||||||
|
* This is to guard against auto selecting the wrong image
|
||||||
|
* if (for example) the user should modify an existing M3U
|
||||||
|
* playlist. We have to let the core handle this because
|
||||||
|
* set_initial_image() must be called before loading content,
|
||||||
|
* i.e. the frontend cannot access image paths in advance
|
||||||
|
* and thus cannot perform the error check itself.
|
||||||
|
* If set path and content path do not match, the core should
|
||||||
|
* ignore the set 'index' value and instead use 0
|
||||||
|
* Returns 'false' if index or 'path' are invalid, or core
|
||||||
|
* does not support this functionality
|
||||||
|
*/
|
||||||
|
typedef bool (RETRO_CALLCONV *retro_set_initial_image_t)(unsigned index, const char *path);
|
||||||
|
|
||||||
|
/* Fetches the path of the specified disk image file.
|
||||||
|
* Returns 'false' if index is invalid (index >= get_num_images())
|
||||||
|
* or path is otherwise unavailable.
|
||||||
|
*/
|
||||||
|
typedef bool (RETRO_CALLCONV *retro_get_image_path_t)(unsigned index, char *path, size_t len);
|
||||||
|
|
||||||
|
/* Fetches a core-provided 'label' for the specified disk
|
||||||
|
* image file. In the simplest case this may be a file name
|
||||||
|
* (without extension), but for cores with more complex
|
||||||
|
* content requirements information may be provided to
|
||||||
|
* facilitate user disk swapping - for example, a core
|
||||||
|
* running floppy-disk-based content may uniquely label
|
||||||
|
* save disks, data disks, level disks, etc. with names
|
||||||
|
* corresponding to in-game disk change prompts (so the
|
||||||
|
* frontend can provide better user guidance than a 'dumb'
|
||||||
|
* disk index value).
|
||||||
|
* Returns 'false' if index is invalid (index >= get_num_images())
|
||||||
|
* or label is otherwise unavailable.
|
||||||
|
*/
|
||||||
|
typedef bool (RETRO_CALLCONV *retro_get_image_label_t)(unsigned index, char *label, size_t len);
|
||||||
|
|
||||||
struct retro_disk_control_callback
|
struct retro_disk_control_callback
|
||||||
{
|
{
|
||||||
retro_set_eject_state_t set_eject_state;
|
retro_set_eject_state_t set_eject_state;
|
||||||
@@ -2360,6 +2455,27 @@ struct retro_disk_control_callback
|
|||||||
retro_add_image_index_t add_image_index;
|
retro_add_image_index_t add_image_index;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct retro_disk_control_ext_callback
|
||||||
|
{
|
||||||
|
retro_set_eject_state_t set_eject_state;
|
||||||
|
retro_get_eject_state_t get_eject_state;
|
||||||
|
|
||||||
|
retro_get_image_index_t get_image_index;
|
||||||
|
retro_set_image_index_t set_image_index;
|
||||||
|
retro_get_num_images_t get_num_images;
|
||||||
|
|
||||||
|
retro_replace_image_index_t replace_image_index;
|
||||||
|
retro_add_image_index_t add_image_index;
|
||||||
|
|
||||||
|
/* NOTE: Frontend will only attempt to record/restore
|
||||||
|
* last used disk index if both set_initial_image()
|
||||||
|
* and get_image_path() are implemented */
|
||||||
|
retro_set_initial_image_t set_initial_image; /* Optional - may be NULL */
|
||||||
|
|
||||||
|
retro_get_image_path_t get_image_path; /* Optional - may be NULL */
|
||||||
|
retro_get_image_label_t get_image_label; /* Optional - may be NULL */
|
||||||
|
};
|
||||||
|
|
||||||
enum retro_pixel_format
|
enum retro_pixel_format
|
||||||
{
|
{
|
||||||
/* 0RGB1555, native endian.
|
/* 0RGB1555, native endian.
|
||||||
@@ -2504,8 +2620,20 @@ struct retro_core_option_display
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Maximum number of values permitted for a core option
|
/* Maximum number of values permitted for a core option
|
||||||
* NOTE: This may be increased on a core-by-core basis
|
* > Note: We have to set a maximum value due the limitations
|
||||||
* if required (doing so has no effect on the frontend) */
|
* of the C language - i.e. it is not possible to create an
|
||||||
|
* array of structs each containing a variable sized array,
|
||||||
|
* so the retro_core_option_definition values array must
|
||||||
|
* have a fixed size. The size limit of 128 is a balancing
|
||||||
|
* act - it needs to be large enough to support all 'sane'
|
||||||
|
* core options, but setting it too large may impact low memory
|
||||||
|
* platforms. In practise, if a core option has more than
|
||||||
|
* 128 values then the implementation is likely flawed.
|
||||||
|
* To quote the above API reference:
|
||||||
|
* "The number of possible options should be very limited
|
||||||
|
* i.e. it should be feasible to cycle through options
|
||||||
|
* without a keyboard."
|
||||||
|
*/
|
||||||
#define RETRO_NUM_CORE_OPTION_VALUES_MAX 128
|
#define RETRO_NUM_CORE_OPTION_VALUES_MAX 128
|
||||||
|
|
||||||
struct retro_core_option_value
|
struct retro_core_option_value
|
||||||
|
|||||||
@@ -89,7 +89,9 @@ typedef int ssize_t;
|
|||||||
/* C++11 says this one isn't needed, but apparently (some versions of) mingw require it anyways */
|
/* C++11 says this one isn't needed, but apparently (some versions of) mingw require it anyways */
|
||||||
/* https://stackoverflow.com/questions/8132399/how-to-printf-uint64-t-fails-with-spurious-trailing-in-format */
|
/* https://stackoverflow.com/questions/8132399/how-to-printf-uint64-t-fails-with-spurious-trailing-in-format */
|
||||||
/* https://github.com/libretro/RetroArch/issues/6009 */
|
/* https://github.com/libretro/RetroArch/issues/6009 */
|
||||||
#define __STDC_FORMAT_MACROS
|
#ifndef __STDC_FORMAT_MACROS
|
||||||
|
#define __STDC_FORMAT_MACROS 1
|
||||||
|
#endif
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#endif
|
#endif
|
||||||
#ifndef PRId64
|
#ifndef PRId64
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ void memstream_set_buffer(uint8_t *buffer, uint64_t size);
|
|||||||
|
|
||||||
uint64_t memstream_get_last_size(void);
|
uint64_t memstream_get_last_size(void);
|
||||||
|
|
||||||
|
uint64_t memstream_get_ptr(memstream_t *stream);
|
||||||
|
|
||||||
RETRO_END_DECLS
|
RETRO_END_DECLS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
151
src/drivers/libretro/libretro-common/include/string/stdstring.h
Normal file
151
src/drivers/libretro/libretro-common/include/string/stdstring.h
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
/* Copyright (C) 2010-2019 The RetroArch team
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
* The following license statement only applies to this file (stdstring.h).
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge,
|
||||||
|
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||||
|
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LIBRETRO_SDK_STDSTRING_H
|
||||||
|
#define __LIBRETRO_SDK_STDSTRING_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <boolean.h>
|
||||||
|
|
||||||
|
#include <retro_common_api.h>
|
||||||
|
#include <retro_inline.h>
|
||||||
|
#include <compat/strl.h>
|
||||||
|
|
||||||
|
RETRO_BEGIN_DECLS
|
||||||
|
|
||||||
|
static INLINE bool string_is_empty(const char *data)
|
||||||
|
{
|
||||||
|
return !data || (*data == '\0');
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE bool string_is_equal(const char *a, const char *b)
|
||||||
|
{
|
||||||
|
return (a && b) ? !strcmp(a, b) : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define STRLEN_CONST(x) ((sizeof((x))-1))
|
||||||
|
|
||||||
|
#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)
|
||||||
|
|
||||||
|
static INLINE bool string_is_equal_case_insensitive(const char *a,
|
||||||
|
const char *b)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
const unsigned char *p1 = (const unsigned char*)a;
|
||||||
|
const unsigned char *p2 = (const unsigned char*)b;
|
||||||
|
|
||||||
|
if (!a || !b)
|
||||||
|
return false;
|
||||||
|
if (p1 == p2)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
while ((result = tolower (*p1) - tolower (*p2++)) == 0)
|
||||||
|
if (*p1++ == '\0')
|
||||||
|
break;
|
||||||
|
|
||||||
|
return (result == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static INLINE bool string_is_equal_noncase(const char *a, const char *b)
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
const unsigned char *p1 = (const unsigned char*)a;
|
||||||
|
const unsigned char *p2 = (const unsigned char*)b;
|
||||||
|
|
||||||
|
if (!a || !b)
|
||||||
|
return false;
|
||||||
|
if (p1 == p2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
while ((result = tolower (*p1) - tolower (*p2++)) == 0)
|
||||||
|
if (*p1++ == '\0')
|
||||||
|
break;
|
||||||
|
|
||||||
|
return (result == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *string_to_upper(char *s);
|
||||||
|
|
||||||
|
char *string_to_lower(char *s);
|
||||||
|
|
||||||
|
char *string_ucwords(char *s);
|
||||||
|
|
||||||
|
char *string_replace_substring(const char *in, const char *pattern,
|
||||||
|
const char *by);
|
||||||
|
|
||||||
|
/* Remove leading whitespaces */
|
||||||
|
char *string_trim_whitespace_left(char *const s);
|
||||||
|
|
||||||
|
/* Remove trailing whitespaces */
|
||||||
|
char *string_trim_whitespace_right(char *const 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);
|
||||||
|
|
||||||
|
/* Splits string into tokens seperated by 'delim'
|
||||||
|
* > Returned token string must be free()'d
|
||||||
|
* > Returns NULL if token is not found
|
||||||
|
* > After each call, 'str' is set to the position after the
|
||||||
|
* last found token
|
||||||
|
* > Tokens *include* empty strings
|
||||||
|
* Usage example:
|
||||||
|
* char *str = "1,2,3,4,5,6,7,,,10,";
|
||||||
|
* char **str_ptr = &str;
|
||||||
|
* char *token = NULL;
|
||||||
|
* while((token = string_tokenize(str_ptr, ",")))
|
||||||
|
* {
|
||||||
|
* printf("%s\n", token);
|
||||||
|
* free(token);
|
||||||
|
* token = NULL;
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
char* string_tokenize(char **str, const char *delim);
|
||||||
|
|
||||||
|
/* Removes every instance of character 'c' from 'str' */
|
||||||
|
void string_remove_all_chars(char *str, char c);
|
||||||
|
|
||||||
|
/* Replaces every instance of character 'find' in 'str'
|
||||||
|
* with character 'replace' */
|
||||||
|
void string_replace_all_chars(char *str, char find, char replace);
|
||||||
|
|
||||||
|
/* Converts string to unsigned integer.
|
||||||
|
* Returns 0 if string is invalid */
|
||||||
|
unsigned string_to_unsigned(const char *str);
|
||||||
|
|
||||||
|
/* Converts hexadecimal string to unsigned integer.
|
||||||
|
* Handles optional leading '0x'.
|
||||||
|
* Returns 0 if string is invalid */
|
||||||
|
unsigned string_hex_to_unsigned(const char *str);
|
||||||
|
|
||||||
|
RETRO_END_DECLS
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -71,7 +71,7 @@ static void memstream_init(memstream_t *stream,
|
|||||||
|
|
||||||
memstream_t *memstream_open(unsigned writing)
|
memstream_t *memstream_open(unsigned writing)
|
||||||
{
|
{
|
||||||
memstream_t *stream;
|
memstream_t *stream;
|
||||||
if (!g_buffer || !g_size)
|
if (!g_buffer || !g_size)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -92,6 +92,11 @@ void memstream_close(memstream_t *stream)
|
|||||||
free(stream);
|
free(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t memstream_get_ptr(memstream_t *stream)
|
||||||
|
{
|
||||||
|
return stream->ptr;
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t memstream_read(memstream_t *stream, void *data, uint64_t bytes)
|
uint64_t memstream_read(memstream_t *stream, void *data, uint64_t bytes)
|
||||||
{
|
{
|
||||||
uint64_t avail = 0;
|
uint64_t avail = 0;
|
||||||
|
|||||||
384
src/drivers/libretro/libretro-common/string/stdstring.c
Normal file
384
src/drivers/libretro/libretro-common/string/stdstring.c
Normal file
@@ -0,0 +1,384 @@
|
|||||||
|
/* Copyright (C) 2010-2018 The RetroArch team
|
||||||
|
*
|
||||||
|
* ---------------------------------------------------------------------------------------
|
||||||
|
* The following license statement only applies to this file (stdstring.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 <ctype.h>
|
||||||
|
|
||||||
|
#include <string/stdstring.h>
|
||||||
|
#include <encodings/utf.h>
|
||||||
|
|
||||||
|
char *string_to_upper(char *s)
|
||||||
|
{
|
||||||
|
char *cs = (char *)s;
|
||||||
|
for ( ; *cs != '\0'; cs++)
|
||||||
|
*cs = toupper((unsigned char)*cs);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *string_to_lower(char *s)
|
||||||
|
{
|
||||||
|
char *cs = (char *)s;
|
||||||
|
for ( ; *cs != '\0'; cs++)
|
||||||
|
*cs = tolower((unsigned char)*cs);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *string_ucwords(char *s)
|
||||||
|
{
|
||||||
|
char *cs = (char *)s;
|
||||||
|
for ( ; *cs != '\0'; cs++)
|
||||||
|
{
|
||||||
|
if (*cs == ' ')
|
||||||
|
*(cs+1) = toupper((unsigned char)*(cs+1));
|
||||||
|
}
|
||||||
|
|
||||||
|
s[0] = toupper((unsigned char)s[0]);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *string_replace_substring(const char *in,
|
||||||
|
const char *pattern, const char *replacement)
|
||||||
|
{
|
||||||
|
size_t numhits, pattern_len, replacement_len, outlen;
|
||||||
|
const char *inat = NULL;
|
||||||
|
const char *inprev = NULL;
|
||||||
|
char *out = NULL;
|
||||||
|
char *outat = NULL;
|
||||||
|
|
||||||
|
/* if either pattern or replacement is NULL,
|
||||||
|
* duplicate in and let caller handle it. */
|
||||||
|
if (!pattern || !replacement)
|
||||||
|
return strdup(in);
|
||||||
|
|
||||||
|
pattern_len = strlen(pattern);
|
||||||
|
replacement_len = strlen(replacement);
|
||||||
|
numhits = 0;
|
||||||
|
inat = in;
|
||||||
|
|
||||||
|
while ((inat = strstr(inat, pattern)))
|
||||||
|
{
|
||||||
|
inat += pattern_len;
|
||||||
|
numhits++;
|
||||||
|
}
|
||||||
|
|
||||||
|
outlen = strlen(in) - pattern_len*numhits + replacement_len*numhits;
|
||||||
|
out = (char *)malloc(outlen+1);
|
||||||
|
|
||||||
|
if (!out)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
outat = out;
|
||||||
|
inat = in;
|
||||||
|
inprev = in;
|
||||||
|
|
||||||
|
while ((inat = strstr(inat, pattern)))
|
||||||
|
{
|
||||||
|
memcpy(outat, inprev, inat-inprev);
|
||||||
|
outat += inat-inprev;
|
||||||
|
memcpy(outat, replacement, replacement_len);
|
||||||
|
outat += replacement_len;
|
||||||
|
inat += pattern_len;
|
||||||
|
inprev = inat;
|
||||||
|
}
|
||||||
|
strcpy(outat, inprev);
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove leading whitespaces */
|
||||||
|
char *string_trim_whitespace_left(char *const s)
|
||||||
|
{
|
||||||
|
if(s && *s)
|
||||||
|
{
|
||||||
|
size_t len = strlen(s);
|
||||||
|
char *current = s;
|
||||||
|
|
||||||
|
while(*current && isspace((unsigned char)*current))
|
||||||
|
{
|
||||||
|
++current;
|
||||||
|
--len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(s != current)
|
||||||
|
memmove(s, current, len + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove trailing whitespaces */
|
||||||
|
char *string_trim_whitespace_right(char *const s)
|
||||||
|
{
|
||||||
|
if(s && *s)
|
||||||
|
{
|
||||||
|
size_t len = strlen(s);
|
||||||
|
char *current = s + len - 1;
|
||||||
|
|
||||||
|
while(current != s && isspace((unsigned char)*current))
|
||||||
|
{
|
||||||
|
--current;
|
||||||
|
--len;
|
||||||
|
}
|
||||||
|
|
||||||
|
current[isspace((unsigned char)*current) ? 0 : 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove leading and trailing whitespaces */
|
||||||
|
char *string_trim_whitespace(char *const s)
|
||||||
|
{
|
||||||
|
string_trim_whitespace_right(s); /* order matters */
|
||||||
|
string_trim_whitespace_left(s);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *word_wrap(char* buffer, const char *string, int line_width, bool unicode, unsigned max_lines)
|
||||||
|
{
|
||||||
|
unsigned i = 0;
|
||||||
|
unsigned len = (unsigned)strlen(string);
|
||||||
|
unsigned lines = 1;
|
||||||
|
|
||||||
|
while (i < len)
|
||||||
|
{
|
||||||
|
unsigned counter;
|
||||||
|
int pos = (int)(&buffer[i] - buffer);
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
/* check if end of string reached */
|
||||||
|
if (i == len)
|
||||||
|
{
|
||||||
|
buffer[i] = 0;
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
character = utf8skip(&string[i], 1);
|
||||||
|
char_len = (unsigned)(character - &string[i]);
|
||||||
|
|
||||||
|
if (!unicode)
|
||||||
|
counter += char_len - 1;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
buffer[i] = string[i];
|
||||||
|
char_len--;
|
||||||
|
i++;
|
||||||
|
} while(char_len);
|
||||||
|
|
||||||
|
/* check for newlines embedded in the original input
|
||||||
|
* and reset the index */
|
||||||
|
if (buffer[j] == '\n')
|
||||||
|
{
|
||||||
|
lines++;
|
||||||
|
counter = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for whitespace */
|
||||||
|
if (string[i] == ' ')
|
||||||
|
{
|
||||||
|
if ((max_lines == 0 || lines < max_lines))
|
||||||
|
{
|
||||||
|
buffer[i] = '\n';
|
||||||
|
i++;
|
||||||
|
lines++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
|
||||||
|
/* check for nearest whitespace back in string */
|
||||||
|
for (k = i; k > 0; k--)
|
||||||
|
{
|
||||||
|
if (string[k] != ' ' || (max_lines != 0 && lines >= max_lines))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
buffer[k] = '\n';
|
||||||
|
/* set string index back to character after this one */
|
||||||
|
i = k + 1;
|
||||||
|
lines++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (&buffer[i] - buffer == pos)
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer[i] = 0;
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Splits string into tokens seperated by 'delim'
|
||||||
|
* > Returned token string must be free()'d
|
||||||
|
* > Returns NULL if token is not found
|
||||||
|
* > After each call, 'str' is set to the position after the
|
||||||
|
* last found token
|
||||||
|
* > Tokens *include* empty strings
|
||||||
|
* Usage example:
|
||||||
|
* char *str = "1,2,3,4,5,6,7,,,10,";
|
||||||
|
* char **str_ptr = &str;
|
||||||
|
* char *token = NULL;
|
||||||
|
* while((token = string_tokenize(str_ptr, ",")))
|
||||||
|
* {
|
||||||
|
* printf("%s\n", token);
|
||||||
|
* free(token);
|
||||||
|
* token = NULL;
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
char* string_tokenize(char **str, const char *delim)
|
||||||
|
{
|
||||||
|
/* Taken from https://codereview.stackexchange.com/questions/216956/strtok-function-thread-safe-supports-empty-tokens-doesnt-change-string# */
|
||||||
|
char *str_ptr = NULL;
|
||||||
|
char *delim_ptr = NULL;
|
||||||
|
char *token = NULL;
|
||||||
|
size_t token_len = 0;
|
||||||
|
|
||||||
|
/* Sanity checks */
|
||||||
|
if (!str || string_is_empty(delim))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
str_ptr = *str;
|
||||||
|
|
||||||
|
/* Note: we don't check string_is_empty() here,
|
||||||
|
* empty strings are valid */
|
||||||
|
if (!str_ptr)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Search for delimiter */
|
||||||
|
delim_ptr = strstr(str_ptr, delim);
|
||||||
|
|
||||||
|
if (delim_ptr)
|
||||||
|
token_len = delim_ptr - str_ptr;
|
||||||
|
else
|
||||||
|
token_len = strlen(str_ptr);
|
||||||
|
|
||||||
|
/* Allocate token string */
|
||||||
|
token = (char *)malloc((token_len + 1) * sizeof(char));
|
||||||
|
|
||||||
|
if (!token)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Copy token */
|
||||||
|
strlcpy(token, str_ptr, (token_len + 1) * sizeof(char));
|
||||||
|
token[token_len] = '\0';
|
||||||
|
|
||||||
|
/* Update input string pointer */
|
||||||
|
*str = delim_ptr ? delim_ptr + strlen(delim) : NULL;
|
||||||
|
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Removes every instance of character 'c' from 'str' */
|
||||||
|
void string_remove_all_chars(char *str, char c)
|
||||||
|
{
|
||||||
|
char *read_ptr = NULL;
|
||||||
|
char *write_ptr = NULL;
|
||||||
|
|
||||||
|
if (string_is_empty(str))
|
||||||
|
return;
|
||||||
|
|
||||||
|
read_ptr = str;
|
||||||
|
write_ptr = str;
|
||||||
|
|
||||||
|
while (*read_ptr != '\0')
|
||||||
|
{
|
||||||
|
*write_ptr = *read_ptr++;
|
||||||
|
write_ptr += (*write_ptr != c) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*write_ptr = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Replaces every instance of character 'find' in 'str'
|
||||||
|
* with character 'replace' */
|
||||||
|
void string_replace_all_chars(char *str, char find, char replace)
|
||||||
|
{
|
||||||
|
char *str_ptr = str;
|
||||||
|
|
||||||
|
if (string_is_empty(str))
|
||||||
|
return;
|
||||||
|
|
||||||
|
while((str_ptr = strchr(str_ptr, find)) != NULL)
|
||||||
|
*str_ptr++ = replace;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Converts string to unsigned integer.
|
||||||
|
* Returns 0 if string is invalid */
|
||||||
|
unsigned string_to_unsigned(const char *str)
|
||||||
|
{
|
||||||
|
const char *ptr = NULL;
|
||||||
|
|
||||||
|
if (string_is_empty(str))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (ptr = str; *ptr != '\0'; ptr++)
|
||||||
|
{
|
||||||
|
if (!isdigit(*ptr))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (unsigned)strtoul(str, NULL, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Converts hexadecimal string to unsigned integer.
|
||||||
|
* Handles optional leading '0x'.
|
||||||
|
* Returns 0 if string is invalid */
|
||||||
|
unsigned string_hex_to_unsigned(const char *str)
|
||||||
|
{
|
||||||
|
const char *hex_str = str;
|
||||||
|
const char *ptr = NULL;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (string_is_empty(str))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Remove leading '0x', if required */
|
||||||
|
len = strlen(str);
|
||||||
|
|
||||||
|
if (len >= 2)
|
||||||
|
if ((str[0] == '0') &&
|
||||||
|
((str[1] == 'x') || (str[1] == 'X')))
|
||||||
|
hex_str = str + 2;
|
||||||
|
|
||||||
|
if (string_is_empty(hex_str))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Check for valid characters */
|
||||||
|
for (ptr = hex_str; *ptr != '\0'; ptr++)
|
||||||
|
{
|
||||||
|
if (!isxdigit(*ptr))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (unsigned)strtoul(hex_str, NULL, 16);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user