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 "Common.h"
|
||||||
#include "Porting.h"
|
#include "Porting.h"
|
||||||
|
#include "KAssert.h"
|
||||||
|
|
||||||
#if KONAN_WASM || KONAN_ZEPHYR
|
#if KONAN_WASM || KONAN_ZEPHYR
|
||||||
extern "C" RUNTIME_NORETURN void Konan_abort(const char*);
|
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.
|
// how we perform console IO, if it turns out, that UTF-16 is better output format.
|
||||||
::SetConsoleCP(CP_UTF8);
|
::SetConsoleCP(CP_UTF8);
|
||||||
::SetConsoleOutputCP(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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,11 +63,6 @@ void consoleWriteUtf8(const void* utf8, uint32_t sizeBytes) {
|
|||||||
#ifdef KONAN_ANDROID
|
#ifdef KONAN_ANDROID
|
||||||
// TODO: use sizeBytes!
|
// TODO: use sizeBytes!
|
||||||
__android_log_print(ANDROID_LOG_INFO, "Konan_main", "%s", utf8);
|
__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
|
#else
|
||||||
::write(STDOUT_FILENO, utf8, sizeBytes);
|
::write(STDOUT_FILENO, utf8, sizeBytes);
|
||||||
#endif
|
#endif
|
||||||
@@ -74,40 +72,54 @@ void consoleErrorUtf8(const void* utf8, uint32_t sizeBytes) {
|
|||||||
#ifdef KONAN_ANDROID
|
#ifdef KONAN_ANDROID
|
||||||
// TODO: use sizeBytes!
|
// TODO: use sizeBytes!
|
||||||
__android_log_print(ANDROID_LOG_ERROR, "Konan_main", "%s", utf8);
|
__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
|
#else
|
||||||
::write(STDERR_FILENO, utf8, sizeBytes);
|
::write(STDERR_FILENO, utf8, sizeBytes);
|
||||||
#endif
|
#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) {
|
int32_t consoleReadUtf8(void* utf8, uint32_t maxSizeBytes) {
|
||||||
#ifdef KONAN_ZEPHYR
|
#ifdef KONAN_ZEPHYR
|
||||||
return 0;
|
return 0;
|
||||||
#elif KONAN_WINDOWS
|
#elif KONAN_WINDOWS
|
||||||
void *con = ::GetStdHandle(STD_INPUT_HANDLE);
|
auto length = 0;
|
||||||
unsigned long bufferRead;
|
void *stdInHandle = ::GetStdHandle(STD_INPUT_HANDLE);
|
||||||
auto bufferLength = maxSizeBytes / 4;
|
if (::GetFileType(stdInHandle) == FILE_TYPE_CHAR) {
|
||||||
wchar_t buffer[bufferLength];
|
unsigned long bufferRead;
|
||||||
::ReadConsoleW(con, buffer, bufferLength, &bufferRead, NULL);
|
// In UTF-16 there are surrogate pairs that a 2 * 16-bit long (4 bytes).
|
||||||
auto length = ::WideCharToMultiByte(CP_UTF8, 0, buffer, bufferRead, (char*) utf8, maxSizeBytes, NULL, NULL);
|
auto bufferLength = maxSizeBytes / 4 - 1;
|
||||||
if (!length) {
|
wchar_t buffer[bufferLength];
|
||||||
auto errCode = ::GetLastError();
|
if (::ReadConsoleW(stdInHandle, buffer, bufferLength, &bufferRead, NULL)) {
|
||||||
if (errCode) {
|
length = ::WideCharToMultiByte(CP_UTF8, 0, buffer, bufferRead, (char*) utf8,
|
||||||
auto flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER;
|
maxSizeBytes - 1, NULL, NULL);
|
||||||
wchar_t *errMsgBuffer;
|
if (!length && KonanNeedDebugInfo) {
|
||||||
auto errMsgLength = ::FormatMessageW(flags, NULL, errCode, 0, errMsgBuffer, 1024, NULL);
|
char msg[512];
|
||||||
char errMsgUtf8[4096];
|
auto errCode = getLastErrorMessage(msg, sizeof(msg));
|
||||||
::WideCharToMultiByte(CP_UTF8, 0, errMsgBuffer, errMsgLength, errMsgUtf8,
|
char buffer[1024];
|
||||||
sizeof(errMsgUtf8), NULL, NULL);
|
consoleErrorf("UTF-16 to UTF-8 conversion error %d: %s", errCode, msg);
|
||||||
consoleErrorf("UTF-16 to UTF-8 convertion error %d: %s\n", errCode, errMsgUtf8);
|
}
|
||||||
::LocalFree(errMsgBuffer);
|
((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
|
#else
|
||||||
auto length = ::read(STDIN_FILENO, utf8, maxSizeBytes - 1);
|
auto length = ::read(STDIN_FILENO, utf8, maxSizeBytes - 1);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user