add LogFormater & LogProvider & LogBuffer

This commit is contained in:
Nomango 2020-07-17 12:23:18 +08:00
parent 83b8e9013d
commit c19b5e224f
18 changed files with 591 additions and 371 deletions

View File

@ -37,7 +37,7 @@ AudioModule::~AudioModule() {}
void AudioModule::SetupModule() void AudioModule::SetupModule()
{ {
KGE_SYS_LOG("Creating audio resources"); KGE_DEBUG_LOGF("Creating audio resources");
HRESULT hr = dlls::MediaFoundation::Get().MFStartup(MF_VERSION, MFSTARTUP_FULL); HRESULT hr = dlls::MediaFoundation::Get().MFStartup(MF_VERSION, MFSTARTUP_FULL);
@ -56,7 +56,7 @@ void AudioModule::SetupModule()
void AudioModule::DestroyModule() void AudioModule::DestroyModule()
{ {
KGE_SYS_LOG("Destroying audio resources"); KGE_DEBUG_LOGF("Destroying audio resources");
if (mastering_voice_) if (mastering_voice_)
{ {
@ -103,7 +103,7 @@ bool AudioModule::CreateSound(Sound& sound, const Transcoder::Buffer& buffer)
if (FAILED(hr)) if (FAILED(hr))
{ {
KGE_ERROR("Create IXAudio2SourceVoice failed with HRESULT of %08X", hr); KGE_ERRORF("Create IXAudio2SourceVoice failed with HRESULT of %08X", hr);
return false; return false;
} }
return true; return true;

View File

@ -65,7 +65,7 @@ bool Sound::Load(const String& file_path)
{ {
if (!FileSystem::GetInstance().IsFileExists(file_path)) if (!FileSystem::GetInstance().IsFileExists(file_path))
{ {
KGE_WARN("Media file '%s' not found", file_path.c_str()); KGE_WARNF("Media file '%s' not found", file_path.c_str());
return false; return false;
} }
@ -79,7 +79,7 @@ bool Sound::Load(const String& file_path)
HRESULT hr = transcoder_.LoadMediaFile(full_path); HRESULT hr = transcoder_.LoadMediaFile(full_path);
if (FAILED(hr)) if (FAILED(hr))
{ {
KGE_ERROR("Load media file failed with HRESULT of %08X", hr); KGE_ERRORF("Load media file failed with HRESULT of %08X", hr);
return false; return false;
} }
@ -103,7 +103,7 @@ bool Sound::Load(const Resource& res)
HRESULT hr = transcoder_.LoadMediaResource(res); HRESULT hr = transcoder_.LoadMediaResource(res);
if (FAILED(hr)) if (FAILED(hr))
{ {
KGE_ERROR("Load media resource failed with HRESULT of %08X", hr); KGE_ERRORF("Load media resource failed with HRESULT of %08X", hr);
return false; return false;
} }
@ -126,7 +126,7 @@ void Sound::Play(int loop_count)
{ {
if (!opened_) if (!opened_)
{ {
KGE_ERROR("Sound must be opened first!"); KGE_ERRORF("Sound must be opened first!");
return; return;
} }
@ -157,7 +157,7 @@ void Sound::Play(int loop_count)
if (FAILED(hr)) if (FAILED(hr))
{ {
KGE_ERROR("Submitting source buffer failed with HRESULT of %08X", hr); KGE_ERRORF("Submitting source buffer failed with HRESULT of %08X", hr);
} }
playing_ = SUCCEEDED(hr); playing_ = SUCCEEDED(hr);

View File

@ -105,7 +105,7 @@ HRESULT Transcoder::LoadMediaResource(const Resource& res)
if (stream == nullptr) if (stream == nullptr)
{ {
KGE_ERROR("SHCreateMemStream failed"); KGE_ERRORF("SHCreateMemStream failed");
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
} }
@ -198,7 +198,7 @@ HRESULT Transcoder::ReadSource(IMFSourceReader* reader)
if (data == nullptr) if (data == nullptr)
{ {
KGE_ERROR("Low memory"); KGE_ERRORF("Low memory");
hr = E_OUTOFMEMORY; hr = E_OUTOFMEMORY;
} }
else else

View File

@ -298,7 +298,7 @@ void HttpModule::Perform(HttpRequestPtr request, HttpResponsePtr response)
ok = Curl::DeleteRequest(this, headers, url, &response_code, &response_data, &response_header, error_message); ok = Curl::DeleteRequest(this, headers, url, &response_code, &response_data, &response_header, error_message);
break; break;
default: default:
KGE_ERROR("HttpModule: unknown request type, only GET, POST, PUT or DELETE is supported"); KGE_ERRORF("HttpModule: unknown request type, only GET, POST, PUT or DELETE is supported");
return; return;
} }

View File

@ -535,7 +535,7 @@ void Actor::AddChild(ActorPtr child, int zorder)
{ {
if (parent == child) if (parent == child)
{ {
KGE_ERROR("A actor cannot be its own parent"); KGE_ERRORF("A actor cannot be its own parent");
return; return;
} }
} }

View File

@ -43,12 +43,12 @@ Stage::~Stage() {}
void Stage::OnEnter() void Stage::OnEnter()
{ {
KGE_SYS_LOG("Stage entered"); KGE_DEBUG_LOGF("Stage entered");
} }
void Stage::OnExit() void Stage::OnExit()
{ {
KGE_SYS_LOG("Stage exited"); KGE_DEBUG_LOGF("Stage exited");
} }
void Stage::RenderBorder(RenderContext& ctx) void Stage::RenderBorder(RenderContext& ctx)

View File

@ -195,7 +195,7 @@ public:
/// @brief 获取该动画的倒转 /// @brief 获取该动画的倒转
virtual ActionPtr Reverse() const override virtual ActionPtr Reverse() const override
{ {
KGE_ERROR("Reverse() not supported in ActionMoveTo"); KGE_ERRORF("Reverse() not supported in ActionMoveTo");
return nullptr; return nullptr;
} }
@ -299,7 +299,7 @@ public:
/// @brief 获取该动画的倒转 /// @brief 获取该动画的倒转
virtual ActionPtr Reverse() const override virtual ActionPtr Reverse() const override
{ {
KGE_ERROR("Reverse() not supported in ActionJumpTo"); KGE_ERRORF("Reverse() not supported in ActionJumpTo");
return nullptr; return nullptr;
} }
@ -398,7 +398,7 @@ public:
/// @brief 获取该动画的倒转 /// @brief 获取该动画的倒转
virtual ActionPtr Reverse() const override virtual ActionPtr Reverse() const override
{ {
KGE_ERROR("Reverse() not supported in ActionScaleTo"); KGE_ERRORF("Reverse() not supported in ActionScaleTo");
return nullptr; return nullptr;
} }
@ -439,7 +439,7 @@ public:
/// @brief 获取该动画的倒转 /// @brief 获取该动画的倒转
virtual ActionPtr Reverse() const override virtual ActionPtr Reverse() const override
{ {
KGE_ERROR("Reverse() not supported in ActionFadeTo"); KGE_ERRORF("Reverse() not supported in ActionFadeTo");
return nullptr; return nullptr;
} }
@ -544,7 +544,7 @@ public:
/// @brief 获取该动画的倒转 /// @brief 获取该动画的倒转
virtual ActionPtr Reverse() const override virtual ActionPtr Reverse() const override
{ {
KGE_ERROR("Reverse() not supported in ActionRotateTo"); KGE_ERRORF("Reverse() not supported in ActionRotateTo");
return nullptr; return nullptr;
} }
@ -589,7 +589,7 @@ public:
/// @brief 获取该动画的倒转 /// @brief 获取该动画的倒转
ActionPtr Reverse() const override ActionPtr Reverse() const override
{ {
KGE_ERROR("Reverse() not supported in ActionCustom"); KGE_ERRORF("Reverse() not supported in ActionCustom");
return nullptr; return nullptr;
} }

View File

@ -122,13 +122,13 @@ void ObjectBase::StopTracingLeaks()
void ObjectBase::DumpTracingObjects() void ObjectBase::DumpTracingObjects()
{ {
KGE_SYS_LOG("-------------------------- All Objects --------------------------"); KGE_DEBUG_LOGF("-------------------------- All Objects --------------------------");
for (const auto object : tracing_objects) for (const auto object : tracing_objects)
{ {
KGE_SYS_LOG("{ class=\"%s\" id=%d refcount=%d name=\"%s\" }", typeid(*object).name(), object->GetObjectID(), KGE_DEBUG_LOGF("{ class=\"%s\" id=%d refcount=%d name=\"%s\" }", typeid(*object).name(), object->GetObjectID(),
object->GetRefCount(), object->GetName().c_str()); object->GetRefCount(), object->GetName().c_str());
} }
KGE_SYS_LOG("------------------------- Total size: %d -------------------------", tracing_objects.size()); KGE_DEBUG_LOGF("------------------------- Total size: %d -------------------------", tracing_objects.size());
} }
Vector<ObjectBase*>& ObjectBase::GetTracingObjects() Vector<ObjectBase*>& ObjectBase::GetTracingObjects()

View File

@ -9,9 +9,9 @@
//#define KGE_ASSERT(EXPR) __noop // Disable asserts //#define KGE_ASSERT(EXPR) __noop // Disable asserts
//---- Define debug-output handler. Defaults to calling kiwano::logs::Messageln()/Warningln()/Errorln() //---- Define debug-output handler. Defaults to calling kiwano::logs::Messageln()/Warningln()/Errorln()
//#define KGE_SYS_LOG(FORMAT, ...) wprintf(FORMAT "\n", __VA_ARGS__) //#define KGE_LOGF(FORMAT, ...) printf(FORMAT "\n", __VA_ARGS__)
//#define KGE_WARN(FORMAT, ...) wprintf(FORMAT "\n", __VA_ARGS__) //#define KGE_WARNF(FORMAT, ...) printf(FORMAT "\n", __VA_ARGS__)
//#define KGE_ERROR(FORMAT, ...) wprintf(FORMAT "\n", __VA_ARGS__) //#define KGE_ERRORF(FORMAT, ...) printf(FORMAT "\n", __VA_ARGS__)
//---- Define attributes of all API symbols declarations for DLL //---- Define attributes of all API symbols declarations for DLL
//#define KGE_USE_DLL //#define KGE_USE_DLL

View File

@ -181,7 +181,7 @@ DbgHelp g_DbgHelp;
void PrintErrorCode(LPCSTR lpszFunction) void PrintErrorCode(LPCSTR lpszFunction)
{ {
KGE_ERROR("%s failed with HRESULT of %08X", lpszFunction, HRESULT_FROM_WIN32(GetLastError())); KGE_ERRORF("%s failed with HRESULT of %08X", lpszFunction, HRESULT_FROM_WIN32(GetLastError()));
} }
void PrintCallStackOnContext(PCONTEXT pContext) void PrintCallStackOnContext(PCONTEXT pContext)
@ -227,7 +227,7 @@ void PrintCallStackOnContext(PCONTEXT pContext)
constexpr int STACKWALK_MAX_NAMELEN = 1024; constexpr int STACKWALK_MAX_NAMELEN = 1024;
BYTE symbolBuffer[sizeof(IMAGEHLP_SYMBOL64) + STACKWALK_MAX_NAMELEN]; BYTE symbolBuffer[sizeof(IMAGEHLP_SYMBOL64) + STACKWALK_MAX_NAMELEN];
KGE_ERROR("========== Stack trace =========="); KGE_ERRORF("========== Stack trace ==========");
while (true) while (true)
{ {
@ -263,11 +263,11 @@ void PrintCallStackOnContext(PCONTEXT pContext)
DWORD dwLineDisplacement; DWORD dwLineDisplacement;
if (g_DbgHelp.SymGetLineFromAddr64(hProcess, sf.AddrPC.Offset, &dwLineDisplacement, &lineInfo)) if (g_DbgHelp.SymGetLineFromAddr64(hProcess, sf.AddrPC.Offset, &dwLineDisplacement, &lineInfo))
{ {
KGE_ERROR("%s (%d): %s", lineInfo.FileName, lineInfo.LineNumber, pSymbol->Name); KGE_ERRORF("%s (%d): %s", lineInfo.FileName, lineInfo.LineNumber, pSymbol->Name);
} }
else else
{ {
KGE_ERROR("(filename not available): %s", pSymbol->Name); KGE_ERRORF("(filename not available): %s", pSymbol->Name);
} }
if (sf.AddrReturn.Offset == 0) if (sf.AddrReturn.Offset == 0)

View File

@ -27,7 +27,7 @@
#define KGE_THROW(MESSAGE) \ #define KGE_THROW(MESSAGE) \
do \ do \
{ \ { \
KGE_ERROR("An exception occurred: %s", MESSAGE); \ KGE_ERRORF("An exception occurred: %s", MESSAGE); \
kiwano::StackTracer().Print(); \ kiwano::StackTracer().Print(); \
throw kiwano::RuntimeError(MESSAGE); \ throw kiwano::RuntimeError(MESSAGE); \
} while (0) } while (0)
@ -35,7 +35,7 @@
#define KGE_THROW_SYSTEM_ERROR(ERRCODE, MESSAGE) \ #define KGE_THROW_SYSTEM_ERROR(ERRCODE, MESSAGE) \
do \ do \
{ \ { \
KGE_ERROR("An exception occurred (%#x): %s", ERRCODE, MESSAGE); \ KGE_ERRORF("An exception occurred (%#x): %s", ERRCODE, MESSAGE); \
kiwano::StackTracer().Print(); \ kiwano::StackTracer().Print(); \
throw kiwano::SystemError(std::error_code(kiwano::error_enum(ERRCODE)), MESSAGE); \ throw kiwano::SystemError(std::error_code(kiwano::error_enum(ERRCODE)), MESSAGE); \
} while (0) } while (0)

View File

@ -48,28 +48,28 @@ Resource::Data Resource::GetData() const
HRSRC res_info = FindResourceA(nullptr, MAKEINTRESOURCEA(id_), type_.data()); HRSRC res_info = FindResourceA(nullptr, MAKEINTRESOURCEA(id_), type_.data());
if (res_info == nullptr) if (res_info == nullptr)
{ {
KGE_ERROR("FindResource failed"); KGE_ERRORF("FindResource failed");
break; break;
} }
HGLOBAL res_data = LoadResource(nullptr, res_info); HGLOBAL res_data = LoadResource(nullptr, res_info);
if (res_data == nullptr) if (res_data == nullptr)
{ {
KGE_ERROR("LoadResource failed"); KGE_ERRORF("LoadResource failed");
break; break;
} }
DWORD size = SizeofResource(nullptr, res_info); DWORD size = SizeofResource(nullptr, res_info);
if (size == 0) if (size == 0)
{ {
KGE_ERROR("SizeofResource failed"); KGE_ERRORF("SizeofResource failed");
break; break;
} }
LPVOID buffer = LockResource(res_data); LPVOID buffer = LockResource(res_data);
if (buffer == nullptr) if (buffer == nullptr)
{ {
KGE_ERROR("LockResource failed"); KGE_ERRORF("LockResource failed");
break; break;
} }

View File

@ -606,7 +606,7 @@ LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
{ {
if (SIZE_MAXHIDE == wparam || SIZE_MINIMIZED == wparam) if (SIZE_MAXHIDE == wparam || SIZE_MINIMIZED == wparam)
{ {
KGE_SYS_LOG("Window minimized"); KGE_DEBUG_LOGF("Window minimized");
is_minimized_ = true; is_minimized_ = true;
// Pause game when window is minimized // Pause game when window is minimized
@ -614,7 +614,7 @@ LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
} }
else if (SIZE_MAXIMIZED == wparam) else if (SIZE_MAXIMIZED == wparam)
{ {
KGE_SYS_LOG("Window maximized"); KGE_DEBUG_LOGF("Window maximized");
if (is_minimized_) if (is_minimized_)
{ {
@ -626,7 +626,7 @@ LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
{ {
if (is_minimized_) if (is_minimized_)
{ {
KGE_SYS_LOG("Window restored"); KGE_DEBUG_LOGF("Window restored");
// the window was restored and was previously minimized // the window was restored and was previously minimized
is_minimized_ = false; is_minimized_ = false;
@ -646,7 +646,7 @@ LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
evt->height = this->GetHeight(); evt->height = this->GetHeight();
this->PushEvent(evt); this->PushEvent(evt);
KGE_SYS_LOG("Window resized to (%d, %d)", this->width_, this->height_); KGE_DEBUG_LOGF("Window resized to (%d, %d)", this->width_, this->height_);
} }
} }
} }
@ -672,7 +672,7 @@ LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
uint32_t client_height = uint32_t(client_rect.bottom - client_rect.top); uint32_t client_height = uint32_t(client_rect.bottom - client_rect.top);
if (client_width != this->GetWidth() || client_height != this->GetHeight()) if (client_width != this->GetWidth() || client_height != this->GetHeight())
{ {
KGE_SYS_LOG("Window resized to (%d, %d)", client_width, client_height); KGE_DEBUG_LOGF("Window resized to (%d, %d)", client_width, client_height);
this->width_ = client_width; this->width_ = client_width;
this->height_ = client_height; this->height_ = client_height;
@ -744,7 +744,7 @@ LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
case WM_SETTEXT: case WM_SETTEXT:
{ {
KGE_SYS_LOG("Window title changed"); KGE_DEBUG_LOGF("Window title changed");
this->title_ = strings::WideToNarrow(reinterpret_cast<LPCWSTR>(lparam)); this->title_ = strings::WideToNarrow(reinterpret_cast<LPCWSTR>(lparam));
@ -756,13 +756,13 @@ LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
case WM_SETICON: case WM_SETICON:
{ {
KGE_SYS_LOG("Window icon changed"); KGE_DEBUG_LOGF("Window icon changed");
} }
break; break;
case WM_DISPLAYCHANGE: case WM_DISPLAYCHANGE:
{ {
KGE_SYS_LOG("The display resolution has changed"); KGE_DEBUG_LOGF("The display resolution has changed");
} }
break; break;
@ -774,7 +774,7 @@ LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
case WM_CLOSE: case WM_CLOSE:
{ {
KGE_SYS_LOG("Window is closing"); KGE_DEBUG_LOGF("Window is closing");
WindowClosedEventPtr evt = new WindowClosedEvent; WindowClosedEventPtr evt = new WindowClosedEvent;
this->PushEvent(evt); this->PushEvent(evt);
@ -785,7 +785,7 @@ LRESULT WindowWin32Impl::MessageProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARA
case WM_DESTROY: case WM_DESTROY:
{ {
KGE_SYS_LOG("Window was destroyed"); KGE_DEBUG_LOGF("Window was destroyed");
::PostQuitMessage(0); ::PostQuitMessage(0);
return 0; return 0;

View File

@ -155,7 +155,7 @@ void RenderContextImpl::DrawTextLayout(const TextLayout& layout, const Point& of
} }
else else
{ {
KGE_ERROR("Failed to draw text layout with HRESULT of %08X", hr); KGE_ERRORF("Failed to draw text layout with HRESULT of %08X", hr);
} }
} }
} }

View File

@ -51,7 +51,7 @@ RendererImpl::RendererImpl()
void RendererImpl::MakeContextForWindow(WindowPtr window) void RendererImpl::MakeContextForWindow(WindowPtr window)
{ {
KGE_SYS_LOG("Creating device resources"); KGE_DEBUG_LOGF("Creating device resources");
KGE_THROW_IF_FAILED(::CoInitialize(nullptr), "CoInitialize failed"); KGE_THROW_IF_FAILED(::CoInitialize(nullptr), "CoInitialize failed");
@ -143,7 +143,7 @@ void RendererImpl::MakeContextForWindow(WindowPtr window)
void RendererImpl::Destroy() void RendererImpl::Destroy()
{ {
KGE_SYS_LOG("Destroying device resources"); KGE_DEBUG_LOGF("Destroying device resources");
if (d2d_res_) if (d2d_res_)
{ {
@ -194,7 +194,7 @@ void RendererImpl::CreateTexture(Texture& texture, const String& file_path)
if (!FileSystem::GetInstance().IsFileExists(file_path)) if (!FileSystem::GetInstance().IsFileExists(file_path))
{ {
KGE_WARN("Texture file '%s' not found!", file_path.c_str()); KGE_WARNF("Texture file '%s' not found!", file_path.c_str());
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
} }
@ -291,7 +291,7 @@ void RendererImpl::CreateTexture(Texture& texture, const Resource& resource)
if (FAILED(hr)) if (FAILED(hr))
{ {
KGE_WARN("Load texture failed with HRESULT of %08X!", hr); KGE_WARNF("Load texture failed with HRESULT of %08X!", hr);
} }
} }
@ -305,7 +305,7 @@ void RendererImpl::CreateGifImage(GifImage& gif, const String& file_path)
if (!FileSystem::GetInstance().IsFileExists(file_path)) if (!FileSystem::GetInstance().IsFileExists(file_path))
{ {
KGE_WARN("Gif texture file '%s' not found!", file_path.c_str()); KGE_WARNF("Gif texture file '%s' not found!", file_path.c_str());
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
} }
@ -324,7 +324,7 @@ void RendererImpl::CreateGifImage(GifImage& gif, const String& file_path)
if (FAILED(hr)) if (FAILED(hr))
{ {
KGE_WARN("Load GIF texture failed with HRESULT of %08X!", hr); KGE_WARNF("Load GIF texture failed with HRESULT of %08X!", hr);
} }
} }
@ -356,7 +356,7 @@ void RendererImpl::CreateGifImage(GifImage& gif, const Resource& resource)
if (FAILED(hr)) if (FAILED(hr))
{ {
KGE_WARN("Load GIF texture failed with HRESULT of %08X!", hr); KGE_WARNF("Load GIF texture failed with HRESULT of %08X!", hr);
} }
} }
@ -520,7 +520,7 @@ void RendererImpl::CreateGifImageFrame(GifImage::Frame& frame, const GifImage& g
if (FAILED(hr)) if (FAILED(hr))
{ {
KGE_WARN("Load GIF frame failed with HRESULT of %08X!", hr); KGE_WARNF("Load GIF frame failed with HRESULT of %08X!", hr);
} }
} }
@ -536,7 +536,7 @@ void RendererImpl::CreateFontCollection(Font& font, const String& file_path)
{ {
if (!FileSystem::GetInstance().IsFileExists(file_path)) if (!FileSystem::GetInstance().IsFileExists(file_path))
{ {
KGE_WARN("Font file '%s' not found!", file_path.c_str()); KGE_WARNF("Font file '%s' not found!", file_path.c_str());
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
} }
} }

View File

@ -19,10 +19,222 @@
// THE SOFTWARE. // THE SOFTWARE.
#include <ctime> #include <ctime>
#include <ios>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <kiwano/utils/Logger.h> #include <kiwano/utils/Logger.h>
namespace kiwano
{
String LogFormater::GetLevelLabel(LogLevel level) const
{
switch (level)
{
case kiwano::LogLevel::Debug:
return "[Debug]";
case kiwano::LogLevel::Info:
return "[Info]";
case kiwano::LogLevel::Notice:
return "[Notice]";
case kiwano::LogLevel::Warning:
return "[Warning]";
case kiwano::LogLevel::Error:
return "[Error]";
default:
break;
}
return String();
}
class TextFormater : public LogFormater
{
public:
void Format(std::iostream& out, LogLevel level, Time time, std::streambuf* raw_msg) override
{
// get timestamp
time_t unix = std::time(nullptr);
std::tm tmbuf;
localtime_s(&tmbuf, &unix);
// build message
out << GetLevelLabel(level) << std::put_time(&tmbuf, " %H:%M:%S ");
if (raw_msg->sgetc() != std::char_traits<char>::eof())
out << raw_msg;
out << "\n";
}
};
LogProvider::~LogProvider() {}
LogProviderPtr ConsoleLogProvider::Create()
{
LogProviderPtr ptr = new ConsoleLogProvider;
return ptr;
}
ConsoleLogProvider::~ConsoleLogProvider()
{
Flush();
}
void ConsoleLogProvider::Init()
{
}
void ConsoleLogProvider::WriteMessage(LogLevel level, LogBuffer* msg)
{
if (level != LogLevel::Error)
std::cout << msg << std::flush;
else
std::cerr << msg;
#if defined(KGE_PLATFORM_WINDOWS)
::OutputDebugStringA(msg->GetRaw());
#endif
}
void ConsoleLogProvider::Flush()
{
std::cout.flush();
}
LogProviderPtr FileLogProvider::Create(const String& filepath, std::ios_base::openmode mode)
{
SmartPtr<FileLogProvider> ptr = new FileLogProvider;
if (ptr)
{
ptr->ofs_.open(filepath, mode);
}
return ptr;
}
FileLogProvider::~FileLogProvider()
{
if (ofs_.is_open())
ofs_.close();
}
void FileLogProvider::Init() {}
void FileLogProvider::WriteMessage(LogLevel level, LogBuffer* msg)
{
if (ofs_)
ofs_ << msg << std::flush;
}
void FileLogProvider::Flush()
{
if (ofs_)
ofs_.flush();
}
Logger::Logger()
: enabled_(true)
, level_(LogLevel::Debug)
{
ResizeBuffer(1024);
LogFormaterPtr formater = new TextFormater;
SetFormater(formater);
LogProviderPtr provider = ConsoleLogProvider::Create();
AddProvider(provider);
}
Logger::~Logger()
{
}
void Logger::Logf(LogLevel level, const char* format, ...)
{
if (!enabled_)
return;
if (level < level_)
return;
// build message
va_list args = nullptr;
va_start(args, format);
StringStream sstream;
sstream << strings::FormatArgs(format, args);
va_end(args);
// write message
Write(level, sstream.rdbuf());
}
void Logger::Flush()
{
if (!enabled_)
return;
for (auto provider : providers_)
{
provider->Flush();
}
}
void Logger::SetLevel(LogLevel level)
{
level_ = level;
}
void Logger::AddProvider(LogProviderPtr provider)
{
if (provider)
{
provider->Init();
providers_.push_back(provider);
}
}
LogFormaterPtr Logger::GetFormater()
{
return formater_;
}
void Logger::ResizeBuffer(size_t buffer_size)
{
buffer_.resize(buffer_size);
}
void Logger::Write(LogLevel level, std::streambuf* raw_msg)
{
std::lock_guard<std::mutex> lock(mutex_);
LogBuffer buf(buffer_);
std::iostream stream(&buf);
if (formater_)
{
formater_->Format(stream, level, Time::Now(), raw_msg);
}
else
{
stream << raw_msg << "\n";
}
for (auto provider : providers_)
{
buf.pubseekpos(0, std::ios_base::out);
provider->WriteMessage(level, &buf);
}
}
#if defined(KGE_PLATFORM_WINDOWS)
//
// Console log
//
namespace namespace
{ {
std::streambuf *cin_buffer, *cout_buffer, *cerr_buffer; std::streambuf *cin_buffer, *cout_buffer, *cerr_buffer;
@ -121,202 +333,6 @@ HWND GetAllocatedConsole()
} }
} // namespace } // namespace
namespace kiwano
{
namespace console_colors
{
const WORD blue = FOREGROUND_BLUE | FOREGROUND_INTENSITY;
const WORD green = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
const WORD red = FOREGROUND_RED | FOREGROUND_INTENSITY;
const WORD yellow = FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY;
const WORD white = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY;
const WORD blue_bg = white | BACKGROUND_BLUE | BACKGROUND_INTENSITY;
const WORD green_bg = white | BACKGROUND_GREEN | BACKGROUND_INTENSITY;
const WORD red_bg = white | BACKGROUND_RED | BACKGROUND_INTENSITY;
const WORD yellow_bg = BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY;
const WORD white_bg = BACKGROUND_BLUE | BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_INTENSITY;
const WORD Reset = white;
} // namespace console_colors
#define DECLARE_HANDLE_COLOR(NAME, HANDLE_NAME, COLOR) \
inline OutputStream&(NAME)(OutputStream & _out) \
{ \
::SetConsoleTextAttribute(::GetStdHandle(HANDLE_NAME), console_colors::##COLOR); \
return _out; \
}
#define DECLARE_COLOR(COLOR) \
DECLARE_HANDLE_COLOR(stdout_##COLOR, STD_OUTPUT_HANDLE, COLOR) \
DECLARE_HANDLE_COLOR(stderr_##COLOR, STD_ERROR_HANDLE, COLOR)
#define DECLARE_BG_COLOR(COLOR) \
DECLARE_HANDLE_COLOR(stdout_##COLOR##_bg, STD_OUTPUT_HANDLE, COLOR##_bg) \
DECLARE_HANDLE_COLOR(stderr_##COLOR##_bg, STD_ERROR_HANDLE, COLOR##_bg)
namespace console_colors
{
DECLARE_COLOR(red);
DECLARE_COLOR(green);
DECLARE_COLOR(yellow);
DECLARE_COLOR(blue);
DECLARE_COLOR(white);
DECLARE_COLOR(Reset);
DECLARE_BG_COLOR(red);
DECLARE_BG_COLOR(green);
DECLARE_BG_COLOR(yellow);
DECLARE_BG_COLOR(blue);
DECLARE_BG_COLOR(white);
} // namespace console_colors
Logger::Logger()
: enabled_(true)
, default_stdout_color_(0)
, default_stderr_color_(0)
, output_stream_(std::cout.rdbuf())
, error_stream_(std::cerr.rdbuf())
{
ResetStreamToStdStream();
}
Logger::~Logger()
{
FreeAllocatedConsole();
}
void Logger::Printf(Level level, const char* format, ...)
{
if (!enabled_)
return;
StringStream sstream;
Prepare(level, sstream);
// Format message
if (format)
{
va_list args = nullptr;
va_start(args, format);
static char temp_buffer[1024 * 3 + 1];
const auto len = ::_vscprintf(format, args) + 1;
::_vsnprintf_s(temp_buffer, len, len, format, args);
sstream << ' ' << temp_buffer << "\n";
va_end(args);
}
Output(level, sstream);
}
void Logger::Prepare(Level level, StringStream& sstream)
{
String prefix;
switch (level)
{
case Level::Info:
prefix = "[INFO] ";
break;
case Level::System:
prefix = "[SYSTEM] ";
break;
case Level::Warning:
prefix = "[WARN] ";
break;
case Level::Error:
prefix = "[ERROR] ";
break;
}
// Timestamp
time_t unix = std::time(nullptr);
std::tm tmbuf;
localtime_s(&tmbuf, &unix);
sstream << prefix << std::put_time(&tmbuf, "%H:%M:%S ");
}
void Logger::Output(Level level, StringStream& sstream)
{
using ConsoleColor = Function<OutputStream&(OutputStream&)>;
OutputStream* ostream = nullptr;
ConsoleColor color = nullptr;
switch (level)
{
case Level::Info:
ostream = &output_stream_;
color = Closure(this, &Logger::DefaultOutputColor);
break;
case Level::System:
ostream = &output_stream_;
color = console_colors::stdout_blue;
break;
case Level::Warning:
ostream = &output_stream_;
color = console_colors::stdout_yellow_bg;
break;
case Level::Error:
ostream = &error_stream_;
color = console_colors::stderr_red_bg;
break;
}
// Printing
if (ostream)
{
auto output = sstream.str();
color(*ostream) << output << std::flush;
::OutputDebugStringA(output.c_str());
ResetConsoleColor();
}
}
void Logger::ResetStreamToStdStream()
{
bool has_console = ::GetConsoleWindow() != nullptr;
if (has_console)
{
default_stdout_color_ = default_stderr_color_ =
FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY;
CONSOLE_SCREEN_BUFFER_INFO stdout_info;
if (::GetConsoleScreenBufferInfo(::GetStdHandle(STD_OUTPUT_HANDLE), &stdout_info))
{
default_stdout_color_ = stdout_info.wAttributes;
}
CONSOLE_SCREEN_BUFFER_INFO stderr_info;
if (::GetConsoleScreenBufferInfo(::GetStdHandle(STD_ERROR_HANDLE), &stderr_info))
{
default_stderr_color_ = stderr_info.wAttributes;
}
// replace the C++ global locale with the user-preferred locale
(void)std::locale::global(std::locale());
(void)std::cout.imbue(std::locale());
(void)std::cerr.imbue(std::locale());
RedirectOutputStream(std::cout.rdbuf());
RedirectErrorStream(std::cerr.rdbuf());
}
}
std::streambuf* Logger::RedirectOutputStream(std::streambuf* buf)
{
return output_stream_.rdbuf(buf);
}
std::streambuf* Logger::RedirectErrorStream(std::streambuf* buf)
{
return error_stream_.rdbuf(buf);
}
void Logger::ShowConsole(bool show) void Logger::ShowConsole(bool show)
{ {
HWND current_console = ::GetConsoleWindow(); HWND current_console = ::GetConsoleWindow();
@ -328,14 +344,13 @@ void Logger::ShowConsole(bool show)
} }
else else
{ {
HWND console = ::AllocateConsole(); HWND console = AllocateConsole();
if (!console) if (console)
{ {
KGE_WARN("AllocConsole failed"); // replace the C++ global locale with the user-preferred locale
} (void)std::locale::global(std::locale());
else (void)std::cout.imbue(std::locale());
{ (void)std::cerr.imbue(std::locale());
ResetStreamToStdStream();
// disable the close button of console // disable the close button of console
HMENU hmenu = ::GetSystemMenu(console, FALSE); HMENU hmenu = ::GetSystemMenu(console, FALSE);
@ -359,4 +374,117 @@ void Logger::ShowConsole(bool show)
} }
} }
#endif
LogBuffer::LogBuffer(Vector<char_type>& buf)
: buf_(buf)
, seek_high_(nullptr)
{
this->setbuf(buf.data(), buf.size());
}
const char* LogBuffer::GetRaw() const
{
const auto pptr = this->pptr();
if (!pptr)
return "";
const auto data = buf_.data();
const auto size = buf_.size();
if (pptr == data)
return "";
if (pptr > data && pptr < data + size)
{
*pptr = '\0';
return data;
}
return "";
}
LogBuffer::int_type LogBuffer::overflow(int_type ch)
{
if (traits_type::eq_int_type(ch, traits_type::eof()))
return traits_type::not_eof(ch); // EOF, return success
const auto pptr = this->pptr();
if (pptr)
return traits_type::eof();
const auto epptr = this->epptr();
if (pptr < epptr)
{
seek_high_ = pptr + 1;
return ch;
}
const auto old_ptr = buf_.data();
const auto old_size = pptr - old_ptr;
size_t new_size = 0;
if (old_size < INT_MAX / 2)
new_size = old_size << 1;
else if (old_size < INT_MAX)
new_size = INT_MAX;
else
return traits_type::eof(); // buffer can't grow, fail
// grow
buf_.resize(new_size);
const auto new_ptr = buf_.data();
const auto new_pnext = new_ptr + old_size;
seek_high_ = new_pnext + 1;
this->setp(new_ptr, new_pnext, new_ptr + new_size);
this->setg(new_ptr, new_ptr + (this->gptr() - old_ptr), seek_high_);
return ch;
}
LogBuffer::int_type LogBuffer::underflow()
{
const auto gptr = this->gptr();
if (!gptr)
return traits_type::eof();
if (gptr < this->egptr())
return traits_type::to_int_type(*gptr);
const auto pptr = this->pptr();
if (!pptr)
return traits_type::eof();
const auto high = std::max(seek_high_, pptr);
if (high <= gptr)
return traits_type::eof();
seek_high_ = high;
this->setg(this->eback(), gptr, high);
return traits_type::to_int_type(*gptr);
}
LogBuffer::pos_type LogBuffer::seekpos(pos_type sp, std::ios_base::openmode which)
{
return this->seekoff(sp - pos_type(off_type(0)), std::ios_base::beg, which);
}
LogBuffer::pos_type LogBuffer::seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode which)
{
if (dir == std::ios_base::cur)
gbump(int(off));
else if (dir == std::ios_base::end)
setg(eback(), egptr() + off, egptr());
else if (dir == std::ios_base::beg)
setg(eback(), eback() + off, egptr());
return gptr() - eback();
}
std::streambuf* LogBuffer::setbuf(char_type* s, std::streamsize n)
{
this->setp(s, s + n);
this->setg(s, s, s);
return this;
}
} // namespace kiwano } // namespace kiwano

View File

@ -19,83 +19,201 @@
// THE SOFTWARE. // THE SOFTWARE.
#pragma once #pragma once
#include <kiwano/core/Common.h> #include <kiwano/core/Time.h>
#include <kiwano/base/ObjectBase.h>
#include <mutex>
#include <iomanip> #include <iomanip>
#include <streambuf> #include <streambuf>
#include <fstream>
#ifndef KGE_SYS_LOG #ifndef KGE_DEBUG_LOG
#ifdef KGE_DEBUG #ifdef KGE_DEBUG
#define KGE_SYS_LOG(FORMAT, ...) \ #define KGE_DEBUG_LOG(...) ::kiwano::Logger::GetInstance().Log(::kiwano::LogLevel::Debug, __VA_ARGS__)
::kiwano::Logger::GetInstance().Printf(::kiwano::Logger::Level::System, FORMAT, __VA_ARGS__)
#else #else
#define KGE_SYS_LOG __noop #define KGE_DEBUG_LOG __noop
#endif #endif
#endif #endif
#ifndef KGE_WARN
#define KGE_WARN(FORMAT, ...) ::kiwano::Logger::GetInstance().Printf(::kiwano::Logger::Level::Warning, FORMAT, __VA_ARGS__)
#endif
#ifndef KGE_ERROR
#define KGE_ERROR(FORMAT, ...) ::kiwano::Logger::GetInstance().Printf(::kiwano::Logger::Level::Error, FORMAT, __VA_ARGS__)
#endif
#ifndef KGE_LOG #ifndef KGE_LOG
#define KGE_LOG(...) ::kiwano::Logger::GetInstance().Println(::kiwano::Logger::Level::Info, __VA_ARGS__) #define KGE_LOG(...) ::kiwano::Logger::GetInstance().Log(::kiwano::LogLevel::Info, __VA_ARGS__)
#endif
#ifndef KGE_NOTICE
#define KGE_NOTICE(...) ::kiwano::Logger::GetInstance().Log(::kiwano::LogLevel::Notice, __VA_ARGS__)
#endif
#ifndef KGE_WARN
#define KGE_WARN(...) ::kiwano::Logger::GetInstance().Log(::kiwano::LogLevel::Warning, __VA_ARGS__)
#endif
#ifndef KGE_ERROR
#define KGE_ERROR(...) ::kiwano::Logger::GetInstance().Log(::kiwano::LogLevel::Error, __VA_ARGS__)
#endif
#ifndef KGE_DEBUG_LOGF
#ifdef KGE_DEBUG
#define KGE_DEBUG_LOGF(FORMAT, ...) ::kiwano::Logger::GetInstance().Logf(::kiwano::LogLevel::Debug, FORMAT, __VA_ARGS__)
#else
#define KGE_DEBUG_LOGF __noop
#endif
#endif #endif
#ifndef KGE_LOGF #ifndef KGE_LOGF
#define KGE_LOGF(FORMAT, ...) ::kiwano::Logger::GetInstance().Printf(::kiwano::Logger::Level::Info, FORMAT, __VA_ARGS__) #define KGE_LOGF(FORMAT, ...) ::kiwano::Logger::GetInstance().Logf(::kiwano::LogLevel::Info, FORMAT, __VA_ARGS__)
#endif #endif
#ifndef KGE_LOG_STREAM #ifndef KGE_NOTICEF
#define KGE_LOG_STREAM() ::kiwano::Logger::GetInstance().GetOutputStream() #define KGE_NOTICEF(FORMAT, ...) ::kiwano::Logger::GetInstance().Logf(::kiwano::LogLevel::Notice, FORMAT, __VA_ARGS__)
#endif #endif
#ifndef KGE_ERROR_STREAM #ifndef KGE_WARNF
#define KGE_ERROR_STREAM() ::kiwano::Logger::GetInstance().GetErrorStream() #define KGE_WARNF(FORMAT, ...) ::kiwano::Logger::GetInstance().Logf(::kiwano::LogLevel::Warning, FORMAT, __VA_ARGS__)
#endif
#ifndef KGE_ERRORF
#define KGE_ERRORF(FORMAT, ...) ::kiwano::Logger::GetInstance().Logf(::kiwano::LogLevel::Error, FORMAT, __VA_ARGS__)
#endif #endif
namespace kiwano namespace kiwano
{ {
KGE_DECLARE_SMART_PTR(LogFormater);
KGE_DECLARE_SMART_PTR(LogProvider);
KGE_DECLARE_SMART_PTR(Logger);
/** /**
* \~chinese * \~chinese
* @brief * @brief
*/
enum class LogLevel
{
Debug, ///< 调试
Info, ///< 信息
Notice, ///< 注意
Warning, ///< 警告
Error, ///< 错误
};
/**
* \~chinese
* @brief
*/
class KGE_API LogFormater : public ObjectBase
{
public:
virtual void Format(std::iostream& out, LogLevel level, Time time, std::streambuf* raw_msg) = 0;
String GetLevelLabel(LogLevel level) const;
};
/**
* \~chinese
* @brief
*/
class LogBuffer : public std::streambuf
{
public:
LogBuffer(Vector<char_type>& buf);
const char* GetRaw() const;
protected:
int_type overflow(int_type ch) override;
int_type underflow() override;
pos_type seekpos(pos_type sp, std::ios_base::openmode which) override;
pos_type seekoff(off_type off, std::ios_base::seekdir dir,
std::ios_base::openmode which = std::ios_base::in) override;
std::streambuf* setbuf(char_type* s, std::streamsize n) override;
private:
Vector<char_type>& buf_;
char_type* seek_high_;
};
/**
* \~chinese
* @brief
*/
class KGE_API LogProvider : public ObjectBase
{
public:
virtual ~LogProvider();
virtual void Init() = 0;
virtual void WriteMessage(LogLevel level, LogBuffer* msg) = 0;
virtual void Flush() = 0;
};
/**
* \~chinese
* @brief
*/
class KGE_API ConsoleLogProvider : public LogProvider
{
public:
static LogProviderPtr Create();
virtual ~ConsoleLogProvider();
void Init() override;
void WriteMessage(LogLevel level, LogBuffer* msg) override;
void Flush() override;
};
/**
* \~chinese
* @brief
*/
class KGE_API FileLogProvider : public LogProvider
{
public:
static LogProviderPtr Create(const String& filepath, std::ios_base::openmode mode = std::ios_base::out);
virtual ~FileLogProvider();
void Init() override;
void WriteMessage(LogLevel level, LogBuffer* msg) override;
void Flush() override;
private:
std::ofstream ofs_;
};
/**
* \~chinese
* @brief
*/ */
class KGE_API Logger : public Singleton<Logger> class KGE_API Logger : public Singleton<Logger>
{ {
friend Singleton<Logger>; friend Singleton<Logger>;
public: public:
/// \~chinese
/// @brief 日志级别
enum class Level
{
Info, ///< 信息
System, ///< 系统
Warning, ///< 警告
Error ///< 错误
};
/// \~chinese /// \~chinese
/// @brief 打印日志 /// @brief 打印日志
/// @param level 日志级别 /// @param level 日志级别
/// @param format 格式字符串 /// @param format 格式字符串
void Printf(Level level, const char* format, ...); void Logf(LogLevel level, const char* format, ...);
/// \~chinese /// \~chinese
/// @brief 打印日志 /// @brief 打印日志
/// @param level 日志级别 /// @param level 日志级别
/// @param args 参数 /// @param args 参数
template <typename... _Args> template <typename... _Args>
void Print(Level level, _Args&&... args); void Log(LogLevel level, _Args&&... args);
/// \~chinese /// \~chinese
/// @brief 打印一行日志 /// @brief 刷新日志缓冲
/// @param level 日志级别 void Flush();
/// @param args 参数
template <typename... _Args>
void Println(Level level, _Args&&... args);
/// \~chinese /// \~chinese
/// @brief 启用日志 /// @brief 启用日志
@ -106,48 +224,53 @@ public:
void Disable(); void Disable();
/// \~chinese /// \~chinese
/// @brief 获取输出流 /// @brief 设置日志等级
OutputStream& GetOutputStream(); void SetLevel(LogLevel level);
/// \~chinese /// \~chinese
/// @brief 获取错误输出流 /// @brief 添加日志提供者
OutputStream& GetErrorStream(); /// @param provider 日志提供者
void AddProvider(LogProviderPtr provider);
/// \~chinese /// \~chinese
/// @brief 重定向输出流 /// @brief 设置日志格式
std::streambuf* RedirectOutputStream(std::streambuf* buf); /// @param formater 日志格式化
void SetFormater(LogFormaterPtr formater);
/// \~chinese /// \~chinese
/// @brief 重定向错误输出流 /// @brief 获取日志格式
std::streambuf* RedirectErrorStream(std::streambuf* buf); /// @return 日志格式
LogFormaterPtr GetFormater();
/// \~chinese
/// @brief 重设缓冲区大小
/// @param buffer_size 缓冲区大小
void ResizeBuffer(size_t buffer_size);
/// \~chinese
/// @brief 写入缓冲区
/// @param level 日志等级
/// @param raw_msg 日志内容
void Write(LogLevel level, std::streambuf* raw_msg);
#if defined(KGE_PLATFORM_WINDOWS)
/// \~chinese /// \~chinese
/// @brief 显示或关闭控制台 /// @brief 显示或关闭控制台
/// @note 此操作会重定向输出流到标准输出流
void ShowConsole(bool show); void ShowConsole(bool show);
#endif
~Logger(); virtual ~Logger();
private: private:
Logger(); Logger();
void Prepare(Level level, StringStream& sstream);
void Output(Level level, StringStream& sstream);
void ResetStreamToStdStream();
void ResetConsoleColor() const;
OutputStream& DefaultOutputColor(OutputStream& out);
private: private:
bool enabled_; bool enabled_;
WORD default_stdout_color_; LogLevel level_;
WORD default_stderr_color_; LogFormaterPtr formater_;
Vector<LogProviderPtr> providers_;
OutputStream output_stream_; Vector<char> buffer_;
OutputStream error_stream_; std::mutex mutex_;
}; };
inline void Logger::Enable() inline void Logger::Enable()
@ -160,57 +283,26 @@ inline void Logger::Disable()
enabled_ = false; enabled_ = false;
} }
inline void Logger::SetFormater(LogFormaterPtr formater)
{
formater_ = formater;
}
template <typename... _Args> template <typename... _Args>
void Logger::Print(Level level, _Args&&... args) inline void Logger::Log(LogLevel level, _Args&&... args)
{ {
if (!enabled_) if (!enabled_)
return; return;
StringStream sstream; if (level < level_)
Prepare(level, sstream);
// Format message
(void)std::initializer_list<int>{ ((sstream << ' ' << args), 0)... };
Output(level, sstream);
}
template <typename... _Args>
void Logger::Println(Level level, _Args&&... args)
{
if (!enabled_)
return; return;
// build message
StringStream sstream; StringStream sstream;
Prepare(level, sstream);
// Format message
(void)std::initializer_list<int>{ ((sstream << ' ' << args), 0)... }; (void)std::initializer_list<int>{ ((sstream << ' ' << args), 0)... };
sstream << "\r\n"; // write message
this->Write(level, sstream.rdbuf());
Output(level, sstream);
} }
inline void Logger::ResetConsoleColor() const
{
::SetConsoleTextAttribute(::GetStdHandle(STD_OUTPUT_HANDLE), default_stdout_color_);
::SetConsoleTextAttribute(::GetStdHandle(STD_ERROR_HANDLE), default_stderr_color_);
}
inline OutputStream& Logger::DefaultOutputColor(OutputStream& out)
{
::SetConsoleTextAttribute(::GetStdHandle(STD_OUTPUT_HANDLE), default_stdout_color_);
return out;
}
inline OutputStream& Logger::GetOutputStream()
{
return output_stream_;
}
inline OutputStream& Logger::GetErrorStream()
{
return error_stream_;
}
} // namespace kiwano } // namespace kiwano

View File

@ -60,7 +60,7 @@ bool ResourceCache::LoadFromJsonFile(const String& file_path)
{ {
if (!FileSystem::GetInstance().IsFileExists(file_path)) if (!FileSystem::GetInstance().IsFileExists(file_path))
{ {
KGE_ERROR("%s failed: File not found.", __FUNCTION__); KGE_ERRORF("%s failed: File not found.", __FUNCTION__);
return false; return false;
} }
@ -78,12 +78,12 @@ bool ResourceCache::LoadFromJsonFile(const String& file_path)
} }
catch (std::wifstream::failure& e) catch (std::wifstream::failure& e)
{ {
KGE_ERROR("%s failed: Cannot open file. (%s)", __FUNCTION__, e.what()); KGE_ERRORF("%s failed: Cannot open file. (%s)", __FUNCTION__, e.what());
return false; return false;
} }
catch (Json::exception& e) catch (Json::exception& e)
{ {
KGE_ERROR("%s failed: Cannot parse to JSON. (%s)", __FUNCTION__, e.what()); KGE_ERRORF("%s failed: Cannot parse to JSON. (%s)", __FUNCTION__, e.what());
return false; return false;
} }
return LoadFromJson(json_data); return LoadFromJson(json_data);
@ -106,12 +106,12 @@ bool ResourceCache::LoadFromJson(const Json& json_data)
} }
else else
{ {
KGE_ERROR("%s failed: unknown resource data version", __FUNCTION__); KGE_ERRORF("%s failed: unknown resource data version", __FUNCTION__);
} }
} }
catch (Json::exception& e) catch (Json::exception& e)
{ {
KGE_ERROR("%s failed: JSON data is invalid. (%s)", __FUNCTION__, e.what()); KGE_ERRORF("%s failed: JSON data is invalid. (%s)", __FUNCTION__, e.what());
return false; return false;
} }
return false; return false;
@ -121,7 +121,7 @@ bool ResourceCache::LoadFromXmlFile(const String& file_path)
{ {
if (!FileSystem::GetInstance().IsFileExists(file_path)) if (!FileSystem::GetInstance().IsFileExists(file_path))
{ {
KGE_ERROR("%s failed: File not found.", __FUNCTION__); KGE_ERRORF("%s failed: File not found.", __FUNCTION__);
return false; return false;
} }
@ -136,7 +136,7 @@ bool ResourceCache::LoadFromXmlFile(const String& file_path)
} }
else else
{ {
KGE_ERROR("%s failed: XML [%s] parsed with errors: %s", __FUNCTION__, full_path.c_str(), result.description()); KGE_ERRORF("%s failed: XML [%s] parsed with errors: %s", __FUNCTION__, full_path.c_str(), result.description());
return false; return false;
} }
} }
@ -160,7 +160,7 @@ bool ResourceCache::LoadFromXml(const XmlDocument& doc)
} }
else else
{ {
KGE_ERROR("%s failed: unknown resource data version", __FUNCTION__); KGE_ERRORF("%s failed: unknown resource data version", __FUNCTION__);
} }
} }
return false; return false;