#include #include #include #include #include #include namespace drvutil { // strerror has to be the most overcomplicated function imaginable. The simple // version, 'strerror', is not thread-safe, and the improved versions are all // incompatible from OS to OS. Even different versions of linux aren't // compatible. A lot of conditional compilation is needed. inline static void strerror_helper(int status, int errnum, char errbuf[256]) { if (status != 0) { snprintf(errbuf, 256, "unknown errno %d", errnum); } } inline static void strerror_helper(const char *result, int errnum, char errbuf[256]) { if (result != errbuf) { snprintf(errbuf, 256, "%s", result); } } void strerror_safe(int errnum, char errbuf[256]) { auto rval = strerror_r(errnum, errbuf, 256); strerror_helper(rval, errnum, errbuf); } std::string strerror_str(int errnum) { char buf[256]; strerror_safe(errnum, buf); return buf; } class MonoClock { private: struct timespec base_; public: MonoClock() { int status = clock_gettime(CLOCK_MONOTONIC, &base_); assert(status == 0); } double get() { struct timespec t; int status = clock_gettime(CLOCK_MONOTONIC, &t); assert(status == 0); double tv_sec = t.tv_sec - base_.tv_sec; double tv_nsec = t.tv_nsec - base_.tv_nsec; return tv_sec + (tv_nsec * 1.0E-9); } }; static MonoClock monoclock; double get_monotonic_clock() { return monoclock.get(); } void console_write(const std::u32string &cps) { std::string utf8 = drvutil::utf32_to_utf8(cps); write(1, utf8.c_str(), utf8.size()); } std::u32string console_read() { std::u32string result; char buffer[512]; int nread = read(0, buffer, 512); if (nread > 0) { std::string_view s(buffer, nread); result = drvutil::utf8_to_utf32(s, nullptr); } return result; } } // namespace drvutil