Update fmt to 8.0.0; drop support for wchar

Adds some boost-nowide headers to assist in
UTF-8/16 conversion for Windows API.
This commit is contained in:
2021-06-22 15:13:37 -04:00
parent 274ad5ef07
commit df3c283186
13 changed files with 1337 additions and 290 deletions

View File

@@ -49,14 +49,6 @@
#define BOLD "\x1b[1m"
#define NORMAL "\x1b[0m"
#define W_RED L"\x001b[1;31m"
#define W_YELLOW L"\x001b[1;33m"
#define W_GREEN L"\x001b[1;32m"
#define W_MAGENTA L"\x001b[1;35m"
#define W_CYAN L"\x001b[1;36m"
#define W_BOLD L"\x001b[1m"
#define W_NORMAL L"\x001b[0m"
#if _WIN32
#define FOREGROUND_WHITE FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
#endif
@@ -72,13 +64,6 @@ static Module Log("logvisor");
static std::unordered_map<std::thread::id, const char*> ThreadMap;
static std::wstring Widen(std::string str) {
std::wstring wide(str.size(), L'\0');
std::locale loc;
std::use_facet<std::ctype<wchar_t>>(loc).widen(str.data(), str.data()+str.size(), wide.data());
return wide;
}
static void AddThreadToMap(const char* name) {
auto lk = LockLog();
ThreadMap[std::this_thread::get_id()] = name;
@@ -119,16 +104,16 @@ void KillProcessTree() {
HANDLE hSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (::Process32FirstW(hSnap, &pe)) {
if (::Process32FirstW(hSnap, &pe) == TRUE) {
BOOL bContinue = TRUE;
// kill child processes
while (bContinue) {
while (bContinue == TRUE) {
// only kill child processes and let console window remain
if (pe.th32ParentProcessID == myprocID && std::wcscmp(pe.szExeFile, L"conhost.exe") != 0) {
HANDLE hChildProc = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe.th32ProcessID);
if (hChildProc) {
if (hChildProc != nullptr) {
::TerminateProcess(hChildProc, 1);
::CloseHandle(hChildProc);
}
@@ -148,9 +133,9 @@ void KillProcessTree() {
HANDLE process;
process = GetCurrentProcess();
SymInitialize(process, NULL, TRUE);
frames = CaptureStackBackTrace(0, 100, stack, NULL);
symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1);
SymInitialize(process, nullptr, TRUE);
frames = CaptureStackBackTrace(0, 100, stack, nullptr);
symbol = static_cast<SYMBOL_INFO*>(calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1));
symbol->MaxNameLen = 255;
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
@@ -268,28 +253,6 @@ void KillProcessTree() {}
LogMutex _LogMutex;
#if _WIN32
static void AbortHandler(int signum) {
_LogMutex.enabled = false;
switch (signum) {
case SIGSEGV:
Log.report(logvisor::Fatal, FMT_STRING(L"Segmentation Fault"));
break;
case SIGILL:
Log.report(logvisor::Fatal, FMT_STRING(L"Bad Execution"));
break;
case SIGFPE:
Log.report(logvisor::Fatal, FMT_STRING(L"Floating Point Exception"));
break;
case SIGABRT:
Log.report(logvisor::Fatal, FMT_STRING(L"Abort Signal"));
break;
default:
Log.report(logvisor::Fatal, FMT_STRING(L"unknown signal {}"), signum);
break;
}
}
#else
static void AbortHandler(int signum) {
_LogMutex.enabled = false;
switch (signum) {
@@ -310,15 +273,14 @@ static void AbortHandler(int signum) {
break;
}
}
#endif
uint64_t _LogCounter;
std::vector<std::unique_ptr<ILogger>> MainLoggers;
std::atomic_size_t ErrorCount(0);
static std::chrono::steady_clock MonoClock;
static std::chrono::steady_clock::time_point GlobalStart = MonoClock.now();
static inline std::chrono::steady_clock::duration CurrentUptime() { return MonoClock.now() - GlobalStart; }
using MonoClock = std::chrono::steady_clock;
static MonoClock::time_point GlobalStart = MonoClock::now();
static inline MonoClock::duration CurrentUptime() { return MonoClock::now() - GlobalStart; }
std::atomic_uint_fast64_t FrameIndex(0);
static inline int ConsoleWidth() {
@@ -506,8 +468,6 @@ struct ConsoleLogger : public ILogger {
SendBuffer(bufOut);
}
void report(const char* modName, Level severity, fmt::wstring_view format, fmt::wformat_args args) override {}
void reportSource(const char* modName, Level severity, const char* file, unsigned linenum, fmt::string_view format,
fmt::format_args args) override {
if (!m_ready)
@@ -566,9 +526,6 @@ struct ConsoleLogger : public ILogger {
SendBuffer(bufOut);
}
void reportSource(const char* modName, Level severity, const char* file, unsigned linenum, fmt::wstring_view format,
fmt::wformat_args args) override {}
};
#else
@@ -603,7 +560,7 @@ struct ConsoleLogger : public ILogger {
static void _reportHead(const char* modName, const char* sourceInfo, Level severity) {
/* Clear current line out */
std::fprintf(stderr, "\r%*c\r", ConsoleWidth(), ' ');
// std::fprintf(stderr, "\r%*c\r", ConsoleWidth(), ' ');
const std::chrono::steady_clock::duration tm = CurrentUptime();
const double tmd = tm.count() * std::chrono::steady_clock::duration::period::num /
@@ -715,120 +672,6 @@ struct ConsoleLogger : public ILogger {
}
}
static void _reportHead(const wchar_t* modName, const wchar_t* sourceInfo, Level severity) {
/* Clear current line out */
std::fwprintf(stderr, L"\r%*c\r", ConsoleWidth(), L' ');
const std::chrono::steady_clock::duration tm = CurrentUptime();
const double tmd = tm.count() * std::chrono::steady_clock::duration::period::num /
static_cast<double>(std::chrono::steady_clock::duration::period::den);
const std::thread::id thrId = std::this_thread::get_id();
std::optional<std::wstring> thrName;
if (ThreadMap.find(thrId) != ThreadMap.end())
thrName = Widen(ThreadMap[thrId]);
if (XtermColor) {
std::fputws(W_BOLD L"[", stderr);
fmt::print(stderr, FMT_STRING(W_GREEN L"{:.4f} "), tmd);
const uint_fast64_t fIdx = FrameIndex.load();
if (fIdx != 0)
fmt::print(stderr, FMT_STRING(L"({}) "), fIdx);
switch (severity) {
case Info:
std::fputws(W_BOLD W_CYAN L"INFO", stderr);
break;
case Warning:
std::fputws(W_BOLD W_YELLOW L"WARNING", stderr);
break;
case Error:
std::fputws(W_RED W_BOLD L"ERROR", stderr);
break;
case Fatal:
std::fputws(W_BOLD W_RED L"FATAL ERROR", stderr);
break;
default:
break;
};
fmt::print(stderr, FMT_STRING(W_NORMAL W_BOLD L" {}"), modName);
if (sourceInfo)
fmt::print(stderr, FMT_STRING(W_BOLD W_YELLOW L" {{}}"), sourceInfo);
if (thrName)
fmt::print(stderr, FMT_STRING(W_BOLD W_MAGENTA L" ({})"), *thrName);
std::fputws(W_NORMAL W_BOLD L"] " W_NORMAL, stderr);
} else {
#if _WIN32
#if !WINDOWS_STORE
SetConsoleTextAttribute(Term, FOREGROUND_INTENSITY | FOREGROUND_WHITE);
std::fputwc(L'[', stderr);
SetConsoleTextAttribute(Term, FOREGROUND_INTENSITY | FOREGROUND_GREEN);
fmt::print(stderr, FMT_STRING(L"{:.4f} "), tmd);
const uint64_t fi = FrameIndex.load();
if (fi != 0)
std::fwprintf(stderr, L"(%" PRIu64 L") ", fi);
switch (severity) {
case Info:
SetConsoleTextAttribute(Term, FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE);
std::fputws(L"INFO", stderr);
break;
case Warning:
SetConsoleTextAttribute(Term, FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN);
std::fputws(L"WARNING", stderr);
break;
case Error:
SetConsoleTextAttribute(Term, FOREGROUND_INTENSITY | FOREGROUND_RED);
std::fputws(L"ERROR", stderr);
break;
case Fatal:
SetConsoleTextAttribute(Term, FOREGROUND_INTENSITY | FOREGROUND_RED);
std::fputws(L"FATAL ERROR", stderr);
break;
default:
break;
}
SetConsoleTextAttribute(Term, FOREGROUND_INTENSITY | FOREGROUND_WHITE);
fmt::print(stderr, FMT_STRING(L" {}"), modName);
SetConsoleTextAttribute(Term, FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN);
if (sourceInfo)
fmt::print(stderr, FMT_STRING(L" {{}}"), sourceInfo);
SetConsoleTextAttribute(Term, FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE);
if (thrName)
fmt::print(stderr, FMT_STRING(L" ({})"), *thrName);
SetConsoleTextAttribute(Term, FOREGROUND_INTENSITY | FOREGROUND_WHITE);
std::fputws(L"] ", stderr);
SetConsoleTextAttribute(Term, FOREGROUND_WHITE);
#endif
#else
std::fputwc(L'[', stderr);
fmt::print(stderr, FMT_STRING(L"{:.4f} "), tmd);
uint_fast64_t fIdx = FrameIndex.load();
if (fIdx)
fmt::print(stderr, FMT_STRING(L"({}) "), fIdx);
switch (severity) {
case Info:
std::fputws(L"INFO", stderr);
break;
case Warning:
std::fputws(L"WARNING", stderr);
break;
case Error:
std::fputws(L"ERROR", stderr);
break;
case Fatal:
std::fputws(L"FATAL ERROR", stderr);
break;
default:
break;
}
fmt::print(stderr, FMT_STRING(L" {}"), modName);
if (sourceInfo)
fmt::print(stderr, FMT_STRING(L" {{}}"), sourceInfo);
if (thrName)
fmt::print(stderr, FMT_STRING(L" ({})"), *thrName);
std::fputws(L"] ", stderr);
#endif
}
}
void report(const char* modName, Level severity, fmt::string_view format, fmt::format_args args) override {
_reportHead(modName, nullptr, severity);
fmt::vprint(stderr, format, args);
@@ -836,13 +679,6 @@ struct ConsoleLogger : public ILogger {
std::fflush(stderr);
}
void report(const char* modName, Level severity, fmt::wstring_view format, fmt::wformat_args args) override {
_reportHead(Widen(modName).c_str(), nullptr, severity);
fmt::vprint(stderr, format, args);
std::fputwc(L'\n', stderr);
std::fflush(stderr);
}
void reportSource(const char* modName, Level severity, const char* file, unsigned linenum, fmt::string_view format,
fmt::format_args args) override {
_reportHead(modName, fmt::format(FMT_STRING("{}:{}"), file, linenum).c_str(), severity);
@@ -850,14 +686,6 @@ struct ConsoleLogger : public ILogger {
std::fputc('\n', stderr);
std::fflush(stderr);
}
void reportSource(const char* modName, Level severity, const char* file, unsigned linenum, fmt::wstring_view format,
fmt::wformat_args args) override {
_reportHead(Widen(modName).c_str(), fmt::format(FMT_STRING(L"{}:{}"), Widen(file).c_str(), linenum).c_str(), severity);
fmt::vprint(stderr, format, args);
std::fputwc(L'\n', stderr);
std::fflush(stderr);
}
};
#endif
@@ -868,6 +696,15 @@ void RegisterConsoleLogger() {
if (!ConsoleLoggerRegistered) {
MainLoggers.emplace_back(new ConsoleLogger);
ConsoleLoggerRegistered = true;
#if _WIN32
#if 0
if (GetACP() != CP_UTF8) {
Log.report(Fatal, FMT_STRING("UTF-8 codepage not active! (Windows 10 1903+ required)"));
}
#else
SetConsoleOutputCP(CP_UTF8);
#endif
#endif
}
}
@@ -921,7 +758,7 @@ struct FileLogger : public ILogger {
openFile();
}
}
virtual void closeFile() {
virtual void closeFile() {
if (fp) {
std::fclose(fp);
fp = nullptr;
@@ -971,48 +808,6 @@ struct FileLogger : public ILogger {
std::fputs("] ", fp);
}
void _reportHead(const wchar_t* modName, const wchar_t* sourceInfo, Level severity) {
const std::chrono::steady_clock::duration tm = CurrentUptime();
const double tmd = tm.count() * std::chrono::steady_clock::duration::period::num /
static_cast<double>(std::chrono::steady_clock::duration::period::den);
const std::thread::id thrId = std::this_thread::get_id();
const wchar_t* thrName = nullptr;
if (ThreadMap.find(thrId) != ThreadMap.end()) {
thrName = Widen(ThreadMap[thrId]).c_str();
}
std::fputwc(L'[', fp);
std::fwprintf(fp, L"%5.4f ", tmd);
const uint_fast64_t fIdx = FrameIndex.load();
if (fIdx != 0) {
std::fwprintf(fp, L"(%" PRIu64 L") ", fIdx);
}
switch (severity) {
case Info:
std::fputws(L"INFO", fp);
break;
case Warning:
std::fputws(L"WARNING", fp);
break;
case Error:
std::fputws(L"ERROR", fp);
break;
case Fatal:
std::fputws(L"FATAL ERROR", fp);
break;
default:
break;
};
std::fwprintf(fp, L" %s", modName);
if (sourceInfo) {
std::fwprintf(fp, L" {%s}", sourceInfo);
}
if (thrName) {
std::fwprintf(fp, L" (%s)", thrName);
}
std::fputws(L"] ", fp);
}
void report(const char* modName, Level severity, fmt::string_view format, fmt::format_args args) override {
openFileIfNeeded();
_reportHead(modName, nullptr, severity);
@@ -1020,13 +815,6 @@ struct FileLogger : public ILogger {
std::fputc('\n', fp);
}
void report(const char* modName, Level severity, fmt::wstring_view format, fmt::wformat_args args) override {
openFileIfNeeded();
_reportHead(Widen(modName).c_str(), nullptr, severity);
fmt::vprint(fp, format, args);
std::fputwc(L'\n', fp);
}
void reportSource(const char* modName, Level severity, const char* file, unsigned linenum, fmt::string_view format,
fmt::format_args args) override {
openFileIfNeeded();
@@ -1034,19 +822,11 @@ struct FileLogger : public ILogger {
fmt::vprint(fp, format, args);
std::fputc('\n', fp);
}
void reportSource(const char* modName, Level severity, const char* file, unsigned linenum, fmt::wstring_view format,
fmt::wformat_args args) override {
openFileIfNeeded();
_reportHead(Widen(modName).c_str(), Widen(fmt::format(FMT_STRING("{}:{}"), file, linenum)).c_str(), severity);
fmt::vprint(fp, format, args);
std::fputwc(L'\n', fp);
}
};
struct FileLogger8 : public FileLogger {
const char* m_filepath;
FileLogger8(const char* filepath) : FileLogger(log_typeid(FileLogger8)), m_filepath(filepath) {}
explicit FileLogger8(const char* filepath) : FileLogger(log_typeid(FileLogger8)), m_filepath(filepath) {}
void openFile() override { fp = std::fopen(m_filepath, "a"); }
~FileLogger8() override = default;
};
@@ -1056,30 +836,4 @@ void RegisterFileLogger(const char* filepath) {
MainLoggers.emplace_back(new FileLogger8(filepath));
}
#if LOG_UCS2
struct FileLogger16 : public FileLogger {
const wchar_t* m_filepath;
FileLogger16(const wchar_t* filepath) : FileLogger(log_typeid(FileLogger16)), m_filepath(filepath) {}
void openFile() override { fp = _wfopen(m_filepath, L"a"); }
~FileLogger16() override = default;
};
void RegisterFileLogger(const wchar_t* filepath) {
/* Determine if file logger already added */
for (const auto& logger : MainLoggers) {
if (logger->getTypeId() == log_typeid(FileLogger16)) {
const auto* fl = static_cast<const FileLogger16*>(logger.get());
if (!wcscmp(filepath, fl->m_filepath)) {
return;
}
}
}
/* Otherwise construct new file logger */
MainLoggers.emplace_back(new FileLogger16(filepath));
}
#endif
} // namespace logvisor