21#if MOCHI_PLATFORM_WINDOWS && !defined(__UNREAL__)
41#define MOCHI_LOG(...) MOCHI_LOG_IMPL(::superdex::LogChannel::Info, __FILE__, __LINE__, __VA_ARGS__)
42#define MOCHI_LOG_VERBOSE(...) MOCHI_LOG_IMPL(::superdex::LogChannel::Verbose, __FILE__, __LINE__, __VA_ARGS__)
43#define MOCHI_LOG_WARNING(...) MOCHI_LOG_IMPL(::superdex::LogChannel::Warning, __FILE__, __LINE__, __VA_ARGS__)
44#define MOCHI_LOG_ERROR(...) MOCHI_LOG_IMPL(::superdex::LogChannel::Error, __FILE__, __LINE__, __VA_ARGS__)
45#define MOCHI_LOG_TO(channel, ...) MOCHI_LOG_IMPL(channel, __FILE__, __LINE__, __VA_ARGS__)
49#define MOCHI_LOG_ONCE_HELPER(channel, ...) \
51 [[maybe_unused]] static bool logged_##__LINE__ = [&]() { \
52 MOCHI_LOG_IMPL(channel, __FILE__, __LINE__, __VA_ARGS__); \
56#define MOCHI_LOG_ONCE(...) MOCHI_LOG_ONCE_HELPER(::superdex::LogChannel::Info, __VA_ARGS__)
57#define MOCHI_LOG_VERBOSE_ONCE(...) MOCHI_LOG_ONCE_HELPER(::superdex::LogChannel::Verbose, __VA_ARGS__)
58#define MOCHI_LOG_WARNING_ONCE(...) MOCHI_LOG_ONCE_HELPER(::superdex::LogChannel::Warning, __VA_ARGS__)
59#define MOCHI_LOG_ERROR_ONCE(...) MOCHI_LOG_ONCE_HELPER(::superdex::LogChannel::Error, __VA_ARGS__)
62[[nodiscard]] std::string
Format(
char const* format, ...);
65using LogFn = std::function<void(
LogChannel,
char const* message,
char const* file,
int line)>;
80void Log(
LogChannel channel, std::string msg,
char const* file,
int line,
bool newline);
89#define MOCHI_LOG_IMPL(channel, file, line, ...) \
90 if (::superdex::IsLogChannelEnabled(channel)) { \
91 ::superdex::Log(channel, ::superdex::Format(__VA_ARGS__), file, line, true); \
96[[nodiscard]]
inline std::string
Format() {
100[[nodiscard]]
inline std::string
Format(
char const* format, ...) {
101 va_list args1, args2;
102 va_start(args1, format);
103 va_copy(args2, args1);
104 int len = vsnprintf(
nullptr, 0, format, args1);
106 str.resize((
size_t)len);
109 vsnprintf(&str[0], len + 1, format, args2);
121inline auto& GetLogMutexRef() {
122 static std::recursive_mutex s_logMutex;
125inline auto& GetLogFnRef() {
126 static LogFn s_logFn;
129inline auto& GetLogChannelsDisabledArrayRef() {
130 static std::array<bool, (size_t)
LogChannel::Count> s_logChannelsDisabled = []() {
135 return disabledChannels;
137 return s_logChannelsDisabled;
141inline void DefaultLogFn(
LogChannel channel, std::string msg,
char const* file,
int line) {
145 auto fmtMsg =
Format(
"%s(%d): [Mochi]%s %s", file, line, channelTag, msg.c_str());
146 printf(
"%s", fmtMsg.c_str());
148#if MOCHI_PLATFORM_WINDOWS && !defined(__UNREAL__)
151 ::OutputDebugStringA(fmtMsg.c_str());
167 std::lock_guard<std::recursive_mutex> lock(log_impl::GetLogMutexRef());
168 auto const& logFn = log_impl::GetLogFnRef();
169 return logFn ? logFn :
LogFn{&log_impl::DefaultLogFn};
171 return LogFn{&log_impl::DefaultLogFn};
177 std::lock_guard<std::recursive_mutex> lock(log_impl::GetLogMutexRef());
178 auto& logFn = log_impl::GetLogFnRef();
179 logFn = fn ? fn :
LogFn{&log_impl::DefaultLogFn};
186 MOCHI_LOG_WARNING(
"Requested LogChannel (%d) is invalid and will be ignored.", (
int)channel);
190 std::lock_guard<std::recursive_mutex> lock(log_impl::GetLogMutexRef());
191 log_impl::GetLogChannelsDisabledArrayRef()[(size_t)channel] = !enable;
201 std::lock_guard<std::recursive_mutex> lock(log_impl::GetLogMutexRef());
202 auto const& isChannelDisabled = log_impl::GetLogChannelsDisabledArrayRef();
203 return !isChannelDisabled[(size_t)channel];
209inline void Log(
LogChannel channel, std::string msg,
char const* file,
int line,
bool newline) {
#define MOCHI_LOG_WARNING(...)
std::function< void(LogChannel, char const *message, char const *file, int line)> LogFn
void Log(LogChannel channel, std::string msg, char const *file, int line, bool newline)
void EnableLogChannel(LogChannel channel, bool enable)
void SetLogCallback(LogFn fn)
bool IsLogChannelEnabled(LogChannel channel)
@ Count
Number of actor type enum values.