refactor(windows console): reduce code duplication

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
This commit is contained in:
Rachel Powers 2023-08-02 06:19:43 -07:00
parent 760b80934f
commit bae59a8c07
No known key found for this signature in database
GPG Key ID: E10E321EB160949B

View File

@ -26,6 +26,24 @@
#include <windows.h> #include <windows.h>
#include <iostream> #include <iostream>
void RedirectHandle(DWORD handle, FILE* stream, const char* mode ) {
HANDLE stdHandle = GetStdHandle(handle);
if (stdHandle != INVALID_HANDLE_VALUE) {
int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT);
if (fileDescriptor != -1) {
FILE* file = _fdopen(fileDescriptor, mode);
if (file != NULL) {
int dup2Result = _dup2(_fileno(file), _fileno(stream));
if (dup2Result == 0) {
setvbuf(stream, NULL, _IONBF, 0);
}
}
}
}
}
// taken from https://stackoverflow.com/a/25927081 // taken from https://stackoverflow.com/a/25927081
// getting a proper output to console with redirection support on windows is apparently hell // getting a proper output to console with redirection support on windows is apparently hell
void BindCrtHandlesToStdHandles(bool bindStdIn, bool bindStdOut, bool bindStdErr) void BindCrtHandlesToStdHandles(bool bindStdIn, bool bindStdOut, bool bindStdErr)
@ -52,53 +70,17 @@ void BindCrtHandlesToStdHandles(bool bindStdIn, bool bindStdOut, bool bindStdErr
// Redirect unbuffered stdin from the current standard input handle // Redirect unbuffered stdin from the current standard input handle
if (bindStdIn) { if (bindStdIn) {
HANDLE stdHandle = GetStdHandle(STD_INPUT_HANDLE); RedirectHandle(STD_INPUT_HANDLE, stdin, "r");
if (stdHandle != INVALID_HANDLE_VALUE) {
int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT);
if (fileDescriptor != -1) {
FILE* file = _fdopen(fileDescriptor, "r");
if (file != NULL) {
int dup2Result = _dup2(_fileno(file), _fileno(stdin));
if (dup2Result == 0) {
setvbuf(stdin, NULL, _IONBF, 0);
}
}
}
}
} }
// Redirect unbuffered stdout to the current standard output handle // Redirect unbuffered stdout to the current standard output handle
if (bindStdOut) { if (bindStdOut) {
HANDLE stdHandle = GetStdHandle(STD_OUTPUT_HANDLE); RedirectHandle(STD_OUTPUT_HANDLE, stdout, "w");
if (stdHandle != INVALID_HANDLE_VALUE) {
int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT);
if (fileDescriptor != -1) {
FILE* file = _fdopen(fileDescriptor, "w");
if (file != NULL) {
int dup2Result = _dup2(_fileno(file), _fileno(stdout));
if (dup2Result == 0) {
setvbuf(stdout, NULL, _IONBF, 0);
}
}
}
}
} }
// Redirect unbuffered stderr to the current standard error handle // Redirect unbuffered stderr to the current standard error handle
if (bindStdErr) { if (bindStdErr) {
HANDLE stdHandle = GetStdHandle(STD_ERROR_HANDLE); RedirectHandle(STD_ERROR_HANDLE, stderr, "w");
if (stdHandle != INVALID_HANDLE_VALUE) {
int fileDescriptor = _open_osfhandle((intptr_t)stdHandle, _O_TEXT);
if (fileDescriptor != -1) {
FILE* file = _fdopen(fileDescriptor, "w");
if (file != NULL) {
int dup2Result = _dup2(_fileno(file), _fileno(stderr));
if (dup2Result == 0) {
setvbuf(stderr, NULL, _IONBF, 0);
}
}
}
}
} }
// Clear the error state for each of the C++ standard stream objects. We need to do this, as attempts to access the // Clear the error state for each of the C++ standard stream objects. We need to do this, as attempts to access the
@ -121,13 +103,29 @@ void BindCrtHandlesToStdHandles(bool bindStdIn, bool bindStdOut, bool bindStdErr
bool AttachWindowsConsole() { bool AttachWindowsConsole() {
auto stdout_type = GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)); auto stdinType = GetFileType(GetStdHandle(STD_INPUT_HANDLE));
if (stdout_type == FILE_TYPE_CHAR || stdout_type == FILE_TYPE_UNKNOWN) { auto stdoutType = GetFileType(GetStdHandle(STD_OUTPUT_HANDLE));
if (AttachConsole(ATTACH_PARENT_PROCESS)) { auto stderrType = GetFileType(GetStdHandle(STD_ERROR_HANDLE));
BindCrtHandlesToStdHandles(true, true, true);
return true; bool bindStdIn = false;
} bool bindStdOut = false;
bool bindStdErr = false;
if (stdinType == FILE_TYPE_CHAR || stdinType == FILE_TYPE_UNKNOWN) {
bindStdIn = true;
} }
if (stdoutType == FILE_TYPE_CHAR || stdoutType == FILE_TYPE_UNKNOWN) {
bindStdOut = true;
}
if (stderrType == FILE_TYPE_CHAR || stderrType == FILE_TYPE_UNKNOWN) {
bindStdErr = true;
}
if (AttachConsole(ATTACH_PARENT_PROCESS)) {
BindCrtHandlesToStdHandles(bindStdIn, bindStdOut, bindStdErr);
return true;
}
return false; return false;
} }