#pragma once class AsyncInput { public: static AsyncInput* GetInstance(); static void Finalize(); static char *Gets(char* buffer, size_t bufferSize); static void ScanKey(); private: static AsyncInput* _instance; AsyncInput(); ~AsyncInput(); void ScanKeyImpl(); char* AsyncGets(char* buffer, size_t bufferSize); HANDLE _hStdin; DWORD _fdwMode; uint16_t _writeChar; uint16_t _readChar; CHAR _charBuffer[256]; };
#include <Windows.h> #include <stdint.h> #include <stdio.h> //#include "_string.h" // 改行コードの除去とかBackSpace対応とか #include "AsyncInput.h" AsyncInput* AsyncInput::_instance = NULL; AsyncInput::AsyncInput() { _hStdin = GetStdHandle(STD_INPUT_HANDLE); GetConsoleMode(_hStdin, &_fdwMode); SetConsoleMode(_hStdin, ENABLE_WINDOW_INPUT); _writeChar = 0; _readChar = 0; _charBuffer[0] = '\0'; } AsyncInput::~AsyncInput() { SetConsoleMode(_hStdin, _fdwMode); } AsyncInput* AsyncInput::GetInstance() { if (_instance != NULL) return _instance; _instance = new AsyncInput(); return _instance; } void AsyncInput::Finalize() { if (_instance == NULL) return; delete _instance; _instance = NULL; } void AsyncInput::ScanKey() { auto instance = GetInstance(); instance->ScanKeyImpl(); } void AsyncInput::ScanKeyImpl() { INPUT_RECORD irInBuf[32]; DWORD irRead; if (PeekConsoleInput(_hStdin, irInBuf, _countof(irInBuf), &irRead) && irRead > 0) { ReadConsoleInput(_hStdin, irInBuf, _countof(irInBuf), &irRead); for (int i = 0; i < irRead; ++i) { if (irInBuf[i].EventType != KEY_EVENT) continue; auto ascii = irInBuf[i].Event.KeyEvent.uChar.AsciiChar; auto keyDown = irInBuf[i].Event.KeyEvent.bKeyDown; if (ascii == 0 || !keyDown) continue; putchar(ascii); if (ascii == '\r') putchar('\n'); uint16_t nw = (_writeChar + 1) % _countof(_charBuffer); if (nw == _readChar) _readChar = (_readChar + 1) % _countof(_charBuffer); _charBuffer[_writeChar] = ascii; _writeChar = nw; } } } char* AsyncInput::Gets(char* line, size_t maxSize) { auto instance = GetInstance(); instance->ScanKeyImpl(); char* result = instance->AsyncGets(line, maxSize); if (result == NULL) return NULL; //_chomp(result); // 改行を除去 //_removebackspace(result); // バックスペースを適用 return result; } char* AsyncInput::AsyncGets(char* line, size_t maxSize) { if (maxSize <= 1) { return NULL; } uint16_t wpos = 0, rpos; uint8_t c; uint16_t size = maxSize; --size; // make room for '\0' rpos = _readChar; while (wpos < size) { if (rpos == _writeChar) return NULL; c = _charBuffer[rpos]; rpos = (rpos + 1) % _countof(_charBuffer); if (c != '\r' && c != '\n' && c != '\0') { line[wpos++] = c; } else if (wpos > 0) { break; } } _readChar = rpos; line[wpos] = '\0'; return line; }
#include <stdio.h> #include "AsyncInput.h" void main(){ char buffer[256]; for(;;){ char *input = AsyncInput::Gets(buffer,sizeof(buffer)); if (input == NULL) continue; printf("%s\r\n",input); } }