Commit c0fbfd9c authored by Joshua Warner's avatar Joshua Warner

fix writeLineToFd for windows console output

This function now (on windows):
* converts \n to \r\n (for both file and console outputs)
* when the output is redirected to a file, uses WriteFile with utf-8 output
* when the output will appear on a console, uses WriteConsole with utf-16 output instead
parent 19784fdd
......@@ -73,25 +73,45 @@ static void writeLineToFd(int fd, StringPtr message) {
}
#if _WIN32
// Sadly, there doesn't seem to be an API on windows that atomically writes data from multiple buffers.
// Also, windows APIs always expect unicode, not utf8. Therefore, we must convert the data every time.
char* newlineExpansionBuffer = (char*)_alloca(2 * (message.size() + 1));
char* p = newlineExpansionBuffer;
for(char ch : message) {
if(ch == '\n') {
*(p++) = '\r';
}
*(p++) = ch;
}
if(!message.endsWith("\n")) {
*(p++) = '\r';
*(p++) = '\n';
}
size_t newlineExpandedSize = p - newlineExpansionBuffer;
KJ_ASSERT(newlineExpandedSize <= 2 * (message.size() + 1));
HANDLE handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
DWORD consoleMode;
bool redirectedToFile = !GetConsoleMode(handle, &consoleMode);
size_t bufferCharCount = message.size() + 1;
wchar_t* buffer = (wchar_t*)_alloca(sizeof(wchar_t) * bufferCharCount);
DWORD writtenSize;
if(redirectedToFile) {
WriteFile(handle, newlineExpansionBuffer, newlineExpandedSize, &writtenSize, nullptr);
} else {
wchar_t* buffer = (wchar_t*)_alloca(sizeof(wchar_t) * newlineExpandedSize);
size_t finalSize = MultiByteToWideChar(CP_UTF8, 0, message.begin(), message.size(), buffer, bufferCharCount);
size_t finalSize = MultiByteToWideChar(
CP_UTF8,
0,
newlineExpansionBuffer,
newlineExpandedSize,
buffer,
newlineExpandedSize);
// We should always have at least one character of extra space for the possible '\n'.
KJ_ASSERT(finalSize < bufferCharCount);
KJ_ASSERT(finalSize <= newlineExpandedSize);
if(buffer[finalSize - 1] != '\n') {
buffer[finalSize++] = '\n';
WriteConsoleW(handle, buffer, finalSize, &writtenSize, nullptr);
}
DWORD writtenSize;
WriteFile(handle, buffer, finalSize * sizeof(wchar_t), &writtenSize, nullptr);
#else
// Unfortunately the writev interface requires non-const pointers even though it won't modify
// the data.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment