mirror of
https://github.com/0TheSpy/Seaside.git
synced 2025-01-09 19:08:48 +08:00
421 lines
13 KiB
C++
421 lines
13 KiB
C++
#ifndef LOGGING_H
|
|
#define LOGGING_H
|
|
|
|
#if !defined(__SPU__)
|
|
|
|
#if defined( COMPILER_MSVC )
|
|
#pragma once
|
|
#endif
|
|
|
|
#include "color.h"
|
|
#include "icommandline.h"
|
|
#include <stdio.h>
|
|
|
|
#if defined( _X360 )
|
|
#include "xbox/xbox_console.h"
|
|
#endif
|
|
|
|
#if defined( _WIN32 ) || (defined(POSIX) && !defined(_GAMECONSOLE))
|
|
#include "win32consoleio.h"
|
|
#endif
|
|
|
|
class CLoggingSystem;
|
|
class CThreadFastMutex;
|
|
|
|
const int MAX_LOGGING_MESSAGE_LENGTH = 2048;
|
|
|
|
const int MAX_LOGGING_IDENTIFIER_LENGTH = 32;
|
|
|
|
const int MAX_LOGGING_CHANNEL_COUNT = 256;
|
|
|
|
const int MAX_LOGGING_TAG_COUNT = 1024;
|
|
|
|
const int MAX_LOGGING_TAG_CHARACTER_COUNT = 8192;
|
|
|
|
const int MAX_LOGGING_LISTENER_COUNT = 16;
|
|
|
|
const Color UNSPECIFIED_LOGGING_COLOR(0, 0, 0, 0);
|
|
|
|
typedef int LoggingChannelID_t;
|
|
|
|
const LoggingChannelID_t INVALID_LOGGING_CHANNEL_ID = -1;
|
|
|
|
enum LoggingSeverity_t
|
|
{
|
|
LS_MESSAGE = 0,
|
|
|
|
LS_WARNING = 1,
|
|
|
|
LS_ASSERT = 2,
|
|
|
|
LS_ERROR = 3,
|
|
|
|
LS_HIGHEST_SEVERITY = 4,
|
|
};
|
|
|
|
enum LoggingResponse_t
|
|
{
|
|
LR_CONTINUE,
|
|
LR_DEBUGGER,
|
|
LR_ABORT,
|
|
};
|
|
|
|
enum LoggingChannelFlags_t
|
|
{
|
|
LCF_CONSOLE_ONLY = 0x00000001,
|
|
|
|
LCF_DO_NOT_ECHO = 0x00000002,
|
|
};
|
|
|
|
typedef void (*RegisterTagsFunc)();
|
|
|
|
struct LoggingContext_t
|
|
{
|
|
LoggingChannelID_t m_ChannelID;
|
|
LoggingChannelFlags_t m_Flags;
|
|
LoggingSeverity_t m_Severity;
|
|
Color m_Color;
|
|
};
|
|
|
|
class ILoggingListener
|
|
{
|
|
public:
|
|
virtual void Log(const LoggingContext_t* pContext, const tchar* pMessage) = 0;
|
|
};
|
|
|
|
class ILoggingResponsePolicy
|
|
{
|
|
public:
|
|
virtual LoggingResponse_t OnLog(const LoggingContext_t* pContext) = 0;
|
|
};
|
|
|
|
class CSimpleLoggingListener : public ILoggingListener
|
|
{
|
|
public:
|
|
CSimpleLoggingListener(bool bQuietPrintf = false, bool bQuietDebugger = false) :
|
|
m_bQuietPrintf(bQuietPrintf),
|
|
m_bQuietDebugger(bQuietDebugger)
|
|
{
|
|
}
|
|
|
|
virtual void Log(const LoggingContext_t* pContext, const tchar* pMessage)
|
|
{
|
|
#ifdef _X360
|
|
if (!m_bQuietDebugger && XBX_IsConsoleConnected())
|
|
{
|
|
XBX_DebugString(XMAKECOLOR(0, 0, 0), pMessage);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
#if !defined( _CERT ) && !defined( DBGFLAG_STRINGS_STRIP )
|
|
if (!m_bQuietPrintf)
|
|
{
|
|
_tprintf(_T("%s"), pMessage);
|
|
}
|
|
#endif
|
|
|
|
#ifdef _WIN32
|
|
if (!m_bQuietDebugger && Plat_IsInDebugSession())
|
|
{
|
|
Plat_DebugString(pMessage);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
bool m_bQuietPrintf;
|
|
bool m_bQuietDebugger;
|
|
};
|
|
|
|
class CSimpleWindowsLoggingListener : public ILoggingListener
|
|
{
|
|
public:
|
|
virtual void Log(const LoggingContext_t* pContext, const tchar* pMessage)
|
|
{
|
|
if (Plat_IsInDebugSession())
|
|
{
|
|
Plat_DebugString(pMessage);
|
|
}
|
|
if (pContext->m_Severity == LS_ERROR)
|
|
{
|
|
if (Plat_IsInDebugSession())
|
|
DebuggerBreak();
|
|
|
|
Plat_MessageBox("Error", pMessage);
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
#if !defined(_GAMECONSOLE)
|
|
class CColorizedLoggingListener : public CSimpleLoggingListener
|
|
{
|
|
public:
|
|
CColorizedLoggingListener(bool bQuietPrintf = false, bool bQuietDebugger = false) : CSimpleLoggingListener(bQuietPrintf, bQuietDebugger)
|
|
{
|
|
InitWin32ConsoleColorContext(&m_ColorContext);
|
|
}
|
|
|
|
virtual void Log(const LoggingContext_t* pContext, const tchar* pMessage)
|
|
{
|
|
if (!m_bQuietPrintf)
|
|
{
|
|
int nPrevColor = -1;
|
|
|
|
if (pContext->m_Color != UNSPECIFIED_LOGGING_COLOR)
|
|
{
|
|
nPrevColor = SetWin32ConsoleColor(&m_ColorContext,
|
|
pContext->m_Color.r(), pContext->m_Color.g(), pContext->m_Color.b(),
|
|
MAX(MAX(pContext->m_Color.r(), pContext->m_Color.g()), pContext->m_Color.b()) > 128);
|
|
}
|
|
|
|
_tprintf(_T("%s"), pMessage);
|
|
|
|
if (nPrevColor >= 0)
|
|
{
|
|
RestoreWin32ConsoleColor(&m_ColorContext, nPrevColor);
|
|
}
|
|
}
|
|
|
|
#ifdef _WIN32
|
|
if (!m_bQuietDebugger && Plat_IsInDebugSession())
|
|
{
|
|
Plat_DebugString(pMessage);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
Win32ConsoleColorContext_t m_ColorContext;
|
|
};
|
|
#endif
|
|
|
|
|
|
class CDefaultLoggingResponsePolicy : public ILoggingResponsePolicy
|
|
{
|
|
public:
|
|
virtual LoggingResponse_t OnLog(const LoggingContext_t* pContext)
|
|
{
|
|
if (pContext->m_Severity == LS_ASSERT && !CommandLine()->FindParm("-noassert"))
|
|
{
|
|
return LR_DEBUGGER;
|
|
}
|
|
else if (pContext->m_Severity == LS_ERROR)
|
|
{
|
|
return LR_ABORT;
|
|
}
|
|
else
|
|
{
|
|
return LR_CONTINUE;
|
|
}
|
|
}
|
|
};
|
|
|
|
class CNonFatalLoggingResponsePolicy : public ILoggingResponsePolicy
|
|
{
|
|
public:
|
|
virtual LoggingResponse_t OnLog(const LoggingContext_t* pContext)
|
|
{
|
|
if ((pContext->m_Severity == LS_ASSERT && !CommandLine()->FindParm("-noassert")) || pContext->m_Severity == LS_ERROR)
|
|
{
|
|
return LR_DEBUGGER;
|
|
}
|
|
else
|
|
{
|
|
return LR_CONTINUE;
|
|
}
|
|
}
|
|
};
|
|
|
|
class CLoggingSystem
|
|
{
|
|
public:
|
|
struct LoggingChannel_t;
|
|
|
|
CLoggingSystem();
|
|
~CLoggingSystem();
|
|
|
|
LoggingChannelID_t RegisterLoggingChannel(const char* pChannelName, RegisterTagsFunc registerTagsFunc, int flags = 0, LoggingSeverity_t minimumSeverity = LS_MESSAGE, Color spewColor = UNSPECIFIED_LOGGING_COLOR);
|
|
|
|
LoggingChannelID_t FindChannel(const char* pChannelName) const;
|
|
|
|
int GetChannelCount() const { return m_nChannelCount; }
|
|
|
|
LoggingChannel_t* GetChannel(LoggingChannelID_t channelID);
|
|
const LoggingChannel_t* GetChannel(LoggingChannelID_t channelID) const;
|
|
|
|
bool HasTag(LoggingChannelID_t channelID, const char* pTag) const { return GetChannel(channelID)->HasTag(pTag); }
|
|
|
|
bool IsValidChannelID(LoggingChannelID_t channelID) const { return (channelID >= 0) && (channelID < m_nChannelCount); }
|
|
|
|
bool IsChannelEnabled(LoggingChannelID_t channelID, LoggingSeverity_t severity) const { return IsValidChannelID(channelID) && GetChannel(channelID)->IsEnabled(severity); }
|
|
|
|
void SetChannelSpewLevel(LoggingChannelID_t channelID, LoggingSeverity_t minimumSeverity);
|
|
void SetChannelSpewLevelByName(const char* pName, LoggingSeverity_t minimumSeverity);
|
|
void SetChannelSpewLevelByTag(const char* pTag, LoggingSeverity_t minimumSeverity);
|
|
void SetGlobalSpewLevel(LoggingSeverity_t minimumSeverity);
|
|
|
|
Color GetChannelColor(LoggingChannelID_t channelID) const { return GetChannel(channelID)->m_SpewColor; }
|
|
void SetChannelColor(LoggingChannelID_t channelID, Color color) { GetChannel(channelID)->m_SpewColor = color; }
|
|
|
|
LoggingChannelFlags_t GetChannelFlags(LoggingChannelID_t channelID) const { return GetChannel(channelID)->m_Flags; }
|
|
void SetChannelFlags(LoggingChannelID_t channelID, LoggingChannelFlags_t flags) { GetChannel(channelID)->m_Flags = flags; }
|
|
|
|
void AddTagToCurrentChannel(const char* pTagName);
|
|
|
|
void PushLoggingState(bool bThreadLocal = false, bool bClearState = true);
|
|
void PopLoggingState(bool bThreadLocal = false);
|
|
|
|
void RegisterLoggingListener(ILoggingListener* pListener);
|
|
|
|
bool IsListenerRegistered(ILoggingListener* pListener);
|
|
|
|
void ResetCurrentLoggingState();
|
|
|
|
void SetLoggingResponsePolicy(ILoggingResponsePolicy* pLoggingResponse);
|
|
|
|
LoggingResponse_t LogDirect(LoggingChannelID_t channelID, LoggingSeverity_t severity, Color color, const tchar* pMessage);
|
|
|
|
struct LoggingTag_t
|
|
{
|
|
const char* m_pTagName;
|
|
LoggingTag_t* m_pNextTag;
|
|
};
|
|
|
|
struct LoggingChannel_t
|
|
{
|
|
bool HasTag(const char* pTag) const
|
|
{
|
|
LoggingTag_t* pCurrentTag = m_pFirstTag;
|
|
while (pCurrentTag != NULL)
|
|
{
|
|
if (stricmp(pCurrentTag->m_pTagName, pTag) == 0)
|
|
{
|
|
return true;
|
|
}
|
|
pCurrentTag = pCurrentTag->m_pNextTag;
|
|
}
|
|
return false;
|
|
}
|
|
bool IsEnabled(LoggingSeverity_t severity) const { return severity >= m_MinimumSeverity; }
|
|
void SetSpewLevel(LoggingSeverity_t severity) { m_MinimumSeverity = severity; }
|
|
|
|
LoggingChannelID_t m_ID;
|
|
LoggingChannelFlags_t m_Flags;
|
|
LoggingSeverity_t m_MinimumSeverity;
|
|
Color m_SpewColor;
|
|
char m_Name[MAX_LOGGING_IDENTIFIER_LENGTH];
|
|
LoggingTag_t* m_pFirstTag;
|
|
};
|
|
|
|
private:
|
|
struct LoggingState_t
|
|
{
|
|
int m_nPreviousStackEntry;
|
|
|
|
int m_nListenerCount;
|
|
ILoggingListener* m_RegisteredListeners[MAX_LOGGING_LISTENER_COUNT];
|
|
|
|
ILoggingResponsePolicy* m_pLoggingResponse;
|
|
};
|
|
|
|
LoggingState_t* GetCurrentState();
|
|
const LoggingState_t* GetCurrentState() const;
|
|
|
|
int FindUnusedStateIndex();
|
|
LoggingTag_t* AllocTag(const char* pTagName);
|
|
|
|
int m_nChannelCount;
|
|
LoggingChannel_t m_RegisteredChannels[MAX_LOGGING_CHANNEL_COUNT];
|
|
|
|
int m_nChannelTagCount;
|
|
LoggingTag_t m_ChannelTags[MAX_LOGGING_TAG_COUNT];
|
|
|
|
int m_nTagNamePoolIndex;
|
|
char m_TagNamePool[MAX_LOGGING_TAG_CHARACTER_COUNT];
|
|
|
|
CThreadFastMutex* m_pStateMutex;
|
|
|
|
int m_nGlobalStateIndex;
|
|
|
|
static const int MAX_LOGGING_STATE_COUNT = 16;
|
|
LoggingState_t m_LoggingStates[MAX_LOGGING_STATE_COUNT];
|
|
|
|
CDefaultLoggingResponsePolicy m_DefaultLoggingResponse;
|
|
|
|
CSimpleLoggingListener m_DefaultLoggingListener;
|
|
|
|
};
|
|
|
|
#ifdef DBGFLAG_STRINGS_STRIP
|
|
#define InternalMsg( Channel, Severity, ... ) do { if ( Severity == LS_ERROR && LoggingSystem_IsChannelEnabled( Channel, Severity ) ) LoggingSystem_Log( Channel, Severity, ##__VA_ARGS__ ); } while( 0 )
|
|
#else
|
|
#define InternalMsg( Channel, Severity, ... ) do { if ( LoggingSystem_IsChannelEnabled( Channel, Severity ) ) LoggingSystem_Log( Channel, Severity, ##__VA_ARGS__ ); } while( 0 )
|
|
#endif
|
|
|
|
#define Log_Msg( Channel, ... ) InternalMsg( Channel, LS_MESSAGE, ##__VA_ARGS__ )
|
|
#define Log_Warning( Channel, ... ) InternalMsg( Channel, LS_WARNING, ##__VA_ARGS__ )
|
|
#define Log_Error( Channel, ... ) InternalMsg( Channel, LS_ERROR, ##__VA_ARGS__ )
|
|
#ifdef DBGFLAG_STRINGS_STRIP
|
|
#define Log_Assert( ... ) LR_CONTINUE
|
|
#else
|
|
#define Log_Assert( Message, ... ) LoggingSystem_LogAssert( Message, ##__VA_ARGS__ )
|
|
#endif
|
|
|
|
|
|
#define DECLARE_LOGGING_CHANNEL( Channel ) extern LoggingChannelID_t Channel
|
|
|
|
#define DEFINE_LOGGING_CHANNEL_NO_TAGS( Channel, ChannelName, ... ) \
|
|
LoggingChannelID_t Channel = LoggingSystem_RegisterLoggingChannel( ChannelName, NULL, ##__VA_ARGS__ )
|
|
|
|
#define BEGIN_DEFINE_LOGGING_CHANNEL( Channel, ChannelName, ... ) \
|
|
static void Register_##Channel##_Tags(); \
|
|
LoggingChannelID_t Channel = LoggingSystem_RegisterLoggingChannel( ChannelName, Register_##Channel##_Tags, ##__VA_ARGS__ ); \
|
|
void Register_##Channel##_Tags() \
|
|
{
|
|
|
|
#define ADD_LOGGING_CHANNEL_TAG( Tag ) LoggingSystem_AddTagToCurrentChannel( Tag )
|
|
|
|
#define END_DEFINE_LOGGING_CHANNEL() \
|
|
}
|
|
|
|
PLATFORM_INTERFACE LoggingChannelID_t LoggingSystem_RegisterLoggingChannel(const char* pName, RegisterTagsFunc registerTagsFunc, int flags = 0, LoggingSeverity_t severity = LS_MESSAGE, Color color = UNSPECIFIED_LOGGING_COLOR);
|
|
|
|
PLATFORM_INTERFACE void LoggingSystem_RegisterLoggingListener(ILoggingListener* pListener);
|
|
PLATFORM_INTERFACE void LoggingSystem_UnregisterLoggingListener(ILoggingListener* pListener);
|
|
PLATFORM_INTERFACE void LoggingSystem_ResetCurrentLoggingState();
|
|
PLATFORM_INTERFACE void LoggingSystem_SetLoggingResponsePolicy(ILoggingResponsePolicy* pResponsePolicy);
|
|
PLATFORM_INTERFACE void LoggingSystem_PushLoggingState(bool bThreadLocal = false, bool bClearState = true);
|
|
PLATFORM_INTERFACE void LoggingSystem_PopLoggingState(bool bThreadLocal = false);
|
|
|
|
PLATFORM_INTERFACE void LoggingSystem_AddTagToCurrentChannel(const char* pTagName);
|
|
|
|
PLATFORM_INTERFACE LoggingChannelID_t LoggingSystem_FindChannel(const char* pChannelName);
|
|
PLATFORM_INTERFACE int LoggingSystem_GetChannelCount();
|
|
PLATFORM_INTERFACE LoggingChannelID_t LoggingSystem_GetFirstChannelID();
|
|
PLATFORM_INTERFACE LoggingChannelID_t LoggingSystem_GetNextChannelID(LoggingChannelID_t channelID);
|
|
PLATFORM_INTERFACE const CLoggingSystem::LoggingChannel_t* LoggingSystem_GetChannel(LoggingChannelID_t channelID);
|
|
|
|
PLATFORM_INTERFACE bool LoggingSystem_HasTag(LoggingChannelID_t channelID, const char* pTag);
|
|
|
|
PLATFORM_INTERFACE bool LoggingSystem_IsChannelEnabled(LoggingChannelID_t channelID, LoggingSeverity_t severity);
|
|
PLATFORM_INTERFACE void LoggingSystem_SetChannelSpewLevel(LoggingChannelID_t channelID, LoggingSeverity_t minimumSeverity);
|
|
PLATFORM_INTERFACE void LoggingSystem_SetChannelSpewLevelByName(const char* pName, LoggingSeverity_t minimumSeverity);
|
|
PLATFORM_INTERFACE void LoggingSystem_SetChannelSpewLevelByTag(const char* pTag, LoggingSeverity_t minimumSeverity);
|
|
PLATFORM_INTERFACE void LoggingSystem_SetGlobalSpewLevel(LoggingSeverity_t minimumSeverity);
|
|
|
|
PLATFORM_INTERFACE int32 LoggingSystem_GetChannelColor(LoggingChannelID_t channelID);
|
|
PLATFORM_INTERFACE void LoggingSystem_SetChannelColor(LoggingChannelID_t channelID, int color);
|
|
|
|
PLATFORM_INTERFACE LoggingChannelFlags_t LoggingSystem_GetChannelFlags(LoggingChannelID_t channelID);
|
|
PLATFORM_INTERFACE void LoggingSystem_SetChannelFlags(LoggingChannelID_t channelID, LoggingChannelFlags_t flags);
|
|
|
|
PLATFORM_INTERFACE LoggingResponse_t LoggingSystem_Log(LoggingChannelID_t channelID, LoggingSeverity_t severity, PRINTF_FORMAT_STRING const char* pMessageFormat, ...) FMTFUNCTION(3, 4);
|
|
PLATFORM_OVERLOAD LoggingResponse_t LoggingSystem_Log(LoggingChannelID_t channelID, LoggingSeverity_t severity, Color spewColor, PRINTF_FORMAT_STRING const char* pMessageFormat, ...) FMTFUNCTION(4, 5);
|
|
|
|
PLATFORM_INTERFACE LoggingResponse_t LoggingSystem_LogDirect(LoggingChannelID_t channelID, LoggingSeverity_t severity, Color spewColor, const char* pMessage);
|
|
PLATFORM_INTERFACE LoggingResponse_t LoggingSystem_LogAssert(PRINTF_FORMAT_STRING const char* pMessageFormat, ...) FMTFUNCTION(1, 2);
|
|
|
|
#endif
|
|
|
|
#endif |