obs-studio/libobs/util/platform.c

306 lines
6.0 KiB
C

/******************************************************************************
Copyright (c) 2013 by Hugh Bailey <obs.jim@gmail.com>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
******************************************************************************/
#include <errno.h>
#include <stdlib.h>
#include "c99defs.h"
#include "platform.h"
#include "bmem.h"
#include "utf8.h"
#include "dstr.h"
FILE *os_wfopen(const wchar_t *path, const char *mode)
{
FILE *file;
#ifdef _MSC_VER
wchar_t *wcs_mode;
os_utf8_to_wcs(mode, 0, &wcs_mode);
file = _wfopen(path, wcs_mode);
bfree(wcs_mode);
#else
char *mbs_path;
os_wcs_to_utf8(path, 0, &mbs_path);
file = fopen(mbs_path, mode);
bfree(mbs_path);
#endif
return file;
}
FILE *os_fopen(const char *path, const char *mode)
{
#ifdef _WIN32
wchar_t *wpath = NULL;
FILE *file = NULL;
os_utf8_to_wcs(path, 0, &wpath);
file = os_wfopen(wpath, mode);
bfree(wpath);
return file;
#else
return fopen(path, mode);
#endif
}
off_t os_fgetsize(FILE *file)
{
off_t cur_offset = ftello(file);
off_t size;
int errval = 0;
if (fseeko(file, 0, SEEK_END) == -1)
return -1;
size = ftello(file);
if (size == -1)
errval = errno;
if (fseeko(file, cur_offset, SEEK_SET) != 0 && errval != 0)
errno = errval;
return size;
}
size_t os_fread_mbs(FILE *file, char **pstr)
{
size_t size = 0;
size_t len = 0;
fseeko(file, 0, SEEK_END);
size = (size_t)ftello(file);
if (size > 0) {
char *mbstr = bmalloc(size+1);
fseeko(file, 0, SEEK_SET);
fread(mbstr, 1, size, file);
mbstr[size] = 0;
len = os_mbs_to_utf8(mbstr, size, pstr);
bfree(mbstr);
} else {
*pstr = NULL;
}
return len;
}
size_t os_fread_utf8(FILE *file, char **pstr)
{
size_t size = 0;
size_t len = 0;
fseeko(file, 0, SEEK_END);
size = (size_t)ftello(file);
if (size > 0) {
char bom[3];
char *utf8str = bmalloc(size+1);
off_t offset;
/* remove the ghastly BOM if present */
fseeko(file, 0, SEEK_SET);
fread(bom, 1, 3, file);
offset = (astrcmp_n(bom, "\xEF\xBB\xBF", 3) == 0) ? 3 : 0;
fseeko(file, offset, SEEK_SET);
fread(utf8str, 1, size, file);
utf8str[size] = 0;
*pstr = utf8str;
} else {
*pstr = NULL;
}
return len;
}
char *os_quick_read_mbs_file(const char *path)
{
FILE *f = os_fopen(path, "rb");
char *file_string = NULL;
if (!f)
return NULL;
os_fread_mbs(f, &file_string);
fclose(f);
return file_string;
}
char *os_quick_read_utf8_file(const char *path)
{
FILE *f = os_fopen(path, "rb");
char *file_string = NULL;
if (!f)
return NULL;
os_fread_utf8(f, &file_string);
fclose(f);
return file_string;
}
bool os_quick_write_mbs_file(const char *path, const char *str, size_t len)
{
FILE *f = os_fopen(path, "wb");
char *mbs = NULL;
size_t mbs_len = 0;
if (!f)
return false;
mbs_len = os_utf8_to_mbs(str, len, &mbs);
if (mbs_len)
fwrite(mbs, 1, mbs_len, f);
bfree(mbs);
fclose(f);
return true;
}
bool os_quick_write_utf8_file(const char *path, const char *str, size_t len,
bool marker)
{
FILE *f = os_fopen(path, "wb");
if (!f)
return false;
if (marker)
fwrite("\xEF\xBB\xBF", 1, 3, f);
if (len)
fwrite(str, 1, len, f);
fclose(f);
return true;
}
size_t os_mbs_to_wcs(const char *str, size_t len, wchar_t **pstr)
{
size_t out_len = mbstowcs(NULL, str, len);
wchar_t *dst = NULL;
if (len) {
dst = bmalloc((out_len+1) * sizeof(wchar_t));
mbstowcs(dst, str, out_len+1);
dst[out_len] = 0;
}
*pstr = dst;
return out_len;
}
size_t os_utf8_to_wcs(const char *str, size_t len, wchar_t **pstr)
{
size_t in_len = len ? len : strlen(str);
size_t out_len = utf8_to_wchar(str, in_len, NULL, 0, 0);
wchar_t *dst = NULL;
if (out_len) {
dst = bmalloc((out_len+1) * sizeof(wchar_t));
utf8_to_wchar(str, in_len, dst, out_len+1, 0);
dst[out_len] = 0;
}
*pstr = dst;
return out_len;
}
size_t os_wcs_to_mbs(const wchar_t *str, size_t len, char **pstr)
{
size_t out_len = wcstombs(NULL, str, len);
char *dst = NULL;
if (len) {
dst = bmalloc(out_len+1);
wcstombs(dst, str, out_len+1);
dst[out_len] = 0;
}
*pstr = dst;
return out_len;
}
size_t os_wcs_to_utf8(const wchar_t *str, size_t len, char **pstr)
{
size_t in_len = (len != 0) ? len : wcslen(str);
size_t out_len = wchar_to_utf8(str, in_len, NULL, 0, 0);
char *dst = NULL;
if (out_len) {
dst = bmalloc(out_len+1);
wchar_to_utf8(str, in_len, dst, out_len+1, 0);
dst[out_len] = 0;
}
*pstr = dst;
return out_len;
}
size_t os_utf8_to_mbs(const char *str, size_t len, char **pstr)
{
wchar_t *wstr = NULL;
char *dst = NULL;
size_t wlen = os_utf8_to_wcs(str, len, &wstr);
size_t out_len = os_wcs_to_mbs(wstr, wlen, &dst);
bfree(wstr);
*pstr = dst;
return out_len;
}
size_t os_mbs_to_utf8(const char *str, size_t len, char **pstr)
{
wchar_t *wstr = NULL;
char *dst = NULL;
size_t wlen = os_mbs_to_wcs(str, len, &wstr);
size_t out_len = os_wcs_to_utf8(wstr, wlen, &dst);
bfree(wstr);
*pstr = dst;
return out_len;
}
#ifdef _MSC_VER
int fseeko(FILE *stream, off_t offset, int whence)
{
#if _FILE_OFFSET_BITS == 64
return _fseeki64(stream, offset, whence);
#else
return fseek(stream, offset, whence);
#endif /* _FILE_OFFSET_BITS == 64 */
}
off_t ftello(FILE *stream)
{
#if _FILE_OFFSET_BITS == 64
return _ftelli64(stream);
#else
return ftell(stream);
#endif /* _FILE_OFFSET_BITS == 64 */
}
#endif /* _MSC_VER */