From 9c4c998a2b3424c9047acec5186f23d2e4c10db6 Mon Sep 17 00:00:00 2001 From: Lynix Date: Tue, 4 Apr 2017 09:03:29 +0200 Subject: [PATCH] Rework unicode encoding/decoding (Windows) --- src/host/os_chdir.c | 10 ++++++++-- src/host/os_copyfile.c | 18 ++++++++++++++++-- src/host/os_getcwd.c | 6 +++--- src/host/os_isdir.c | 13 +++++++------ src/host/os_isfile.c | 10 ++++++++-- src/host/os_islink.c | 9 +++++++-- src/host/os_match.c | 22 ++++++++++++++++++---- src/host/os_rmdir.c | 10 ++++++++-- src/host/premake.h | 6 ------ src/host/utf8handling.c | 33 --------------------------------- 10 files changed, 75 insertions(+), 62 deletions(-) delete mode 100644 src/host/utf8handling.c diff --git a/src/host/os_chdir.c b/src/host/os_chdir.c index 3b930127..28aa0fcd 100644 --- a/src/host/os_chdir.c +++ b/src/host/os_chdir.c @@ -14,8 +14,14 @@ int do_chdir(lua_State* L, const char* path) (void)(L); /* warning: unused parameter */ #if PLATFORM_WINDOWS - z = SetCurrentDirectoryW(utf8_towide(L, path)); - lua_pop(L, 1); + wchar_t wide_buffer[PATH_MAX]; + if (MultiByteToWideChar(CP_UTF8, 0, path, -1, wide_buffer, PATH_MAX) == 0) + { + lua_pushstring(L, "unable to encode path"); + return lua_error(L); + } + + z = SetCurrentDirectoryW(wide_buffer); #else z = !chdir(path); #endif diff --git a/src/host/os_copyfile.c b/src/host/os_copyfile.c index 434694a7..e15c93dd 100644 --- a/src/host/os_copyfile.c +++ b/src/host/os_copyfile.c @@ -14,8 +14,22 @@ int os_copyfile(lua_State* L) const char* dst = luaL_checkstring(L, 2); #if PLATFORM_WINDOWS - z = CopyFileW(utf8_towide(L, src), utf8_towide(L, dst), FALSE); - lua_pop(L, 2); + wchar_t wide_src[PATH_MAX]; + wchar_t wide_dst[PATH_MAX]; + + if (MultiByteToWideChar(CP_UTF8, 0, src, -1, wide_src, PATH_MAX) == 0) + { + lua_pushstring(L, "unable to encode source path"); + return lua_error(L); + } + + if (MultiByteToWideChar(CP_UTF8, 0, dst, -1, wide_dst, PATH_MAX) == 0) + { + lua_pushstring(L, "unable to encode source path"); + return lua_error(L); + } + + z = CopyFileW(wide_src, wide_dst, FALSE); #else lua_pushfstring(L, "cp \"%s\" \"%s\"", src, dst); z = (system(lua_tostring(L, -1)) == 0); diff --git a/src/host/os_getcwd.c b/src/host/os_getcwd.c index 5cd9bab1..5a3e2931 100644 --- a/src/host/os_getcwd.c +++ b/src/host/os_getcwd.c @@ -24,9 +24,9 @@ int do_getcwd(char* buffer, size_t size) int result; #if PLATFORM_WINDOWS - wchar_t wbuffer[MAX_PATH]; - - result = (GetCurrentDirectoryW(MAX_PATH, wbuffer) != 0); + wchar_t wbuffer[PATH_MAX]; + + result = (GetCurrentDirectoryW(PATH_MAX, wbuffer) != 0); if (result) { WideCharToMultiByte(CP_UTF8, 0, wbuffer, -1, buffer, size, NULL, NULL); diff --git a/src/host/os_isdir.c b/src/host/os_isdir.c index 91cdd6fb..b3e2ccdd 100644 --- a/src/host/os_isdir.c +++ b/src/host/os_isdir.c @@ -18,8 +18,13 @@ int os_isdir(lua_State* L) const char* path = luaL_checkstring(L, 1); #ifdef _WIN32 int attr; - - const wchar_t* wide_path = utf8_towide(L, path); + + wchar_t wide_path[PATH_MAX]; + if (MultiByteToWideChar(CP_UTF8, 0, path, -1, wide_path, PATH_MAX) == 0) + { + lua_pushstring(L, "unable to encode path"); + return lua_error(L); + } #endif /* empty path is equivalent to ".", must be true */ @@ -44,10 +49,6 @@ int os_isdir(lua_State* L) { lua_pushboolean(L, 0); } - -#ifdef _WIN32 - lua_remove(L, -2); /* pop wide string */ -#endif return 1; } diff --git a/src/host/os_isfile.c b/src/host/os_isfile.c index 2c737e1e..2bad6f04 100644 --- a/src/host/os_isfile.c +++ b/src/host/os_isfile.c @@ -21,9 +21,15 @@ int do_isfile(lua_State* L, const char* filename) (void)(L); /* warning: unused parameter */ #if PLATFORM_WINDOWS - DWORD attrib = GetFileAttributesW(utf8_towide(L, filename)); - lua_pop(L, 1); + wchar_t wide_path[PATH_MAX]; + if (MultiByteToWideChar(CP_UTF8, 0, filename, -1, wide_path, PATH_MAX) == 0) + { + lua_pushstring(L, "unable to encode filepath"); + return lua_error(L); + } + + DWORD attrib = GetFileAttributesW(wide_path); if (attrib != INVALID_FILE_ATTRIBUTES) { return (attrib & FILE_ATTRIBUTE_DIRECTORY) == 0; diff --git a/src/host/os_islink.c b/src/host/os_islink.c index 61b845fc..1c2dee91 100644 --- a/src/host/os_islink.c +++ b/src/host/os_islink.c @@ -14,9 +14,14 @@ int os_islink(lua_State* L) #if PLATFORM_WINDOWS { - DWORD attr = GetFileAttributesW(utf8_towide(L, path)); - lua_pop(L, 1); + wchar_t wide_path[PATH_MAX]; + if (MultiByteToWideChar(CP_UTF8, 0, path, -1, wide_path, PATH_MAX) == 0) + { + lua_pushstring(L, "unable to encode path"); + return lua_error(L); + } + DWORD attr = GetFileAttributesW(wide_path); if (attr != INVALID_FILE_ATTRIBUTES) { lua_pushboolean(L, (attr & FILE_ATTRIBUTE_REPARSE_POINT) != 0); return 1; diff --git a/src/host/os_match.c b/src/host/os_match.c index 109d1c1a..2a25df68 100644 --- a/src/host/os_match.c +++ b/src/host/os_match.c @@ -21,11 +21,17 @@ typedef struct struct_MatchInfo int os_matchstart(lua_State* L) { const char* mask = luaL_checkstring(L, 1); + + wchar_t wide_mask[PATH_MAX]; + if (MultiByteToWideChar(CP_UTF8, 0, mask, -1, wide_mask, PATH_MAX) == 0) + { + lua_pushstring(L, "unable to encode mask"); + return lua_error(L); + } + MatchInfo* m = (MatchInfo*)malloc(sizeof(MatchInfo)); - m->handle = FindFirstFileW(utf8_towide(L, mask), &m->entry); - lua_pop(L, 1); - + m->handle = FindFirstFileW(wide_mask, &m->entry); m->is_first = 1; lua_pushlightuserdata(L, m); return 1; @@ -43,7 +49,15 @@ int os_matchdone(lua_State* L) int os_matchname(lua_State* L) { MatchInfo* m = (MatchInfo*)lua_touserdata(L, 1); - utf8_fromwide(L, m->entry.cFileName); + + char filename[PATH_MAX]; + if (WideCharToMultiByte(CP_UTF8, 0, m->entry.cFileName, -1, filename, PATH_MAX, NULL, NULL) == 0) + { + lua_pushstring(L, "unable to decode filename"); + return lua_error(L); + } + + lua_pushstring(L, filename); return 1; } diff --git a/src/host/os_rmdir.c b/src/host/os_rmdir.c index 01e6d1cc..46e65d9d 100644 --- a/src/host/os_rmdir.c +++ b/src/host/os_rmdir.c @@ -14,8 +14,14 @@ int os_rmdir(lua_State* L) const char* path = luaL_checkstring(L, 1); #if PLATFORM_WINDOWS - z = RemoveDirectoryW(utf8_towide(L, path)); - lua_pop(L, 1); + wchar_t wide_path[PATH_MAX]; + if (MultiByteToWideChar(CP_UTF8, 0, path, -1, wide_path, PATH_MAX) == 0) + { + lua_pushstring(L, "unable to encode path"); + return lua_error(L); + } + + z = RemoveDirectoryW(wide_path); #else z = (0 == rmdir(path)); #endif diff --git a/src/host/premake.h b/src/host/premake.h index 4c3b9826..c8bb3f23 100644 --- a/src/host/premake.h +++ b/src/host/premake.h @@ -87,12 +87,6 @@ void do_normalize(lua_State* L, char* buffer, const char* path); int do_pathsearch(lua_State* L, const char* filename, const char* path); void do_translate(char* value, const char sep); -/* Unicode conversion helper functions (required for Windows systems) */ -#ifdef PLATFORM_WINDOWS -const char* utf8_fromwide(lua_State* L, const wchar_t* wstr); -const wchar_t* utf8_towide(lua_State* L, const char* str); -#endif - /* Built-in functions */ int criteria_compile(lua_State* L); int criteria_delete(lua_State* L); diff --git a/src/host/utf8handling.c b/src/host/utf8handling.c deleted file mode 100644 index e9bb9374..00000000 --- a/src/host/utf8handling.c +++ /dev/null @@ -1,33 +0,0 @@ -/** - * \file utf8handking.c - * \brief Handles conversions between Unicode (UTF-8) and system native encoding (wide chars on Windows) - * \author Copyright (c) 2017 Jérôme Leclercq and the Premake project - */ - -#include "premake.h" -#include "stdlib.h" - -#ifdef PLATFORM_WINDOWS -const char* utf8_fromwide(lua_State* L, const wchar_t* wstr) -{ - int size_required = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL); - - char* unicode_str = (char*) malloc(size_required * sizeof(char)); - WideCharToMultiByte(CP_UTF8, 0, wstr, -1, unicode_str, size_required, NULL, NULL); - - lua_pushstring(L, unicode_str); - free(unicode_str); - - return unicode_str; -} - -const wchar_t* utf8_towide(lua_State* L, const char* str) -{ - int size_required = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0); - - wchar_t* wide_string = (wchar_t*) lua_newuserdata(L, size_required * sizeof(wchar_t)); - MultiByteToWideChar(CP_UTF8, 0, str, -1, wide_string, size_required); - - return wide_string; -} -#endif