update Logger

This commit is contained in:
Nomango 2019-03-31 13:08:59 +08:00 committed by Nomango
parent ec512490dd
commit eea3f92567
3 changed files with 316 additions and 157 deletions

View File

@ -19,6 +19,7 @@
// THE SOFTWARE. // THE SOFTWARE.
#include "logs.h" #include "logs.h"
#include <iostream>
namespace easy2d namespace easy2d
{ {
@ -68,21 +69,48 @@ namespace easy2d
} }
Logger::Logger() Logger::Logger()
: enabled_(true)
, has_console_(false)
, default_stdout_color_(0)
, default_stderr_color_(0)
, output_stream_(std::wcout.rdbuf())
, error_stream_(std::wcerr.rdbuf())
{ {
enabled_ = ::GetConsoleWindow() != nullptr; ResetOutputStream();
default_stdout_color_ = default_stderr_color_ = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY; }
CONSOLE_SCREEN_BUFFER_INFO stdout_info; void Logger::ResetOutputStream()
if (::GetConsoleScreenBufferInfo(::GetStdHandle(STD_OUTPUT_HANDLE), &stdout_info)) {
has_console_ = ::GetConsoleWindow() != nullptr;
if (has_console_)
{ {
default_stdout_color_ = stdout_info.wAttributes; default_stdout_color_ = default_stderr_color_ = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY;
}
CONSOLE_SCREEN_BUFFER_INFO stderr_info; CONSOLE_SCREEN_BUFFER_INFO stdout_info;
if (::GetConsoleScreenBufferInfo(::GetStdHandle(STD_ERROR_HANDLE), &stderr_info)) if (::GetConsoleScreenBufferInfo(::GetStdHandle(STD_OUTPUT_HANDLE), &stdout_info))
{ {
default_stderr_color_ = stderr_info.wAttributes; 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;
}
RedirectOutputStreamBuffer(std::wcout.rdbuf());
RedirectErrorStreamBuffer(std::wcerr.rdbuf());
} }
} }
std::wstreambuf* Logger::RedirectOutputStreamBuffer(std::wstreambuf* buf)
{
return output_stream_.rdbuf(buf);
}
std::wstreambuf* Logger::RedirectErrorStreamBuffer(std::wstreambuf* buf)
{
return error_stream_.rdbuf(buf);
}
} }

View File

@ -23,7 +23,6 @@
#include "../common/Singleton.hpp" #include "../common/Singleton.hpp"
#include <ctime> #include <ctime>
#include <iomanip> #include <iomanip>
#include <iostream>
#include <sstream> #include <sstream>
#ifndef E2D_LOG #ifndef E2D_LOG
@ -44,10 +43,81 @@
namespace easy2d namespace easy2d
{ {
class E2D_API Logger
: public Singleton<Logger>
{
E2D_DECLARE_SINGLETON(Logger);
public:
void Enable();
void Disable();
template <typename ..._Args>
void Print(const wchar_t* format, _Args&&... args);
template <typename ..._Args>
void Println(const wchar_t* format, _Args&&... args);
template <typename ..._Args>
void Message(const wchar_t * format, _Args&&... args);
template <typename ..._Args>
void Messageln(const wchar_t * format, _Args&&... args);
template <typename ..._Args>
void Warning(const wchar_t* format, _Args&&... args);
template <typename ..._Args>
void Warningln(const wchar_t* format, _Args&&... args);
template <typename ..._Args>
void Error(const wchar_t* format, _Args&&... args);
template <typename ..._Args>
void Errorln(const wchar_t* format, _Args&&... args);
std::wstreambuf* RedirectOutputStreamBuffer(std::wstreambuf* buf);
std::wstreambuf* RedirectErrorStreamBuffer(std::wstreambuf* buf);
void ResetOutputStream();
private:
Logger();
template <typename ..._Args>
void OutputLine(std::wostream& os, std::wostream&(*color)(std::wostream&), const wchar_t* prompt, const wchar_t* format, _Args&&... args) const;
template <typename ..._Args>
void Output(std::wostream& os, std::wostream&(*color)(std::wostream&), const wchar_t* prompt, const wchar_t* format, _Args&&... args) const;
template <typename ..._Args>
std::wstring MakeOutputString(const wchar_t* prompt, const wchar_t* format, _Args&&... args) const;
void ResetConsoleColor() const;
static std::wostream& DefaultOutputColor(std::wostream& out);
static std::wostream& OutPrefix(std::wostream& out);
private:
bool enabled_;
bool has_console_;
WORD default_stdout_color_;
WORD default_stderr_color_;
std::wostream output_stream_;
std::wostream error_stream_;
};
//
// details of Logger
//
namespace __console_colors namespace __console_colors
{ {
using ConsoleColor = std::wostream&(*)(std::wostream&);
#define DECLARE_COLOR(COLOR)\ #define DECLARE_COLOR(COLOR)\
extern std::wostream&(stdout_##COLOR)(std::wostream&);\ extern std::wostream&(stdout_##COLOR)(std::wostream&);\
extern std::wostream&(stderr_##COLOR)(std::wostream&); extern std::wostream&(stderr_##COLOR)(std::wostream&);
@ -73,146 +143,136 @@ namespace easy2d
#undef DECLARE_BG_COLOR #undef DECLARE_BG_COLOR
} }
class E2D_API Logger
: public Singleton<Logger> inline void Logger::Enable()
{ {
E2D_DECLARE_SINGLETON(Logger); enabled_ = true;
}
public: inline void Logger::Disable()
inline void Enable() {
enabled_ = false;
}
template <typename ..._Args>
inline void Logger::Print(const wchar_t* format, _Args&&... args)
{
Output(output_stream_, Logger::DefaultOutputColor, nullptr, format, std::forward<_Args>(args)...);
}
template <typename ..._Args>
inline void Logger::Println(const wchar_t* format, _Args&&... args)
{
OutputLine(output_stream_, Logger::DefaultOutputColor, nullptr, format, std::forward<_Args>(args)...);
}
template <typename ..._Args>
inline void Logger::Message(const wchar_t * format, _Args&&... args)
{
using namespace __console_colors;
Output(output_stream_, stdout_blue, nullptr, format, std::forward<_Args>(args)...);
}
template <typename ..._Args>
inline void Logger::Messageln(const wchar_t * format, _Args&&... args)
{
using namespace __console_colors;
OutputLine(output_stream_, stdout_blue, nullptr, format, std::forward<_Args>(args)...);
}
template <typename ..._Args>
inline void Logger::Warning(const wchar_t* format, _Args&&... args)
{
using namespace __console_colors;
Output(output_stream_, stdout_yellow_bg, L"Warning: ", format, std::forward<_Args>(args)...);
}
template <typename ..._Args>
inline void Logger::Warningln(const wchar_t* format, _Args&&... args)
{
using namespace __console_colors;
OutputLine(output_stream_, stdout_yellow_bg, L"Warning: ", format, std::forward<_Args>(args)...);
}
template <typename ..._Args>
inline void Logger::Error(const wchar_t* format, _Args&&... args)
{
using namespace __console_colors;
Output(error_stream_, stderr_red_bg, L"Error: ", format, std::forward<_Args>(args)...);
}
template <typename ..._Args>
inline void Logger::Errorln(const wchar_t* format, _Args&&... args)
{
using namespace __console_colors;
OutputLine(error_stream_, stderr_red_bg, L"Error: ", format, std::forward<_Args>(args)...);
}
template <typename ..._Args>
inline void Logger::OutputLine(std::wostream& os, std::wostream&(*color)(std::wostream&), const wchar_t* prompt, const wchar_t* format, _Args&&... args) const
{
if (enabled_ && has_console_)
{ {
enabled_ = true;
}
inline void Disable()
{
enabled_ = false;
}
template <typename ..._Args>
inline void Print(const wchar_t* format, _Args&&... args) const
{
using namespace __console_colors;
Output(std::wcout, stdout_white, nullptr, format, std::forward<_Args>(args)...);
}
template <typename ..._Args>
inline void Println(const wchar_t* format, _Args&&... args) const
{
using namespace __console_colors;
OutputLine(std::wcout, stdout_white, nullptr, format, std::forward<_Args>(args)...);
}
template <typename ..._Args>
inline void Message(const wchar_t * format, _Args&&... args) const
{
using namespace __console_colors;
Output(std::wcout, stdout_blue, nullptr, format, std::forward<_Args>(args)...);
}
template <typename ..._Args>
inline void Messageln(const wchar_t * format, _Args&&... args) const
{
using namespace __console_colors;
OutputLine(std::wcout, stdout_blue, nullptr, format, std::forward<_Args>(args)...);
}
template <typename ..._Args>
inline void Warning(const wchar_t* format, _Args&&... args) const
{
using namespace __console_colors;
Output(std::wcerr, stdout_yellow_bg, L"Warning: ", format, std::forward<_Args>(args)...);
}
template <typename ..._Args>
inline void Warningln(const wchar_t* format, _Args&&... args) const
{
using namespace __console_colors;
OutputLine(std::wcerr, stdout_yellow_bg, L"Warning: ", format, std::forward<_Args>(args)...);
}
template <typename ..._Args>
inline void Error(const wchar_t* format, _Args&&... args) const
{
using namespace __console_colors;
Output(std::wcerr, stderr_red_bg, L"Error: ", format, std::forward<_Args>(args)...);
}
template <typename ..._Args>
inline void Errorln(const wchar_t* format, _Args&&... args) const
{
using namespace __console_colors;
OutputLine(std::wcerr, stderr_red_bg, L"Error: ", format, std::forward<_Args>(args)...);
}
private:
Logger();
template <typename ..._Args>
inline void OutputLine(std::wostream& os, __console_colors::ConsoleColor color, const wchar_t* prompt, const wchar_t* format, _Args&&... args) const
{
if (!enabled_)
return;
Output(os, color, prompt, format, std::forward<_Args>(args)...); Output(os, color, prompt, format, std::forward<_Args>(args)...);
os << std::endl; os << std::endl;
::OutputDebugStringW(L"\r\n"); ::OutputDebugStringW(L"\r\n");
} }
}
template <typename ..._Args> template <typename ..._Args>
inline void Output(std::wostream& os, __console_colors::ConsoleColor color, const wchar_t* prompt, const wchar_t* format, _Args&&... args) const inline void Logger::Output(std::wostream& os, std::wostream&(*color)(std::wostream&), const wchar_t* prompt, const wchar_t* format, _Args&&... args) const
{
if (enabled_ && has_console_)
{ {
if (!enabled_)
return;
std::wstring output = MakeOutputString(prompt, format, std::forward<_Args>(args)...); std::wstring output = MakeOutputString(prompt, format, std::forward<_Args>(args)...);
os << color << output; os << color << output;
::OutputDebugStringW(output.c_str()); ::OutputDebugStringW(output.c_str());
ResetColor(); ResetConsoleColor();
} }
}
template <typename ..._Args> template <typename ..._Args>
inline std::wstring MakeOutputString(const wchar_t* prompt, const wchar_t* format, _Args&&... args) const inline std::wstring Logger::MakeOutputString(const wchar_t* prompt, const wchar_t* format, _Args&&... args) const
{ {
static wchar_t temp_buffer[1024 * 3 + 1]; static wchar_t temp_buffer[1024 * 3 + 1];
const auto len = ::_scwprintf(format, std::forward<_Args>(args)...); const auto len = ::_scwprintf(format, std::forward<_Args>(args)...);
::swprintf_s(temp_buffer, len + 1, format, std::forward<_Args>(args)...); ::swprintf_s(temp_buffer, len + 1, format, std::forward<_Args>(args)...);
std::wstringstream ss; std::wstringstream ss;
ss << Logger::OutPrefix; ss << Logger::OutPrefix;
if (prompt) if (prompt)
ss << prompt; ss << prompt;
ss << temp_buffer; ss << temp_buffer;
return ss.str(); return ss.str();
} }
inline void ResetColor() const inline void Logger::ResetConsoleColor() const
{ {
::SetConsoleTextAttribute(::GetStdHandle(STD_OUTPUT_HANDLE), default_stdout_color_); ::SetConsoleTextAttribute(::GetStdHandle(STD_OUTPUT_HANDLE), default_stdout_color_);
::SetConsoleTextAttribute(::GetStdHandle(STD_ERROR_HANDLE), default_stderr_color_); ::SetConsoleTextAttribute(::GetStdHandle(STD_ERROR_HANDLE), default_stderr_color_);
} }
static inline std::wostream& OutPrefix(std::wostream& out) inline std::wostream& Logger::DefaultOutputColor(std::wostream& out)
{ {
std::time_t unix = std::time(nullptr); ::SetConsoleTextAttribute(::GetStdHandle(STD_OUTPUT_HANDLE), Logger::Instance().default_stdout_color_);
std::tm tmbuf; return out;
localtime_s(&tmbuf, &unix); }
out << std::put_time(&tmbuf, L"[easy2d] %H:%M:%S ");
return out;
}
private: inline std::wostream& Logger::OutPrefix(std::wostream& out)
bool enabled_; {
WORD default_stdout_color_; std::time_t unix = std::time(nullptr);
WORD default_stderr_color_; std::tm tmbuf;
}; localtime_s(&tmbuf, &unix);
out << std::put_time(&tmbuf, L"[easy2d] %H:%M:%S ");
return out;
}
} }
namespace easy2d namespace easy2d

View File

@ -31,9 +31,98 @@
#include <windowsx.h> #include <windowsx.h>
#include <imm.h> #include <imm.h>
#include <iostream> #include <iostream>
#include <fstream>
#pragma comment(lib, "imm32.lib") #pragma comment(lib, "imm32.lib")
namespace
{
std::streambuf *cin_buffer, *cout_buffer, *cerr_buffer;
std::fstream console_input, console_output, console_error;
std::wstreambuf *wcin_buffer, *wcout_buffer, *wcerr_buffer;
std::wfstream wconsole_input, wconsole_output, wconsole_error;
void RedirectStdIO()
{
cin_buffer = std::cin.rdbuf();
cout_buffer = std::cout.rdbuf();
cerr_buffer = std::cerr.rdbuf();
wcin_buffer = std::wcin.rdbuf();
wcout_buffer = std::wcout.rdbuf();
wcerr_buffer = std::wcerr.rdbuf();
console_input.open("CONIN$", std::ios::in);
console_output.open("CONOUT$", std::ios::out);
console_error.open("CONOUT$", std::ios::out);
wconsole_input.open("CONIN$", std::ios::in);
wconsole_output.open("CONOUT$", std::ios::out);
wconsole_error.open("CONOUT$", std::ios::out);
std::cin.rdbuf(console_input.rdbuf());
std::cout.rdbuf(console_output.rdbuf());
std::cerr.rdbuf(console_error.rdbuf());
std::wcin.rdbuf(wconsole_input.rdbuf());
std::wcout.rdbuf(wconsole_output.rdbuf());
std::wcerr.rdbuf(wconsole_error.rdbuf());
}
void ResetStdIO()
{
console_input.close();
console_output.close();
console_error.close();
wconsole_input.close();
wconsole_output.close();
wconsole_error.close();
std::cin.rdbuf(cin_buffer);
std::cout.rdbuf(cout_buffer);
std::cerr.rdbuf(cerr_buffer);
std::wcin.rdbuf(wcin_buffer);
std::wcout.rdbuf(wcout_buffer);
std::wcerr.rdbuf(wcerr_buffer);
cin_buffer = nullptr;
cout_buffer = nullptr;
cerr_buffer = nullptr;
wcin_buffer = nullptr;
wcout_buffer = nullptr;
wcerr_buffer = nullptr;
}
HWND allocated_console = nullptr;
HWND AllocateConsole()
{
if (::AllocConsole())
{
allocated_console = ::GetConsoleWindow();
if (allocated_console)
{
RedirectStdIO();
}
}
return allocated_console;
}
void FreeAllocatedConsole()
{
if (allocated_console)
{
ResetStdIO();
::FreeConsole();
allocated_console = nullptr;
}
}
HWND GetAllocatedConsole()
{
return allocated_console;
}
}
namespace easy2d namespace easy2d
{ {
Application::Application() Application::Application()
@ -51,6 +140,8 @@ namespace easy2d
{ {
Destroy(); Destroy();
FreeAllocatedConsole();
::CoUninitialize(); ::CoUninitialize();
} }
@ -321,8 +412,6 @@ namespace easy2d
void Application::ShowConsole(bool show) void Application::ShowConsole(bool show)
{ {
static HWND allocated_console = nullptr;
HWND current_console = ::GetConsoleWindow(); HWND current_console = ::GetConsoleWindow();
if (show) if (show)
{ {
@ -332,33 +421,16 @@ namespace easy2d
} }
else else
{ {
if (!::AllocConsole()) HWND console = ::AllocateConsole();
if (!console)
{ {
E2D_WARNING_LOG(L"AllocConsole failed"); E2D_WARNING_LOG(L"AllocConsole failed");
} }
else else
{ {
allocated_console = ::GetConsoleWindow(); // disable the close button of console
HMENU hmenu = ::GetSystemMenu(console, FALSE);
if (allocated_console) ::RemoveMenu(hmenu, SC_CLOSE, MF_BYCOMMAND);
{
FILE * dummy;
freopen_s(&dummy, "CONOUT$", "w+t", stdout);
freopen_s(&dummy, "CONIN$", "r+t", stdin);
freopen_s(&dummy, "CONOUT$", "w+t", stderr);
(void)dummy;
std::cout.clear();
std::wcout.clear();
std::cin.clear();
std::wcin.clear();
std::cerr.clear();
std::wcerr.clear();
// disable the close button of console
HMENU hmenu = ::GetSystemMenu(allocated_console, FALSE);
::RemoveMenu(hmenu, SC_CLOSE, MF_BYCOMMAND);
}
} }
} }
} }
@ -366,10 +438,9 @@ namespace easy2d
{ {
if (current_console) if (current_console)
{ {
if (current_console == allocated_console) if (current_console == GetAllocatedConsole())
{ {
::FreeConsole(); FreeAllocatedConsole();
allocated_console = nullptr;
} }
else else
{ {
@ -377,6 +448,8 @@ namespace easy2d
} }
} }
} }
Logger::Instance().ResetOutputStream();
} }
LRESULT CALLBACK Application::WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) LRESULT CALLBACK Application::WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
@ -526,8 +599,6 @@ namespace easy2d
{ {
bool active = (LOWORD(wparam) != WA_INACTIVE); bool active = (LOWORD(wparam) != WA_INACTIVE);
E2D_LOG(active ? L"Window activated" : L"Window deactivated");
app->GetWindow()->SetActive(active); app->GetWindow()->SetActive(active);
if (app->curr_scene_) if (app->curr_scene_)