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) { ...@@ -73,25 +73,45 @@ static void writeLineToFd(int fd, StringPtr message) {
} }
#if _WIN32 #if _WIN32
// Sadly, there doesn't seem to be an API on windows that atomically writes data from multiple buffers. char* newlineExpansionBuffer = (char*)_alloca(2 * (message.size() + 1));
// Also, windows APIs always expect unicode, not utf8. Therefore, we must convert the data every time. 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)); HANDLE handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
DWORD consoleMode;
bool redirectedToFile = !GetConsoleMode(handle, &consoleMode);
size_t bufferCharCount = message.size() + 1; DWORD writtenSize;
wchar_t* buffer = (wchar_t*)_alloca(sizeof(wchar_t) * bufferCharCount); 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 <= newlineExpandedSize);
KJ_ASSERT(finalSize < bufferCharCount);
if(buffer[finalSize - 1] != '\n') { WriteConsoleW(handle, buffer, finalSize, &writtenSize, nullptr);
buffer[finalSize++] = '\n';
} }
DWORD writtenSize;
WriteFile(handle, buffer, finalSize * sizeof(wchar_t), &writtenSize, nullptr);
#else #else
// Unfortunately the writev interface requires non-const pointers even though it won't modify // Unfortunately the writev interface requires non-const pointers even though it won't modify
// the data. // 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