// Copyright 2009 Dolphin Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include #include #include #include "Common/FormatUtil.h" namespace Common::Log { enum class LogType : int { ACTIONREPLAY, AUDIO, AUDIO_INTERFACE, BOOT, COMMANDPROCESSOR, COMMON, CONSOLE, CONTROLLERINTERFACE, CORE, DISCIO, DSPHLE, DSPLLE, DSP_MAIL, DSPINTERFACE, DVDINTERFACE, DYNA_REC, EXPANSIONINTERFACE, FILEMON, FRAMEDUMP, GDB_STUB, GPFIFO, HOST_GPU, IOS, IOS_DI, IOS_ES, IOS_FS, IOS_NET, IOS_SD, IOS_SSL, IOS_STM, IOS_USB, IOS_WC24, IOS_WFS, IOS_WIIMOTE, MASTER_LOG, MEMMAP, MEMCARD_MANAGER, NETPLAY, OSHLE, OSREPORT, OSREPORT_HLE, PIXELENGINE, PROCESSORINTERFACE, POWERPC, SERIALINTERFACE, SP1, SYMBOLS, VIDEO, VIDEOINTERFACE, WII_IPC, WIIMOTE, NUMBER_OF_LOGS // Must be last }; enum class LogLevel : int { LNOTICE = 1, // VERY important information that is NOT errors. Like startup and OSReports. LERROR = 2, // Critical errors LWARNING = 3, // Something is suspicious. LINFO = 4, // General information. LDEBUG = 5, // Detailed debugging - might make things slow. }; #if defined(_DEBUG) || defined(DEBUGFAST) constexpr auto MAX_LOGLEVEL = Common::Log::LogLevel::LDEBUG; #else constexpr auto MAX_LOGLEVEL = Common::Log::LogLevel::LINFO; #endif // logging static const char LOG_LEVEL_TO_CHAR[7] = "-NEWID"; void GenericLogFmtImpl(LogLevel level, LogType type, const char* file, int line, fmt::string_view format, const fmt::format_args& args); template void GenericLogFmt(LogLevel level, LogType type, const char* file, int line, const S& format, const Args&... args) { static_assert(NumFields == sizeof...(args), "Unexpected number of replacement fields in format string; did you pass too few or " "too many arguments?"); GenericLogFmtImpl(level, type, file, line, format, fmt::make_args_checked(format, args...)); } void GenericLog(LogLevel level, LogType type, const char* file, int line, const char* fmt, ...) #ifdef __GNUC__ __attribute__((format(printf, 5, 6))) #endif ; void GenericLogV(LogLevel level, LogType type, const char* file, int line, const char* fmt, va_list args); } // namespace Common::Log // Let the compiler optimize this out #define GENERIC_LOG(t, v, ...) \ do \ { \ if (v <= Common::Log::MAX_LOGLEVEL) \ Common::Log::GenericLog(v, t, __FILE__, __LINE__, __VA_ARGS__); \ } while (0) #define ERROR_LOG(t, ...) \ do \ { \ GENERIC_LOG(Common::Log::LogType::t, Common::Log::LogLevel::LERROR, __VA_ARGS__); \ } while (0) #define WARN_LOG(t, ...) \ do \ { \ GENERIC_LOG(Common::Log::LogType::t, Common::Log::LogLevel::LWARNING, __VA_ARGS__); \ } while (0) #define NOTICE_LOG(t, ...) \ do \ { \ GENERIC_LOG(Common::Log::LogType::t, Common::Log::LogLevel::LNOTICE, __VA_ARGS__); \ } while (0) #define INFO_LOG(t, ...) \ do \ { \ GENERIC_LOG(Common::Log::LogType::t, Common::Log::LogLevel::LINFO, __VA_ARGS__); \ } while (0) #define DEBUG_LOG(t, ...) \ do \ { \ GENERIC_LOG(Common::Log::LogType::t, Common::Log::LogLevel::LDEBUG, __VA_ARGS__); \ } while (0) #define GENERIC_LOG_V(t, v, fmt, args) \ do \ { \ if (v <= Common::Log::MAX_LOGLEVEL) \ Common::Log::GenericLogV(v, t, __FILE__, __LINE__, fmt, args); \ } while (0) // fmtlib capable API #define GENERIC_LOG_FMT(t, v, format, ...) \ do \ { \ if (v <= Common::Log::MAX_LOGLEVEL) \ { \ /* Use a macro-like name to avoid shadowing warnings */ \ constexpr auto GENERIC_LOG_FMT_N = Common::CountFmtReplacementFields(format); \ Common::Log::GenericLogFmt(v, t, __FILE__, __LINE__, FMT_STRING(format), \ ##__VA_ARGS__); \ } \ } while (0) #define ERROR_LOG_FMT(t, ...) \ do \ { \ GENERIC_LOG_FMT(Common::Log::LogType::t, Common::Log::LogLevel::LERROR, __VA_ARGS__); \ } while (0) #define WARN_LOG_FMT(t, ...) \ do \ { \ GENERIC_LOG_FMT(Common::Log::LogType::t, Common::Log::LogLevel::LWARNING, __VA_ARGS__); \ } while (0) #define NOTICE_LOG_FMT(t, ...) \ do \ { \ GENERIC_LOG_FMT(Common::Log::LogType::t, Common::Log::LogLevel::LNOTICE, __VA_ARGS__); \ } while (0) #define INFO_LOG_FMT(t, ...) \ do \ { \ GENERIC_LOG_FMT(Common::Log::LogType::t, Common::Log::LogLevel::LINFO, __VA_ARGS__); \ } while (0) #define DEBUG_LOG_FMT(t, ...) \ do \ { \ GENERIC_LOG_FMT(Common::Log::LogType::t, Common::Log::LogLevel::LDEBUG, __VA_ARGS__); \ } while (0)