core: more std::[w]string conversions in windows.cpp

No free()in necessary means less convoluted control flow.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2023-04-29 15:09:20 +02:00 committed by bstoeger
parent a3f540fe34
commit 81cd91f78b

View file

@ -27,7 +27,6 @@
*/ */
static std::string utf16_to_utf8_fl(const std::wstring &utf16, const char *file, int line) static std::string utf16_to_utf8_fl(const std::wstring &utf16, const char *file, int line)
{ {
assert(utf16 != NULL);
assert(file != NULL); assert(file != NULL);
assert(line); assert(line);
/* estimate buffer size */ /* estimate buffer size */
@ -45,6 +44,24 @@ static std::string utf16_to_utf8_fl(const std::wstring &utf16, const char *file,
return std::string(); return std::string();
} }
/* this function converts a utf-8 string to win32's utf-16 2 byte string.
*/
static std::wstring utf8_to_utf16_fl(const char *utf8, const char *file, int line)
{
assert(file != NULL);
assert(line);
/* estimate buffer size */
const int sz = strlen(utf8) + 1;
std::wstring utf16(sz, ' '); // Note: includes the terminating '\0', just in case.
int actual_size = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, &utf16[0], sz);
if (actual_size) {
utf16.resize(actual_size - 1); // Chop off final '\0' character
return utf16;
}
fprintf(stderr, "%s:%d: cannot convert string\n", file, line);
return std::wstring();
}
#define utf16_to_utf8(s) utf16_to_utf8_fl(s, __FILE__, __LINE__) #define utf16_to_utf8(s) utf16_to_utf8_fl(s, __FILE__, __LINE__)
/* this function returns the Win32 Roaming path for the current user as UTF-8. /* this function returns the Win32 Roaming path for the current user as UTF-8.
@ -105,28 +122,6 @@ bool subsurface_ignore_font(const char *font)
return false; return false;
} }
/* this function converts a utf-8 string to win32's utf-16 2 byte string.
* the caller function should manage the allocated memory.
*/
static wchar_t *utf8_to_utf16_fl(const char *utf8, const char *file, int line)
{
assert(utf8 != NULL);
assert(file != NULL);
assert(line);
/* estimate buffer size */
const int sz = strlen(utf8) + 1;
wchar_t *utf16 = (wchar_t *)malloc(sizeof(wchar_t) * sz);
if (!utf16) {
fprintf(stderr, "%s:%d: cannot allocate buffer of size: %d\n", file, line, sz);
return NULL;
}
if (MultiByteToWideChar(CP_UTF8, 0, utf8, -1, utf16, sz))
return utf16;
fprintf(stderr, "%s:%d: cannot convert string\n", file, line);
free((void *)utf16);
return NULL;
}
#define utf8_to_utf16(s) utf8_to_utf16_fl(s, __FILE__, __LINE__) #define utf8_to_utf16(s) utf8_to_utf16_fl(s, __FILE__, __LINE__)
/* '\' not included at the end. /* '\' not included at the end.
@ -236,18 +231,15 @@ int enumerate_devices(device_callback_t callback, void *userdata, unsigned int t
*/ */
int subsurface_rename(const char *path, const char *newpath) int subsurface_rename(const char *path, const char *newpath)
{ {
int ret = -1;
if (!path || !newpath) if (!path || !newpath)
return ret; return -1;
wchar_t *wpath = utf8_to_utf16(path); std::wstring wpath = utf8_to_utf16(path);
wchar_t *wnewpath = utf8_to_utf16(newpath); std::wstring wnewpath = utf8_to_utf16(newpath);
if (wpath && wnewpath) if (!wpath.empty() && !wnewpath.empty())
ret = _wrename(wpath, wnewpath); return _wrename(wpath.c_str(), wnewpath.c_str());
free((void *)wpath); return -1;
free((void *)wnewpath);
return ret;
} }
// if the QDir based rename fails, we try this one // if the QDir based rename fails, we try this one
@ -296,69 +288,58 @@ int subsurface_dir_rename(const char *path, const char *newpath)
int subsurface_open(const char *path, int oflags, mode_t mode) int subsurface_open(const char *path, int oflags, mode_t mode)
{ {
int ret = -1;
if (!path) if (!path)
return ret; return -1;
wchar_t *wpath = utf8_to_utf16(path); std::wstring wpath = utf8_to_utf16(path);
if (wpath) if (!wpath.empty())
ret = _wopen(wpath, oflags, mode); return _wopen(wpath.c_str(), oflags, mode);
free((void *)wpath); return -1;
return ret;
} }
FILE *subsurface_fopen(const char *path, const char *mode) FILE *subsurface_fopen(const char *path, const char *mode)
{ {
FILE *ret = NULL;
if (!path) if (!path)
return ret; return NULL;
wchar_t *wpath = utf8_to_utf16(path); std::wstring wpath = utf8_to_utf16(path);
if (wpath) { if (!wpath.empty()) {
const int len = strlen(mode); const int len = strlen(mode);
wchar_t wmode[len + 1]; std::wstring wmode(len, ' ');
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
wmode[i] = (wchar_t)mode[i]; wmode[i] = (wchar_t)mode[i];
wmode[len] = 0; return _wfopen(wpath.c_str(), wmode.c_str());
ret = _wfopen(wpath, wmode);
} }
free((void *)wpath); return NULL;
return ret;
} }
/* here we return a void pointer instead of _WDIR or DIR pointer */ /* here we return a void pointer instead of _WDIR or DIR pointer */
void *subsurface_opendir(const char *path) void *subsurface_opendir(const char *path)
{ {
_WDIR *ret = NULL;
if (!path) if (!path)
return ret; return NULL;
wchar_t *wpath = utf8_to_utf16(path); std::wstring wpath = utf8_to_utf16(path);
if (wpath) if (!wpath.empty())
ret = _wopendir(wpath); return (void *)_wopendir(wpath.c_str());
free((void *)wpath); return NULL;
return (void *)ret;
} }
int subsurface_access(const char *path, int mode) int subsurface_access(const char *path, int mode)
{ {
int ret = -1;
if (!path) if (!path)
return ret; return -1;
wchar_t *wpath = utf8_to_utf16(path); std::wstring wpath = utf8_to_utf16(path);
if (wpath) if (!wpath.empty())
ret = _waccess(wpath, mode); return _waccess(wpath.c_str(), mode);
free((void *)wpath); return -1;
return ret;
} }
int subsurface_stat(const char* path, struct stat* buf) int subsurface_stat(const char* path, struct stat* buf)
{ {
int ret = -1;
if (!path) if (!path)
return ret; return -1;
wchar_t *wpath = utf8_to_utf16(path); std::wstring wpath = utf8_to_utf16(path);
if (wpath) if (!wpath.empty())
ret = wstat(wpath, buf); return wstat(wpath.c_str(), buf);
free((void *)wpath); return -1;
return ret;
} }
#ifndef O_BINARY #ifndef O_BINARY