Seaside/SpyCustom/logging.h
2021-06-16 16:11:47 +03:00

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