Former-commit-id: ddfe1d92246d6717e4e4ec2e982eddfa1b74ed50
This commit is contained in:
Lynix 2015-12-07 19:55:05 +01:00
commit 6284503da6
12 changed files with 405 additions and 156 deletions

View File

@ -0,0 +1,9 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
/*!
* \class Nz::AbstractLogger
* \brief Logger interface
*/

View File

@ -0,0 +1,31 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_ABSTRACTLOGGER_HPP
#define NAZARA_ABSTRACTLOGGER_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Enums.hpp>
#include <Nazara/Core/String.hpp>
namespace Nz
{
class NAZARA_CORE_API AbstractLogger
{
public:
AbstractLogger() = default;
virtual ~AbstractLogger();
virtual void EnableStdReplication(bool enable) = 0;
virtual bool IsStdReplicationEnabled() = 0;
virtual void Write(const String& string) = 0;
virtual void WriteError(ErrorType type, const String& error, unsigned int line = 0, const char* file = nullptr, const char* function = nullptr);
};
}
#endif // NAZARA_ABSTRACTLOGGER_HPP

View File

@ -0,0 +1,46 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_FILELOGGER_HPP
#define NAZARA_FILELOGGER_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/AbstractLogger.hpp>
#include <Nazara/Core/File.hpp>
#include <Nazara/Core/StdLogger.hpp>
namespace Nz
{
class NAZARA_CORE_API FileLogger : public AbstractLogger
{
public:
FileLogger(const String& logPath = "NazaraLog.log");
FileLogger(const FileLogger&) = default;
FileLogger(FileLogger&&) = default;
~FileLogger();
void EnableTimeLogging(bool enable);
void EnableStdReplication(bool enable) override;
bool IsStdReplicationEnabled() override;
bool IsTimeLoggingEnabled();
void Write(const String& string) override;
void WriteError(ErrorType type, const String& error, unsigned int line = 0, const char* file = nullptr, const char* function = nullptr) override;
FileLogger& operator=(const FileLogger&) = default;
FileLogger& operator=(FileLogger&&) = default;
private:
File m_outputFile;
StdLogger m_stdLogger;
bool m_forceStdOutput;
bool m_stdReplicationEnabled;
bool m_timeLoggingEnabled;
};
}
#endif // NAZARA_FILELOGGER_HPP

View File

@ -9,7 +9,9 @@
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Signal.hpp>
#include <Nazara/Core/String.hpp>
#include <memory>
#if NAZARA_CORE_THREADSAFE && NAZARA_THREADSAFETY_LOG
#include <Nazara/Core/ThreadSafety.hpp>
@ -23,48 +25,37 @@
#define NazaraDebug(txt)
#endif
#define NazaraLog Nz::Log::Instance()
#define NazaraNotice(txt) NazaraLog->Write(txt)
#define NazaraNotice(txt) Nz::Log::Write(txt)
namespace Nz
{
class File;
class AbstractLogger;
class NAZARA_CORE_API Log
{
friend class Core;
public:
void Enable(bool enable);
void EnableAppend(bool enable);
void EnableDateTime(bool enable);
static void Enable(bool enable);
String GetFile() const;
static AbstractLogger* GetLogger();
bool IsEnabled() const;
static bool IsEnabled();
void SetFile(const String& filePath);
static void SetLogger(AbstractLogger* logger);
void Write(const String& string);
void WriteError(ErrorType type, const String& error);
void WriteError(ErrorType type, const String& error, unsigned int line, const String& file, const String& func);
static void Write(const String& string);
static void WriteError(ErrorType type, const String& error, unsigned int line = 0, const char* file = nullptr, const char* function = nullptr);
static Log* Instance();
NazaraStaticSignal(OnLogWrite, const String& /*string*/);
NazaraStaticSignal(OnLogWriteError, ErrorType /*type*/, const String& /*error*/, unsigned int /*line*/, const char* /*file*/, const char* /*function*/);
private:
Log();
Log(const Log&) = delete;
Log(Log&&) = delete;
~Log();
static bool Initialize();
static void Uninitialize();
Log& operator=(const Log&) = delete;
Log& operator=(Log&&) = delete;
NazaraMutexAttrib(m_mutex, mutable)
String m_filePath;
File* m_file;
bool m_append;
bool m_enabled;
bool m_writeTime;
static AbstractLogger* s_logger;
static bool s_enabled;
};
}

View File

@ -11,8 +11,12 @@
#include <memory>
#include <vector>
#define NazaraSignal(SignalName, ...) using SignalName ## Type = Nz::Signal<__VA_ARGS__>; \
mutable SignalName ## Type SignalName
#define NazaraDetailSignal(Keyword, SignalName, ...) using SignalName ## Type = Nz::Signal<__VA_ARGS__>; \
Keyword SignalName ## Type SignalName
#define NazaraSignal(SignalName, ...) NazaraDetailSignal(mutable, SignalName, __VA_ARGS__)
#define NazaraStaticSignal(SignalName, ...) NazaraDetailSignal(static, SignalName, __VA_ARGS__)
#define NazaraStaticSignalImpl(Class, SignalName) Class :: SignalName ## Type Class :: SignalName
#define NazaraSlotType(Class, SignalName) Class::SignalName ## Type::ConnectionGuard
#define NazaraSlot(Class, SignalName, SlotName) NazaraSlotType(Class, SignalName) SlotName

View File

@ -0,0 +1,35 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_STDLOGGER_HPP
#define NAZARA_STDLOGGER_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/AbstractLogger.hpp>
namespace Nz
{
class NAZARA_CORE_API StdLogger : public AbstractLogger
{
public:
StdLogger() = default;
StdLogger(const StdLogger&) = default;
StdLogger(StdLogger&&) = default;
~StdLogger();
void EnableStdReplication(bool enable) override;
bool IsStdReplicationEnabled() override;
void Write(const String& string) override;
void WriteError(ErrorType type, const String& error, unsigned int line = 0, const char* file = nullptr, const char* function = nullptr) override;
StdLogger& operator=(const StdLogger&) = default;
StdLogger& operator=(StdLogger&&) = default;
};
}
#endif // NAZARA_STDLOGGER_HPP

View File

@ -0,0 +1,33 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/AbstractLogger.hpp>
#include <Nazara/Core/StringStream.hpp>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
namespace
{
const char* errorType[] = {
"Assert failed: ", // ErrorType_AssertFailed
"Internal error: ", // ErrorType_Internal
"Error: ", // ErrorType_Normal
"Warning: " // ErrorType_Warning
};
static_assert(sizeof(errorType) / sizeof(const char*) == ErrorType_Max + 1, "Error type array is incomplete");
}
AbstractLogger::~AbstractLogger() = default;
void AbstractLogger::WriteError(ErrorType type, const String& error, unsigned int line, const char* file, const char* function)
{
StringStream stream;
stream << errorType[type] << error;
if (line != 0 && file && function)
stream << " (" << file << ':' << line << ": " << function << ')';
}
}

View File

@ -23,6 +23,8 @@ namespace Nz
s_moduleReferenceCounter++;
Log::Initialize();
NazaraNotice("Initialized: Core");
return true;
}
@ -47,6 +49,7 @@ namespace Nz
s_moduleReferenceCounter = 0;
HardwareInfo::Uninitialize();
Log::Uninitialize();
PluginManager::Uninitialize();
TaskScheduler::Uninitialize();

View File

@ -85,7 +85,7 @@ namespace Nz
void Error::Trigger(ErrorType type, const String& error)
{
if (type == ErrorType_AssertFailed || (s_flags & ErrorFlag_Silent) == 0 || (s_flags & ErrorFlag_SilentDisabled) != 0)
NazaraLog->WriteError(type, error);
Log::WriteError(type, error);
s_lastError = error;
s_lastErrorFile = "";
@ -105,7 +105,7 @@ namespace Nz
void Error::Trigger(ErrorType type, const String& error, unsigned int line, const char* file, const char* function)
{
if (type == ErrorType_AssertFailed || (s_flags & ErrorFlag_Silent) == 0 || (s_flags & ErrorFlag_SilentDisabled) != 0)
NazaraLog->WriteError(type, error, line, file, function);
Log::WriteError(type, error, line, file, function);
s_lastError = error;
s_lastErrorFile = file;

View File

@ -0,0 +1,101 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/FileLogger.hpp>
#include <Nazara/Core/CallOnExit.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/StringStream.hpp>
#include <array>
#include <ctime>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
FileLogger::FileLogger(const String& logPath) :
m_outputFile(logPath),
m_forceStdOutput(false),
m_stdReplicationEnabled(true),
m_timeLoggingEnabled(true)
{
}
FileLogger::~FileLogger() = default;
void FileLogger::EnableTimeLogging(bool enable)
{
m_timeLoggingEnabled = enable;
}
void FileLogger::EnableStdReplication(bool enable)
{
m_stdReplicationEnabled = enable;
}
bool FileLogger::IsStdReplicationEnabled()
{
return m_stdReplicationEnabled;
}
bool FileLogger::IsTimeLoggingEnabled()
{
return m_timeLoggingEnabled;
}
void FileLogger::Write(const String& string)
{
if (m_forceStdOutput || m_stdReplicationEnabled)
{
m_stdLogger.Write(string);
if (m_forceStdOutput)
return;
}
// To prevent infinite loops
m_forceStdOutput = true;
CallOnExit resetOnExit([this] ()
{
m_forceStdOutput = false;
});
if (!m_outputFile.IsOpen())
{
if (!m_outputFile.Open(OpenMode_Text | OpenMode_Truncate | OpenMode_WriteOnly))
{
NazaraError("Failed to open output file");
return;
}
}
// Apply some processing before writing
StringStream stream;
if (m_timeLoggingEnabled)
{
std::array<char, 24> buffer;
time_t currentTime = std::time(nullptr);
std::strftime(buffer.data(), 24, "%d/%m/%Y - %H:%M:%S: ", std::localtime(&currentTime));
stream << buffer.data();
}
stream << string << '\n';
m_outputFile.Write(stream);
}
void FileLogger::WriteError(ErrorType type, const String& error, unsigned int line, const char* file, const char* function)
{
if (m_forceStdOutput || m_stdReplicationEnabled)
{
m_stdLogger.WriteError(type, error, line, file, function);
if (m_forceStdOutput)
return;
}
AbstractLogger::WriteError(type, error, line, file, function);
m_outputFile.Flush();
}
}

View File

@ -3,163 +3,73 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Log.hpp>
#include <Nazara/Core/Config.hpp>
#include <Nazara/Core/File.hpp>
#include <Nazara/Core/StringStream.hpp>
#include <ctime>
#include <cstring>
#if NAZARA_CORE_DUPLICATE_LOG_TO_COUT
#include <cstdio>
#endif
#if NAZARA_CORE_THREADSAFE && NAZARA_THREADSAFETY_LOG
#include <Nazara/Core/ThreadSafety.hpp>
#else
#include <Nazara/Core/ThreadSafetyOff.hpp>
#endif
#include <Nazara/Core/AbstractLogger.hpp>
#include <Nazara/Core/FileLogger.hpp>
#include <Nazara/Core/StdLogger.hpp>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
namespace
{
const char* errorType[] = {
"Assert failed: ", // ErrorType_AssertFailed
"Internal error: ", // ErrorType_Internal
"Error: ", // ErrorType_Normal
"Warning: " // ErrorType_Warning
};
static_assert(sizeof(errorType)/sizeof(const char*) == ErrorType_Max+1, "Error type array is incomplete");
}
Log::Log() :
m_filePath("NazaraLog.log"),
m_file(nullptr),
m_append(false),
m_enabled(true),
m_writeTime(true)
{
}
Log::~Log()
{
delete m_file;
StdLogger s_stdLogger;
}
void Log::Enable(bool enable)
{
NazaraLock(m_mutex)
if (m_enabled == enable)
return;
m_enabled = enable;
if (!m_enabled && m_file)
{
delete m_file;
m_file = nullptr;
}
s_enabled = enable;
}
void Log::EnableAppend(bool enable)
AbstractLogger* Log::GetLogger()
{
NazaraLock(m_mutex)
m_append = enable;
if (!m_append && m_file)
{
m_file->Delete();
m_file = nullptr;
}
return s_logger;
}
void Log::EnableDateTime(bool enable)
bool Log::IsEnabled()
{
NazaraLock(m_mutex)
m_writeTime = enable;
return s_enabled;
}
String Log::GetFile() const
void Log::SetLogger(AbstractLogger* logger)
{
NazaraLock(m_mutex)
if (s_logger != &s_stdLogger)
delete s_logger;
if (m_file)
return m_file->GetPath();
else
return String();
}
bool Log::IsEnabled() const
{
NazaraLock(m_mutex)
return m_enabled;
}
void Log::SetFile(const String& filePath)
{
NazaraLock(m_mutex)
m_filePath = filePath;
if (m_file)
m_file->SetFile(filePath);
s_logger = logger;
if (!s_logger)
s_logger = &s_stdLogger;
}
void Log::Write(const String& string)
{
NazaraLock(m_mutex)
if (s_enabled)
s_logger->Write(string);
if (m_enabled)
OnLogWrite(string);
}
void Log::WriteError(ErrorType type, const String& error, unsigned int line, const char* file, const char* function)
{
if (!m_file)
m_file = new File(m_filePath, OpenMode_Text | OpenMode_WriteOnly | ((m_append) ? OpenMode_Append : OpenMode_Truncate));
if (s_enabled)
s_logger->WriteError(type, error, line, file, function);
String line;
OnLogWriteError(type, error, line, file, function);
}
if (m_writeTime)
bool Log::Initialize()
{
line.Reserve(23 + string.GetSize() + 1);
line.Set(23, '\0'); // Buffer non-initialisé
time_t currentTime = std::time(nullptr);
std::strftime(&line[0], 24, "%d/%m/%Y - %H:%M:%S: ", std::localtime(&currentTime));
}
else
line.Reserve(string.GetSize() + 1);
line += string;
line += '\n';
if (m_file->IsOpen())
m_file->Write(line);
#if NAZARA_CORE_DUPLICATE_LOG_TO_COUT
std::fputs(line.GetConstBuffer(), stdout);
#endif
}
SetLogger(new FileLogger());
return true;
}
void Log::WriteError(ErrorType type, const String& error)
void Log::Uninitialize()
{
StringStream stream;
stream << errorType[type] << error;
Write(stream);
SetLogger(nullptr);
}
void Log::WriteError(ErrorType type, const String& error, unsigned int line, const String& file, const String& func)
{
StringStream stream;
stream << errorType[type] << error << " (" << file << ':' << line << ": " << func << ')';
Write(stream);
}
NazaraStaticSignalImpl(Log, OnLogWrite);
NazaraStaticSignalImpl(Log, OnLogWriteError);
Log* Log::Instance()
{
static Log log;
return &log;
}
AbstractLogger* Log::s_logger = &s_stdLogger;
bool Log::s_enabled = true;
}

View File

@ -0,0 +1,86 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/StdLogger.hpp>
#include <cstdio>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
namespace
{
const char* errorType[] = {
"Assert failed", // ErrorType_AssertFailed
"Internal error", // ErrorType_Internal
"Error", // ErrorType_Normal
"Warning" // ErrorType_Warning
};
static_assert(sizeof(errorType) / sizeof(const char*) == ErrorType_Max + 1, "Error type array is incomplete");
}
/*!
* \class Nz::StdLogger
* \brief Logger writing to standard output (stdout, stderr)
*/
StdLogger::~StdLogger() = default;
/*!
* \brief Enable replication to standard output
*
* Does nothing, as the std logger always write to standard output
*/
void StdLogger::EnableStdReplication(bool enable)
{
NazaraUnused(enable);
// We always replicate to std, that's our purpose
}
/*!
* \brief Get the standard output replication status
*
* Always returns true
*/
bool StdLogger::IsStdReplicationEnabled()
{
return true;
}
/*!
* Write to the console
* \param string The log to write to the console
*
* \see WriteError
*/
void StdLogger::Write(const String& string)
{
fputs(string.GetConstBuffer(), stdout);
fputc('\n', stdout);
}
/*!
* Write an error to the console
* \param type The error type
* \param error The error text
* \param line The line the error occurred
* \param file The file the error occurred
* \param function The function the error occurred
*
* \see Write
*/
void StdLogger::WriteError(ErrorType type, const String& error, unsigned int line, const char* file, const char* function)
{
fprintf(stderr, "%s: %s", errorType[type], error.GetConstBuffer());
if (line != 0 && file && function)
fprintf(stderr, " (in %s at %s:%d)", function, file, line);
fputc('\n', stderr);
}
}