Replaced the usage of ReadConsoleInputW and fgetwc with standard C++ input functions to make getchar32() work consistently in all environments, including cases when stdin is redirected.

The previous implementation of getchar32() relied on low-level console functions, which caused issues when running the code in subprocesses with redirected stdin. The ReadConsoleInputW function is designed to read from the console input buffer and may not function correctly with input redirection. Additionally, using fgetwc in a Windows environment could lead to potential issues in certain scenarios.

I encountered unexpected results when redirecting stdin, even without passing any argument. To replicate the issue, try the following command in your C# code:

```
            ProcessStartInfo startInfo = new()
            {
                FileName = ".\\main.exe",
                Arguments = "-m .\\7b-q4.bin -n 256 --repeat_penalty 1.0 --interactive-first -r \"User:\" -f .\\chat-with-bob.txt",
                RedirectStandardOutput = true,
                RedirectStandardInput = true,
                UseShellExecute = false,
                CreateNoWindow = true
            };
```

To address this problem and enable people to stream the program directly to a UI without worrying about the C++ part, I made the following changes:
- Replaced ReadConsoleInputW with std::getwchar(), a standard C++ input function that reads wide characters from std::wcin. This change allows getchar32() to handle both console and redirected stdin scenarios consistently.

With these modifications, getchar32() now functions as intended in various environments and ensures that console interactions work correctly, even when stdin is redirected.
This commit is contained in:
Kerim Büyükakyüz 2023-08-01 14:05:46 +03:00 committed by GitHub
parent 86aeb27734
commit 5b61ec41e0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -778,34 +778,26 @@ void console_set_color(console_state & con_st, console_color_t color) {
char32_t getchar32() {
#if defined(_WIN32)
HANDLE hConsole = GetStdHandle(STD_INPUT_HANDLE);
wchar_t high_surrogate = 0;
while (true) {
INPUT_RECORD record;
DWORD count;
if (!ReadConsoleInputW(hConsole, &record, 1, &count) || count == 0) {
wint_t wc = std::getwchar(); // Use std::getwchar() to read a wide character from std::wcin
if (wc == WEOF) {
return WEOF;
}
if (record.EventType == KEY_EVENT && record.Event.KeyEvent.bKeyDown) {
wchar_t wc = record.Event.KeyEvent.uChar.UnicodeChar;
if (wc == 0) {
continue;
if ((wc >= 0xD800) && (wc <= 0xDBFF)) { // Check if wc is a high surrogate
high_surrogate = wc;
continue;
} else if ((wc >= 0xDC00) && (wc <= 0xDFFF)) { // Check if wc is a low surrogate
if (high_surrogate != 0) { // Check if we have a high surrogate
return ((high_surrogate - 0xD800) << 10) + (wc - 0xDC00) + 0x10000;
}
if ((wc >= 0xD800) && (wc <= 0xDBFF)) { // Check if wc is a high surrogate
high_surrogate = wc;
continue;
} else if ((wc >= 0xDC00) && (wc <= 0xDFFF)) { // Check if wc is a low surrogate
if (high_surrogate != 0) { // Check if we have a high surrogate
return ((high_surrogate - 0xD800) << 10) + (wc - 0xDC00) + 0x10000;
}
}
high_surrogate = 0; // Reset the high surrogate
return static_cast<char32_t>(wc);
}
high_surrogate = 0; // Reset the high surrogate
return static_cast<char32_t>(wc);
}
#else
wchar_t wc = getwchar();