Merge pull request #785 from DrLynix/unicode-file-operations-win32
Unicode file functions for Windows
This commit is contained in:
commit
235d364756
@ -18,6 +18,9 @@
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
|
||||
#if defined(LUA_WIN)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
|
||||
#define IO_INPUT 1
|
||||
@ -177,8 +180,29 @@ static int io_tostring (lua_State *L) {
|
||||
static int io_open (lua_State *L) {
|
||||
const char *filename = luaL_checkstring(L, 1);
|
||||
const char *mode = luaL_optstring(L, 2, "r");
|
||||
|
||||
#if defined(LUA_WIN)
|
||||
wchar_t wide_path[4096];
|
||||
if (MultiByteToWideChar(CP_UTF8, 0, filename, -1, wide_path, 4096) == 0)
|
||||
{
|
||||
lua_pushstring(L, "unable to encode path");
|
||||
return lua_error(L);
|
||||
}
|
||||
|
||||
wchar_t wide_mode[64];
|
||||
if (MultiByteToWideChar(CP_UTF8, 0, mode, -1, wide_mode, 64) == 0)
|
||||
{
|
||||
lua_pushstring(L, "unable to encode open mode");
|
||||
return lua_error(L);
|
||||
}
|
||||
#endif
|
||||
|
||||
FILE **pf = newfile(L);
|
||||
#if defined(LUA_WIN)
|
||||
*pf = _wfopen(wide_path, wide_mode);
|
||||
#else
|
||||
*pf = fopen(filename, mode);
|
||||
#endif
|
||||
return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
|
||||
}
|
||||
|
||||
|
51
src/host/os_remove.c
Normal file
51
src/host/os_remove.c
Normal file
@ -0,0 +1,51 @@
|
||||
/**
|
||||
* \file os_rmdir.c
|
||||
* \brief Remove a subdirectory.
|
||||
* \author Copyright (c) 2002-2013 Jason Perkins and the Premake project
|
||||
*/
|
||||
|
||||
#include "premake.h"
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
|
||||
int os_remove(lua_State* L)
|
||||
{
|
||||
const char* filename = luaL_checkstring(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 path");
|
||||
return lua_error(L);
|
||||
}
|
||||
|
||||
if (DeleteFileW(wide_path))
|
||||
{
|
||||
lua_pushboolean(L, 1);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
|
||||
char unicodeErr[512];
|
||||
|
||||
LPWSTR messageBuffer = NULL;
|
||||
if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR) &messageBuffer, 0, NULL) != 0)
|
||||
{
|
||||
if (WideCharToMultiByte(CP_UTF8, 0, messageBuffer, -1, unicodeErr, sizeof(unicodeErr), NULL, NULL) == 0)
|
||||
strcpy(unicodeErr, "failed to translate error message");
|
||||
|
||||
LocalFree(messageBuffer);
|
||||
}
|
||||
else
|
||||
strcpy(unicodeErr, "failed to get error message");
|
||||
|
||||
lua_pushnil(L);
|
||||
lua_pushfstring(L, "%s: %s", filename, unicodeErr);
|
||||
lua_pushinteger(L, err);
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
59
src/host/os_rename.c
Normal file
59
src/host/os_rename.c
Normal file
@ -0,0 +1,59 @@
|
||||
/**
|
||||
* \file os_rmdir.c
|
||||
* \brief Remove a subdirectory.
|
||||
* \author Copyright (c) 2002-2013 Jason Perkins and the Premake project
|
||||
*/
|
||||
|
||||
#include "premake.h"
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
|
||||
int os_rename(lua_State* L)
|
||||
{
|
||||
const char *fromname = luaL_checkstring(L, 1);
|
||||
const char *toname = luaL_checkstring(L, 2);
|
||||
|
||||
wchar_t wide_frompath[PATH_MAX];
|
||||
if (MultiByteToWideChar(CP_UTF8, 0, fromname, -1, wide_frompath, PATH_MAX) == 0)
|
||||
{
|
||||
lua_pushstring(L, "unable to encode source path");
|
||||
return lua_error(L);
|
||||
}
|
||||
|
||||
wchar_t wide_topath[PATH_MAX];
|
||||
if (MultiByteToWideChar(CP_UTF8, 0, toname, -1, wide_topath, PATH_MAX) == 0)
|
||||
{
|
||||
lua_pushstring(L, "unable to encode dest path");
|
||||
return lua_error(L);
|
||||
}
|
||||
|
||||
if (MoveFileExW(wide_frompath, wide_topath, MOVEFILE_COPY_ALLOWED))
|
||||
{
|
||||
lua_pushboolean(L, 1);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD err = GetLastError();
|
||||
|
||||
char unicodeErr[512];
|
||||
|
||||
LPWSTR messageBuffer = NULL;
|
||||
if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR) &messageBuffer, 0, NULL) != 0)
|
||||
{
|
||||
if (WideCharToMultiByte(CP_UTF8, 0, messageBuffer, -1, unicodeErr, sizeof(unicodeErr), NULL, NULL) == 0)
|
||||
strcpy(unicodeErr, "failed to translate error message");
|
||||
|
||||
LocalFree(messageBuffer);
|
||||
}
|
||||
else
|
||||
strcpy(unicodeErr, "failed to get error message");
|
||||
|
||||
lua_pushnil(L);
|
||||
lua_pushfstring(L, "%s: %s", fromname, unicodeErr);
|
||||
lua_pushinteger(L, err);
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -10,10 +10,24 @@
|
||||
|
||||
int os_stat(lua_State* L)
|
||||
{
|
||||
const char* filename = luaL_checkstring(L, 1);
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
struct _stat64i32 s;
|
||||
|
||||
wchar_t wide_filename[PATH_MAX];
|
||||
if (MultiByteToWideChar(CP_UTF8, 0, filename, -1, wide_filename, PATH_MAX) == 0)
|
||||
{
|
||||
lua_pushstring(L, "unable to encode source path");
|
||||
return lua_error(L);
|
||||
}
|
||||
|
||||
if (_wstat(wide_filename, &s) != 0)
|
||||
#else
|
||||
struct stat s;
|
||||
|
||||
const char* filename = luaL_checkstring(L, 1);
|
||||
if (stat(filename, &s) != 0)
|
||||
#endif
|
||||
{
|
||||
lua_pushnil(L);
|
||||
switch (errno)
|
||||
|
@ -19,12 +19,22 @@
|
||||
|
||||
static int compare_file(const char* content, size_t length, const char* dst)
|
||||
{
|
||||
FILE* file = fopen(dst, "rb");
|
||||
FILE* file;
|
||||
size_t size;
|
||||
size_t read;
|
||||
char buffer[4096];
|
||||
size_t num;
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
wchar_t wide_path[PATH_MAX];
|
||||
if (MultiByteToWideChar(CP_UTF8, 0, dst, -1, wide_path, PATH_MAX) == 0)
|
||||
return FALSE;
|
||||
|
||||
file = _wfopen(wide_path, L"rb");
|
||||
#else
|
||||
file = fopen(dst, "rb");
|
||||
#endif
|
||||
|
||||
if (file == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
@ -81,8 +91,16 @@ int os_writefile_ifnotequal(lua_State* L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
wchar_t wide_path[PATH_MAX];
|
||||
if (MultiByteToWideChar(CP_UTF8, 0, dst, -1, wide_path, PATH_MAX) == 0)
|
||||
return FALSE;
|
||||
|
||||
file = _wfopen(wide_path, L"wb");
|
||||
#else
|
||||
file = fopen(dst, "wb");
|
||||
#endif
|
||||
|
||||
if (file != NULL)
|
||||
{
|
||||
fwrite(content, 1, length, file);
|
||||
|
@ -8,6 +8,11 @@
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
// isspace custom version (visual c++'s one doesn't like utf8 characters)
|
||||
static int is_space(char c)
|
||||
{
|
||||
return (c >= 9 && c <= 13) || c == 32;
|
||||
}
|
||||
|
||||
static void* normalize_substring(const char* str, const char* endPtr, char* writePtr) {
|
||||
const char* const source = str;
|
||||
@ -93,7 +98,7 @@ int path_normalize(lua_State* L)
|
||||
const char* endPtr;
|
||||
|
||||
// skip leading white spaces
|
||||
while (*readPtr && isspace(*readPtr)) {
|
||||
while (*readPtr && is_space(*readPtr)) {
|
||||
++readPtr;
|
||||
}
|
||||
|
||||
@ -106,14 +111,14 @@ int path_normalize(lua_State* L)
|
||||
}
|
||||
|
||||
// find the end of sub path
|
||||
while (*endPtr && !isspace(*endPtr)) {
|
||||
while (*endPtr && !is_space(*endPtr)) {
|
||||
++endPtr;
|
||||
}
|
||||
|
||||
writePtr = normalize_substring(readPtr, endPtr, writePtr);
|
||||
|
||||
// skip any white spaces between sub paths
|
||||
while (*endPtr && isspace(*endPtr)) {
|
||||
while (*endPtr && is_space(*endPtr)) {
|
||||
*(writePtr++) = *(endPtr++);
|
||||
}
|
||||
|
||||
@ -121,7 +126,7 @@ int path_normalize(lua_State* L)
|
||||
}
|
||||
|
||||
// skip any trailing white spaces
|
||||
while (isspace(*(--endPtr))) {
|
||||
while (is_space(*(--endPtr))) {
|
||||
--writePtr;
|
||||
}
|
||||
|
||||
|
@ -74,6 +74,11 @@ static const luaL_Reg os_functions[] = {
|
||||
{ "matchnext", os_matchnext },
|
||||
{ "matchstart", os_matchstart },
|
||||
{ "mkdir", os_mkdir },
|
||||
#if PLATFORM_WINDOWS
|
||||
// utf8 functions for Windows (assuming posix already handle utf8)
|
||||
{"remove", os_remove },
|
||||
{"rename", os_rename },
|
||||
#endif
|
||||
{ "pathsearch", os_pathsearch },
|
||||
{ "realpath", os_realpath },
|
||||
{ "rmdir", os_rmdir },
|
||||
|
@ -120,6 +120,11 @@ int os_matchstart(lua_State* L);
|
||||
int os_mkdir(lua_State* L);
|
||||
int os_pathsearch(lua_State* L);
|
||||
int os_realpath(lua_State* L);
|
||||
#if PLATFORM_WINDOWS
|
||||
// utf8 versions
|
||||
int os_remove(lua_State* L);
|
||||
int os_rename(lua_State* L);
|
||||
#endif
|
||||
int os_rmdir(lua_State* L);
|
||||
int os_stat(lua_State* L);
|
||||
int os_uuid(lua_State* L);
|
||||
|
Loading…
Reference in New Issue
Block a user