94 lines
2.7 KiB
C++
94 lines
2.7 KiB
C++
|
|
#include <windows.h>
|
|
#include <profileapi.h>
|
|
|
|
namespace drvutil {
|
|
|
|
static void strerror_safe(int errnum, char errbuf[256]) {
|
|
int status = strerror_s(errbuf, 256, errnum);
|
|
if (status != 0) {
|
|
snprintf(errbuf, 256, "unknown errno %d", errnum);
|
|
}
|
|
}
|
|
|
|
std::string strerror_str(int errnum) {
|
|
char buf[256];
|
|
strerror_safe(errnum, buf);
|
|
return buf;
|
|
}
|
|
|
|
class MonoClock {
|
|
public:
|
|
double freq_;
|
|
LONGLONG base_;
|
|
inline LONGLONG qpc() {
|
|
LARGE_INTEGER x;
|
|
BOOL status = QueryPerformanceCounter(&x);
|
|
assert(status != 0);
|
|
return x.QuadPart;
|
|
}
|
|
MonoClock() {
|
|
LARGE_INTEGER x;
|
|
BOOL status = QueryPerformanceFrequency(&x);
|
|
assert(status != 0);
|
|
freq_ = 1.0 / double(x.QuadPart);
|
|
base_ = qpc();
|
|
}
|
|
double get() {
|
|
return (qpc() - base_) * freq_;
|
|
}
|
|
};
|
|
|
|
static MonoClock monoclock;
|
|
double get_monotonic_clock() {
|
|
return monoclock.get();
|
|
}
|
|
|
|
void console_write(const std::u32string &cps) {
|
|
if (cps.size() == 0) return;
|
|
// Convert to wstring. Any character not representable as a single wchar_t
|
|
// is replaced with a box. It's not ideal, but it's pretty good.
|
|
std::wstring ws(cps.size(), 0);
|
|
for (int i = 0; i < int(cps.size()); i++) {
|
|
char32_t c = cps[i];
|
|
if (drvutil::is_single_wchar_t(c)) ws[i] = (wchar_t)c;
|
|
else ws[i] = 0x2610;
|
|
}
|
|
HANDLE hstdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
assert(hstdout != INVALID_HANDLE_VALUE);
|
|
DWORD nwrote;
|
|
std::wstring_view v(ws);
|
|
while (v.size() > 0) {
|
|
int nwrite = v.size();
|
|
if (nwrite > 10000) nwrite = 10000;
|
|
assert(WriteConsoleW(hstdout, v.data(), nwrite, &nwrote, nullptr));
|
|
assert(nwrote > 0);
|
|
v.remove_prefix(nwrote);
|
|
}
|
|
}
|
|
|
|
std::u32string console_read() {
|
|
HANDLE hstdin = GetStdHandle(STD_INPUT_HANDLE);
|
|
assert(hstdin != INVALID_HANDLE_VALUE);
|
|
INPUT_RECORD inrecords[512];
|
|
DWORD nread, nevents;
|
|
if (GetNumberOfConsoleInputEvents(hstdin, &nevents)) {
|
|
if (int(nevents) > 0) {
|
|
if (int(nevents) > 512) nevents = 512;
|
|
ReadConsoleInputW(hstdin, inrecords, nevents, &nread);
|
|
std::u32string result(nread, 0);
|
|
int len = 0;
|
|
for (int i = 0; i < int(nread); i++) {
|
|
const INPUT_RECORD &inr = inrecords[i];
|
|
if (inr.EventType != KEY_EVENT) continue;
|
|
const KEY_EVENT_RECORD &key = inr.Event.KeyEvent;
|
|
if (!key.bKeyDown) continue;
|
|
result[len++] = key.uChar.UnicodeChar;
|
|
}
|
|
return result.substr(0, len);
|
|
}
|
|
}
|
|
return std::u32string();
|
|
}
|
|
|
|
} // namespace drvutil
|