1
0

Added forgoten files

This commit is contained in:
Tycho 2014-08-10 19:44:49 +01:00
parent 806d0936dc
commit bf0050e066
4 changed files with 457 additions and 0 deletions

236
src/Listeners.cpp Normal file
View File

@ -0,0 +1,236 @@
#include "Globals.h"
#include "Listeners.h"
#if defined(_WIN32)
#include <io.h> // Needed for _isatty(), not available on Linux
#elif defined(__linux) && !defined(ANDROID_NDK)
#include <unistd.h> // Needed for isatty() on Linux
#elif defined(ANDROID_NDK)
#include <android/log.h>
#endif
namespace Logger
{
#if defined(_WIN32) || (defined (__linux) && !defined(ANDROID_NDK))
class cColouredConsoleListener
: public cLoggerListener
{
virtual void SetLogColour(eLogLevel a_LogLevel) = 0;
virtual void SetDefaultLogColour() = 0;
virtual void Log(AString a_Message, eLogLevel a_LogLevel) override
{
SetLogColour(a_LogLevel);
puts(a_Message.c_str());
SetDefaultLogColour();
}
};
#endif
#ifdef _WIN32
class cWindowsConsoleListener
: public cColouredConsoleListener
{
public:
cWindowsConsoleListener(HANDLE a_Console, WORD a_DefaultConsoleAttrib) :
m_Console(a_Console),
m_DefaultConsoleAttrib(a_DefaultConsoleAttrib)
{
}
#ifdef DEBUG
virtual void Log(AString a_Message, eLogLevel a_LogLevel) override
{
cColouredConsoleListener::Log(a_Message, a_LogLevel);
// In a Windows Debug build, output the log to debug console as well:
OutputDebugStringA(a_Message.c_str());
}
#endif // _WIN32
virtual void SetLogColour(eLogLevel a_LogLevel) override
{
// by default, gray on black
WORD Attrib = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
switch (a_LogLevel)
{
case llRegular:
// Gray on black
Attrib = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED;
break;
case llInfo:
// Yellow on black
Attrib = FOREGROUND_GREEN | ;
break;
case llWarning:
// Red on black
Attrib = FOREGROUND_RED | FOREGROUND_INTENSITY;
break;
case llError:
// Black on red
Attrib = BACKGROUND_RED | BACKGROUND_INTENSITY;
break;
}
SetConsoleTextAttribute(m_Console, Attrib);
}
virtual void SetDefaultLogColour() override
{
SetConsoleTextAttribute(m_Console, m_DefaultConsoleAttrib);
}
private:
HANDLE m_Console;
WORD m_DefaultConsoleAttrib;
};
#elif defined (__linux) && !defined(ANDROID_NDK)
class cLinuxConsoleListener
: public cColouredConsoleListener
{
public:
virtual void SetLogColour(eLogLevel a_LogLevel) override
{
switch (a_LogLevel)
{
case llRegular:
// Whatever the console default is
printf("\x1b[0m");
break;
case llInfo:
// Yellow on black
printf("\x1b[33;1m");
break;
case llWarning:
// Red on black
printf("\x1b[31;1m");
break;
case llError:
// Yellow on red
printf("\x1b[1;33;41;1m");
break;
}
}
virtual void SetDefaultLogColour() override
{
// Whatever the console default is
printf("\x1b[0m");
}
};
#elif defined(ANDROID_NDK)
class cAndroidConsoleListener
: public cLoggerListener
{
public:
virtual void Log(AString a_Message, eLogLevel a_LogLevel) override
{
android_LogPriority AndroidLogLevel;
switch (a_LogLevel)
{
case llRegular:
AndroidLogLevel = ANDROID_LOG_VERBOSE;
break;
case llInfo:
AndroidLogLevel = ANDROID_LOG_INFO;
break;
case llWarning:
AndroidLogLevel = ANDROID_LOG_WARNING;
break;
case llError:
AndroidLogLevel = ANDROID_LOG_ERROR;
break;
}
__android_log_print(AndroidLogLevel, "MCServer", "%s", a_Message.c_str());
}
};
#endif
class cVanillaCPPConsoleListener
: public cLoggerListener
{
public:
virtual void Log(AString a_Message, eLogLevel a_LogLevel) override
{
AString LogLevelString;
switch (a_LogLevel)
{
case llRegular:
LogLevelString = "Log";
break;
case llInfo:
LogLevelString = "Info";
break;
case llWarning:
LogLevelString = "Warning";
break;
case llError:
LogLevelString = "Error";
break;
}
printf("%s: %s", LogLevelString.c_str(), a_Message.c_str());
}
};
cLoggerListener * MakeConsoleListener()
{
#ifdef _WIN32
// See whether we are writing to a console the default console attrib:
bool ShouldColorOutput = (_isatty(_fileno(stdin)) != 0);
if (ShouldColorOutput)
{
CONSOLE_SCREEN_BUFFER_INFO sbi;
HANDLE Console = getStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(Console, &sbi);
WORD DefaultConsoleAttrib = sbi.wAttributes;
return new cWindowsConsoleListener(Console, DefaultConsoleAttrib);
} else {
return new cVanillaCPPConsoleListener();
}
#elif defined (__linux) && !defined(ANDROID_NDK)
// TODO: lookup terminal in terminfo
if (isatty(fileno(stdout)))
{
return new cLinuxConsoleListener();
} else {
return new cVanillaCPPConsoleListener();
}
#else
return new cVanillaCPPConsoleListener();
#endif
}
cFileListener::cFileListener()
{
cFile::CreateFolder(FILE_IO_PREFIX + AString("logs"));
AString FileName;
FileName = Printf("%s%sLOG_%d.txt", FILE_IO_PREFIX, "logs/", (int)time(NULL));
m_File.Open(FileName, cFile::fmAppend);
}
void cFileListener::Log(AString a_Message, eLogLevel a_LogLevel)
{
AString LogLevelString;
switch (a_LogLevel)
{
case llRegular:
LogLevelString = "Log";
break;
case llInfo:
LogLevelString = "Info";
break;
case llWarning:
LogLevelString = "Warning";
break;
case llError:
LogLevelString = "Error";
break;
}
m_File.Printf("%s: %s", LogLevelString.c_str(), a_Message.c_str());
}
}

21
src/Listeners.h Normal file
View File

@ -0,0 +1,21 @@
#include "LogDispacher.h"
namespace Logger
{
class cFileListener
: public cLoggerListener
{
public:
cFileListener();
cFileListener(AString a_Filename);
virtual void Log(AString a_Message, eLogLevel a_LogLevel) override;
private:
cFile m_File;
};
cLoggerListener * MakeConsoleListener();
}

115
src/LogDispacher.cpp Normal file
View File

@ -0,0 +1,115 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "Log.h"
#include "OSSupport/IsThread.h"
namespace Logger
{
cLogDispacher & GetInstance(void)
{
static cLogDispacher Instance;
return Instance;
}
void InitiateMultithreading()
{
GetInstance();
}
void cLogDispacher::LogSimple(AString a_Message, eLogLevel a_LogLevel)
{
time_t rawtime;
time ( &rawtime);
struct tm* timeinfo;
#ifdef _MSC_VER
struct tm timeinforeal;
timeinfo = &timeinforeal;
localtime_s(timeinfo, &rawtime);
#else
timeinfo = localtime( &rawtime);
#endif
AString Line;
#ifdef _DEBUG
Printf(Line, "[%04lx|%02d:%02d:%02d] %s\n", cIsThread::GetCurrentID(), timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, a_Message.c_str());
#else
Printf(Line, "[%02d:%02d:%02d] %s\n", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec, a_Message.c_str());
#endif
cCSLock Lock(m_CriticalSection);
for(size_t i = 0; i < m_LogListeners.size(); i++)
{
m_LogListeners[i]->Log(a_Message, a_LogLevel);
}
}
void cLogDispacher::Log(const char * a_Format, eLogLevel a_LogLevel, va_list a_ArgList)
{
AString Message;
AppendVPrintf(Message, a_Format, a_ArgList);
LogSimple(Message, a_LogLevel);
}
void cLogDispacher::AttachListener(Logger::cLoggerListener * a_Listener)
{
cCSLock Lock(m_CriticalSection);
m_LogListeners.push_back(a_Listener);
}
void cLogDispacher::DetachListener(Logger::cLoggerListener * a_Listener)
{
cCSLock Lock(m_CriticalSection);
m_LogListeners.erase(std::remove(m_LogListeners.begin(), m_LogListeners.end(), a_Listener));
}
};
////////////////////////////////////////////////////////////////////////////////
// Global functions
void LOG(const char* a_Format, ...)
{
va_list argList;
va_start(argList, a_Format);
Logger::GetInstance().Log(a_Format, Logger::llRegular, argList);
va_end(argList);
}
void LOGINFO(const char* a_Format, ...)
{
va_list argList;
va_start(argList, a_Format);
Logger::GetInstance().Log( a_Format, Logger::llInfo, argList);
va_end(argList);
}
void LOGWARN(const char* a_Format, ...)
{
va_list argList;
va_start(argList, a_Format);
Logger::GetInstance().Log( a_Format, Logger::llWarning, argList);
va_end(argList);
}
void LOGERROR(const char* a_Format, ...)
{
va_list argList;
va_start(argList, a_Format);
Logger::GetInstance().Log( a_Format, Logger::llError, argList);
va_end(argList);
}

85
src/LogDispacher.h Normal file
View File

@ -0,0 +1,85 @@
#pragma once
class cLog;
namespace Logger
{
enum eLogLevel
{
llRegular,
llInfo,
llWarning,
llError,
};
class cLogDispacher;
// Must be called before calling GetInstance in a multithreaded context
void InitiateMultithreading();
cLogDispacher & GetInstance(void);
class cLoggerListener
{
public:
virtual void Log(AString a_Message, eLogLevel a_LogLevel) = 0;
virtual ~cLoggerListener(){}
};
class cLogDispacher
{
public:
void Log (const char * a_Format, Logger::eLogLevel a_LogLevel, va_list a_ArgList) FORMATSTRING(2, 0);
/** Logs the simple text message at the specified log level. */
void LogSimple(AString a_Message, Logger::eLogLevel a_LogLevel = Logger::llRegular);
void AttachListener(Logger::cLoggerListener * a_Listener);
void DetachListener(Logger::cLoggerListener * a_Listener);
private:
cCriticalSection m_CriticalSection;
std::vector<Logger::cLoggerListener *> m_LogListeners;
};
}
extern void LOG(const char* a_Format, ...) FORMATSTRING(1, 2);
extern void LOGINFO(const char* a_Format, ...) FORMATSTRING(1, 2);
extern void LOGWARN(const char* a_Format, ...) FORMATSTRING(1, 2);
extern void LOGERROR(const char* a_Format, ...) FORMATSTRING(1, 2);
// In debug builds, translate LOGD to LOG, otherwise leave it out altogether:
#ifdef _DEBUG
#define LOGD LOG
#else
#define LOGD(...)
#endif // _DEBUG
#define LOGWARNING LOGWARN