2014-06-17 15:44:03 +00:00
|
|
|
#pragma once
|
|
|
|
|
2016-02-01 21:55:43 +00:00
|
|
|
#include "types.h"
|
|
|
|
#include "Atomic.h"
|
2014-06-17 15:44:03 +00:00
|
|
|
|
2016-01-12 21:57:16 +00:00
|
|
|
namespace _log
|
2014-06-17 15:44:03 +00:00
|
|
|
{
|
2016-01-12 21:57:16 +00:00
|
|
|
enum class level : uint
|
2014-06-17 15:44:03 +00:00
|
|
|
{
|
2016-01-12 21:57:16 +00:00
|
|
|
always, // highest level (unused, cannot be disabled)
|
|
|
|
fatal,
|
|
|
|
error,
|
|
|
|
todo,
|
|
|
|
success,
|
|
|
|
warning,
|
|
|
|
notice,
|
|
|
|
trace, // lowest level (usually disabled)
|
2014-06-17 15:44:03 +00:00
|
|
|
};
|
|
|
|
|
2016-01-12 21:57:16 +00:00
|
|
|
struct channel
|
2014-06-17 15:44:03 +00:00
|
|
|
{
|
2016-02-01 21:55:43 +00:00
|
|
|
// Channel prefix (added to every log message)
|
|
|
|
const char* const name;
|
2016-01-12 21:57:16 +00:00
|
|
|
|
|
|
|
// The lowest logging level enabled for this channel (used for early filtering)
|
2016-02-01 21:55:43 +00:00
|
|
|
atomic_t<level> enabled;
|
2016-01-12 21:57:16 +00:00
|
|
|
|
2016-02-01 21:55:43 +00:00
|
|
|
// Constant initialization: name and initial log level
|
|
|
|
constexpr channel(const char* name, level enabled = level::trace)
|
2016-04-26 22:27:24 +00:00
|
|
|
: name(name)
|
|
|
|
, enabled(enabled)
|
2016-01-12 21:57:16 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-04-26 22:27:24 +00:00
|
|
|
// Formatting function
|
2016-01-12 21:57:16 +00:00
|
|
|
template<typename... Args>
|
2016-04-25 10:49:12 +00:00
|
|
|
void format(level sev, const char* fmt, const Args&... args) const
|
2016-01-12 21:57:16 +00:00
|
|
|
{
|
2016-04-26 22:27:24 +00:00
|
|
|
#ifdef _MSC_VER
|
2016-01-12 21:57:16 +00:00
|
|
|
if (sev <= enabled)
|
2016-04-26 22:27:24 +00:00
|
|
|
#else
|
|
|
|
if (__builtin_expect(sev <= enabled, 0))
|
|
|
|
#endif
|
2016-04-25 10:49:12 +00:00
|
|
|
broadcast(*this, sev, fmt, ::unveil<Args>::get(args)...);
|
2016-01-12 21:57:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#define GEN_LOG_METHOD(_sev)\
|
|
|
|
template<typename... Args>\
|
2016-04-25 10:49:12 +00:00
|
|
|
void _sev(const char* fmt, const Args&... args) const\
|
2016-01-12 21:57:16 +00:00
|
|
|
{\
|
|
|
|
return format<Args...>(level::_sev, fmt, args...);\
|
|
|
|
}
|
|
|
|
|
|
|
|
GEN_LOG_METHOD(fatal)
|
|
|
|
GEN_LOG_METHOD(error)
|
|
|
|
GEN_LOG_METHOD(todo)
|
|
|
|
GEN_LOG_METHOD(success)
|
|
|
|
GEN_LOG_METHOD(warning)
|
|
|
|
GEN_LOG_METHOD(notice)
|
|
|
|
GEN_LOG_METHOD(trace)
|
|
|
|
|
|
|
|
#undef GEN_LOG_METHOD
|
2016-04-25 10:49:12 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
// Send log message to global logger instance
|
|
|
|
static void broadcast(const channel& ch, level sev, const char* fmt...);
|
2014-06-17 15:44:03 +00:00
|
|
|
};
|
|
|
|
|
2016-04-26 22:27:24 +00:00
|
|
|
/* Small set of predefined channels */
|
2016-01-12 21:57:16 +00:00
|
|
|
|
|
|
|
extern channel GENERAL;
|
|
|
|
extern channel LOADER;
|
|
|
|
extern channel MEMORY;
|
|
|
|
extern channel RSX;
|
|
|
|
extern channel HLE;
|
|
|
|
extern channel PPU;
|
|
|
|
extern channel SPU;
|
|
|
|
extern channel ARMv7;
|
2014-06-27 13:26:46 +00:00
|
|
|
}
|
2016-01-12 21:57:16 +00:00
|
|
|
|
2016-02-01 21:55:43 +00:00
|
|
|
template<>
|
|
|
|
struct bijective<_log::level, const char*>
|
|
|
|
{
|
2016-04-26 22:27:24 +00:00
|
|
|
static constexpr bijective_pair<_log::level, const char*> map[]
|
2016-02-01 21:55:43 +00:00
|
|
|
{
|
|
|
|
{ _log::level::always, "Nothing" },
|
|
|
|
{ _log::level::fatal, "Fatal" },
|
|
|
|
{ _log::level::error, "Error" },
|
|
|
|
{ _log::level::todo, "TODO" },
|
|
|
|
{ _log::level::success, "Success" },
|
|
|
|
{ _log::level::warning, "Warning" },
|
|
|
|
{ _log::level::notice, "Notice" },
|
|
|
|
{ _log::level::trace, "Trace" },
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2016-01-12 21:57:16 +00:00
|
|
|
// Legacy:
|
|
|
|
|
|
|
|
#define LOG_SUCCESS(ch, fmt, ...) _log::ch.success(fmt, ##__VA_ARGS__)
|
|
|
|
#define LOG_NOTICE(ch, fmt, ...) _log::ch.notice (fmt, ##__VA_ARGS__)
|
|
|
|
#define LOG_WARNING(ch, fmt, ...) _log::ch.warning(fmt, ##__VA_ARGS__)
|
|
|
|
#define LOG_ERROR(ch, fmt, ...) _log::ch.error (fmt, ##__VA_ARGS__)
|
|
|
|
#define LOG_TODO(ch, fmt, ...) _log::ch.todo (fmt, ##__VA_ARGS__)
|
|
|
|
#define LOG_TRACE(ch, fmt, ...) _log::ch.trace (fmt, ##__VA_ARGS__)
|
|
|
|
#define LOG_FATAL(ch, fmt, ...) _log::ch.fatal (fmt, ##__VA_ARGS__)
|