Skip to content

Commit

Permalink
support wtf-8
Browse files Browse the repository at this point in the history
  • Loading branch information
actboy168 committed Apr 10, 2024
1 parent 69e1eec commit 8bae05c
Show file tree
Hide file tree
Showing 15 changed files with 301 additions and 89 deletions.
131 changes: 75 additions & 56 deletions 3rd/lua/utf8_crt.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include <Windows.h>
#include <assert.h>
#include <bee/platform/win/wtf8_c.h>
#include <io.h>
#include <malloc.h>

Expand All @@ -19,50 +20,58 @@
# error Cannot define thread_local
#endif

wchar_t* u2w(const char* str) {
int len = 0;
int out_len = 0;
wchar_t* buf = NULL;
struct u2w_result {
wchar_t* wstr;
size_t wlen;
};

static struct u2w_result u2w_r(const char* str, size_t len) {
struct u2w_result res = { NULL, 0 };
if (!str) {
return NULL;
}
len = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
if (!len) {
return NULL;
return res;
}
buf = (wchar_t*)calloc(len, sizeof(wchar_t));
if (!buf) {
return NULL;
size_t wlen = wtf8_to_utf16_length(str, len);
if (wlen == (size_t)-1) {
return res;
}
out_len = MultiByteToWideChar(CP_UTF8, 0, str, -1, buf, len);
if (out_len < 0) {
free(buf);
return NULL;
res.wstr = (wchar_t*)calloc(wlen + 1, sizeof(wchar_t));
if (!res.wstr) {
return res;
}
return buf;
res.wlen = wlen;
wtf8_to_utf16(str, len, res.wstr, res.wlen);
return res;
}

char* w2u(const wchar_t* str) {
int len = 0;
int out_len = 0;
char* buf = NULL;
wchar_t* u2w(const char* str) {
if (!str) {
return NULL;
}
len = WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL);
if (!len) {
size_t len = strlen(str); // TODO
size_t wlen = wtf8_to_utf16_length(str, len);
if (wlen == (size_t)-1) {
return NULL;
}
wchar_t* wresult = (wchar_t*)calloc(wlen + 1, sizeof(wchar_t));
if (!wresult) {
return NULL;
}
buf = (char*)calloc(len, sizeof(char));
if (!buf) {
wtf8_to_utf16(str, len, wresult, wlen);
return wresult;
}

char* w2u(const wchar_t* wstr) {
if (!wstr) {
return NULL;
}
out_len = WideCharToMultiByte(CP_UTF8, 0, str, -1, buf, len, NULL, NULL);
if (out_len < 0) {
free(buf);
size_t wlen = wcslen(wstr); // TODO
size_t len = wtf8_from_utf16_length(wstr, wlen);
char* result = (char*)calloc(len + 1, sizeof(char));
if (!result) {
return NULL;
}
return buf;
wtf8_from_utf16(wstr, wlen, result);
return result;
}

FILE* __cdecl utf8_fopen(const char* filename, const char* mode) {
Expand Down Expand Up @@ -140,10 +149,8 @@ char* __cdecl utf8_tmpnam(char* buffer) {
if (!_wtmpnam(tmp)) {
return NULL;
}
unsigned long ret = WideCharToMultiByte(CP_UTF8, 0, tmp, -1, buffer, L_tmpnam, NULL, NULL);
if (ret == 0) {
return NULL;
}
size_t wlen = wcslen(tmp);
wtf8_from_utf16(tmp, wlen, buffer);
return buffer;
}

Expand All @@ -160,10 +167,20 @@ unsigned long __stdcall utf8_GetModuleFileNameA(void* module, char* filename, un
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return 0;
}
unsigned long tmplen = GetModuleFileNameW(module, tmp, size);
unsigned long ret = WideCharToMultiByte(CP_UTF8, 0, tmp, tmplen + 1, filename, size, NULL, NULL);
DWORD tmplen = GetModuleFileNameW(module, tmp, size);
if (tmplen == 0) {
free(tmp);
return 0;
}
size_t len = wtf8_from_utf16_length(tmp, tmplen);
if (len > size) {
free(tmp);
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return 0;
}
wtf8_from_utf16(tmp, tmplen, filename);
free(tmp);
return ret - 1;
return (unsigned long)len;
}

unsigned long __stdcall utf8_FormatMessageA(
Expand All @@ -180,14 +197,20 @@ unsigned long __stdcall utf8_FormatMessageA(
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return 0;
}
int res = FormatMessageW(dwFlags, lpSource, dwMessageId, dwLanguageId, tmp, nSize, Arguments);
if (!res) {
DWORD tmplen = FormatMessageW(dwFlags, lpSource, dwMessageId, dwLanguageId, tmp, nSize, Arguments);
if (tmplen == 0) {
free(tmp);
return res;
return 0;
}
size_t len = wtf8_from_utf16_length(tmp, tmplen);
if (len > nSize) {
free(tmp);
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return 0;
}
int ret = WideCharToMultiByte(CP_UTF8, 0, tmp, -1, lpBuffer, nSize, NULL, NULL);
wtf8_from_utf16(tmp, tmplen, lpBuffer);
free(tmp);
return ret;
return (unsigned long)len;
}

static void ConsoleWrite(FILE* stream, const char* s, int l) {
Expand All @@ -196,21 +219,17 @@ static void ConsoleWrite(FILE* stream, const char* s, int l) {
fwrite(s, sizeof(char), l, stream);
return;
}
int wsz = MultiByteToWideChar(CP_UTF8, 0, s, l, NULL, 0);
if (wsz > 0) {
wchar_t* wmsg = (wchar_t*)calloc(wsz, sizeof(wchar_t));
if (wmsg) {
wsz = MultiByteToWideChar(CP_UTF8, 0, s, l, wmsg, wsz);
if (wsz > 0) {
if (WriteConsoleW(handle, wmsg, wsz, NULL, NULL)) {
free(wmsg);
return;
}
}
free(wmsg);
}
}
fwrite(s, sizeof(char), l, stream);
struct u2w_result r = u2w_r(s, l);
if (!r.wstr) {
fwrite(s, sizeof(char), l, stream);
return;
}
if (!WriteConsoleW(handle, r.wstr, (DWORD)r.wlen, NULL, NULL)) {
free(r.wstr);
fwrite(s, sizeof(char), l, stream);
return;
}
free(r.wstr);
}

void utf8_ConsoleWrite(const char* s, int l) {
Expand Down
4 changes: 2 additions & 2 deletions bee/error.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

#if defined(_WIN32)
# include <Windows.h>
# include <bee/platform/win/unicode.h>
# include <bee/platform/win/wtf8.h>
#else
# include <errno.h>
#endif
Expand Down Expand Up @@ -47,7 +47,7 @@ namespace bee {
return "Windows";
}
std::string message(int error_code) const override {
return win::w2u(error_message(error_code));
return wtf8::w2u(error_message(error_code));
}
std::error_condition default_error_condition(int error_code) const noexcept override {
const std::error_condition cond = std::system_category().default_error_condition(error_code);
Expand Down
6 changes: 3 additions & 3 deletions bee/filewatch/filewatch_win.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#include <bee/error.h>
#include <bee/filewatch/filewatch.h>
#include <bee/nonstd/unreachable.h>
#include <bee/platform/win/unicode.h>
#include <bee/platform/win/wtf8.h>

#include <array>
#include <cassert>
Expand Down Expand Up @@ -189,13 +189,13 @@ namespace bee::filewatch {
path = task.path() + path;
switch (fni.Action) {
case FILE_ACTION_MODIFIED:
m_notify.emplace(notify::flag::modify, win::w2u(path));
m_notify.emplace(notify::flag::modify, wtf8::w2u(path));
break;
case FILE_ACTION_ADDED:
case FILE_ACTION_REMOVED:
case FILE_ACTION_RENAMED_OLD_NAME:
case FILE_ACTION_RENAMED_NEW_NAME:
m_notify.emplace(notify::flag::rename, win::w2u(path));
m_notify.emplace(notify::flag::rename, wtf8::w2u(path));
break;
default:
std::unreachable();
Expand Down
6 changes: 3 additions & 3 deletions bee/net/socket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
# include <winsock2.h>
// clang-format on
# include <bee/nonstd/charconv.h>
# include <bee/platform/win/unicode.h>
# include <bee/platform/win/unlink.h>
# include <bee/platform/win/wtf8.h>
# include <bee/utility/dynarray.h>
# include <mstcpip.h>
# include <mswsock.h>
Expand Down Expand Up @@ -43,7 +43,7 @@ namespace bee::net::socket {
static_assert(sizeof(SOCKET) == sizeof(fd_t));

# if defined(_MSC_VER)
# define FILENAME(n) win::u2w(n)
# define FILENAME(n) wtf8::u2w(n)
# else
# define FILENAME(n) (n)
# endif
Expand Down Expand Up @@ -556,7 +556,7 @@ namespace bee::net::socket {
return false;
}
#if defined(_WIN32)
return win::unlink(win::u2w(path).c_str());
return win::unlink(wtf8::u2w(path).c_str());
#else
return 0 == ::unlink(path.c_str());
#endif
Expand Down
31 changes: 31 additions & 0 deletions bee/platform/win/wtf8.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#pragma once

extern "C" {
#include <bee/platform/win/wtf8_c.h>
}
#include <bee/utility/zstring_view.h>

namespace bee::wtf8 {
inline std::wstring u2w(zstring_view str) noexcept {
if (str.empty()) {
return L"";
}
size_t wlen = wtf8_to_utf16_length(str.data(), str.size());
if (wlen == (size_t)-1) {
return L"";
}
std::wstring wresult(wlen, L'\0');
wtf8_to_utf16(str.data(), str.size(), wresult.data(), wlen);
return wresult;
}

inline std::string w2u(wzstring_view wstr) noexcept {
if (wstr.empty()) {
return "";
}
size_t len = wtf8_from_utf16_length(wstr.data(), wstr.size());
std::string result(len, '\0');
wtf8_from_utf16(wstr.data(), wstr.size(), result.data());
return result;
}
}
Loading

0 comments on commit 8bae05c

Please sign in to comment.