Better unicode support: use UTF-16 for console input, while piped input still uses UTF-8.
This commit is contained in:
committed by
Pavel Punegov
parent
33ebd40964
commit
1b3504119d
@@ -34,6 +34,7 @@
|
||||
|
||||
#include "Common.h"
|
||||
#include "Porting.h"
|
||||
#include "KAssert.h"
|
||||
|
||||
#if KONAN_WASM || KONAN_ZEPHYR
|
||||
extern "C" RUNTIME_NORETURN void Konan_abort(const char*);
|
||||
@@ -53,6 +54,8 @@ void consoleInit() {
|
||||
// how we perform console IO, if it turns out, that UTF-16 is better output format.
|
||||
::SetConsoleCP(CP_UTF8);
|
||||
::SetConsoleOutputCP(CP_UTF8);
|
||||
// FIXME: should set original CP back during the deinit of the program.
|
||||
// Otherwise, this codepage remains in the console.
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -60,11 +63,6 @@ void consoleWriteUtf8(const void* utf8, uint32_t sizeBytes) {
|
||||
#ifdef KONAN_ANDROID
|
||||
// TODO: use sizeBytes!
|
||||
__android_log_print(ANDROID_LOG_INFO, "Konan_main", "%s", utf8);
|
||||
//#elif KONAN_WINDOWS
|
||||
// // UTF-16 write
|
||||
// void *con = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
// unsigned long num;
|
||||
// ::WriteConsole(con, utf8, sizeBytes, &num, NULL);
|
||||
#else
|
||||
::write(STDOUT_FILENO, utf8, sizeBytes);
|
||||
#endif
|
||||
@@ -74,40 +72,54 @@ void consoleErrorUtf8(const void* utf8, uint32_t sizeBytes) {
|
||||
#ifdef KONAN_ANDROID
|
||||
// TODO: use sizeBytes!
|
||||
__android_log_print(ANDROID_LOG_ERROR, "Konan_main", "%s", utf8);
|
||||
//#elif KONAN_WINDOWS
|
||||
// // UTF-16 write
|
||||
// void *con = GetStdHandle(STD_ERROR_HANDLE);
|
||||
// unsigned long num;
|
||||
// ::WriteConsole(con, utf8, sizeBytes, &num, NULL);
|
||||
#else
|
||||
::write(STDERR_FILENO, utf8, sizeBytes);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if KONAN_WINDOWS
|
||||
int getLastErrorMessage(char* message, uint32_t size) {
|
||||
auto errCode = ::GetLastError();
|
||||
if (errCode) {
|
||||
auto flags = FORMAT_MESSAGE_FROM_SYSTEM;
|
||||
auto errMsgBufSize = size / 4;
|
||||
wchar_t errMsgBuffer[errMsgBufSize];
|
||||
::FormatMessageW(flags, NULL, errCode, 0, errMsgBuffer, errMsgBufSize, NULL);
|
||||
auto errMsgLength = ::WideCharToMultiByte(CP_UTF8, 0, errMsgBuffer, -1, message, size, NULL, NULL);
|
||||
}
|
||||
return errCode;
|
||||
}
|
||||
#endif
|
||||
|
||||
int32_t consoleReadUtf8(void* utf8, uint32_t maxSizeBytes) {
|
||||
#ifdef KONAN_ZEPHYR
|
||||
return 0;
|
||||
#elif KONAN_WINDOWS
|
||||
void *con = ::GetStdHandle(STD_INPUT_HANDLE);
|
||||
unsigned long bufferRead;
|
||||
auto bufferLength = maxSizeBytes / 4;
|
||||
wchar_t buffer[bufferLength];
|
||||
::ReadConsoleW(con, buffer, bufferLength, &bufferRead, NULL);
|
||||
auto length = ::WideCharToMultiByte(CP_UTF8, 0, buffer, bufferRead, (char*) utf8, maxSizeBytes, NULL, NULL);
|
||||
if (!length) {
|
||||
auto errCode = ::GetLastError();
|
||||
if (errCode) {
|
||||
auto flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER;
|
||||
wchar_t *errMsgBuffer;
|
||||
auto errMsgLength = ::FormatMessageW(flags, NULL, errCode, 0, errMsgBuffer, 1024, NULL);
|
||||
char errMsgUtf8[4096];
|
||||
::WideCharToMultiByte(CP_UTF8, 0, errMsgBuffer, errMsgLength, errMsgUtf8,
|
||||
sizeof(errMsgUtf8), NULL, NULL);
|
||||
consoleErrorf("UTF-16 to UTF-8 convertion error %d: %s\n", errCode, errMsgUtf8);
|
||||
::LocalFree(errMsgBuffer);
|
||||
auto length = 0;
|
||||
void *stdInHandle = ::GetStdHandle(STD_INPUT_HANDLE);
|
||||
if (::GetFileType(stdInHandle) == FILE_TYPE_CHAR) {
|
||||
unsigned long bufferRead;
|
||||
// In UTF-16 there are surrogate pairs that a 2 * 16-bit long (4 bytes).
|
||||
auto bufferLength = maxSizeBytes / 4 - 1;
|
||||
wchar_t buffer[bufferLength];
|
||||
if (::ReadConsoleW(stdInHandle, buffer, bufferLength, &bufferRead, NULL)) {
|
||||
length = ::WideCharToMultiByte(CP_UTF8, 0, buffer, bufferRead, (char*) utf8,
|
||||
maxSizeBytes - 1, NULL, NULL);
|
||||
if (!length && KonanNeedDebugInfo) {
|
||||
char msg[512];
|
||||
auto errCode = getLastErrorMessage(msg, sizeof(msg));
|
||||
char buffer[1024];
|
||||
consoleErrorf("UTF-16 to UTF-8 conversion error %d: %s", errCode, msg);
|
||||
}
|
||||
((char*) utf8)[length] = 0;
|
||||
} else if (KonanNeedDebugInfo) {
|
||||
char msg[512];
|
||||
auto errCode = getLastErrorMessage(msg, sizeof(msg));
|
||||
consoleErrorf("Console read failure: %d %s", errCode, msg);
|
||||
}
|
||||
} else {
|
||||
length = ::read(STDIN_FILENO, utf8, maxSizeBytes - 1);
|
||||
}
|
||||
((char*) utf8)[length] = 0;
|
||||
#else
|
||||
auto length = ::read(STDIN_FILENO, utf8, maxSizeBytes - 1);
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user