#pragma once #include #include #include "String.Format.tlh" #include "ErrorCodeToString.hpp" #define __LOG__SimpleLog__ //----------------------------------------------------------------------------- // SimpleLog //----------------------------------------------------------------------------- class SimpleLog { public: enum enLogLevel { enUndefined = 0, enDebug = 10, enInfo = 20, enNotice = 30, enWarn = 40, enError = 50, enFatal = 60 }; public: inline static enLogLevel gLogLevel = enLogLevel::enUndefined; private: FILE * fpLog = nullptr; static inline char LogLevelToChar (int level) { // static char Name [6] = { ' ', ' ', ' ', 'W', 'E', 'F' }; if (level == enWarn) return 'W'; if (level == enError) return 'E'; if (level == enFatal) return 'F'; return ' '; } public: SimpleLog () = default; SimpleLog (const char * LogName) { Open (LogName); } bool Open (const char * LogName) { if (fpLog) fclose (fpLog); char AppPath [_MAX_PATH + _MAX_PATH]; int len = GetModuleFileName (NULL, AppPath, _MAX_PATH); len--; while (AppPath [len] != '\\') AppPath [len--] = '\0'; struct timeb tp; ftime (&tp); tm tmNow; _localtime64_s (&tmNow, &tp.time); auto Y = tmNow.tm_year + 1900; auto M = tmNow.tm_mon + 1; auto D = tmNow.tm_mday; auto H = tmNow.tm_hour; auto T = tmNow.tm_min; auto S = tmNow.tm_sec; char logFileName [_MAX_PATH]; ECOM::Utility::String::StringFormat (logFileName, _MAX_PATH) .Format ("{$}\\Log\\{$}.{$:d04}{$:d02}{$:d02}.log", AppPath, LogName, Y, M, D); fpLog = fopen (logFileName, "ab+"); assert (fpLog); return (fpLog != NULL); } void Close () { if (fpLog) fclose (fpLog); fpLog = nullptr; } public: template inline int Force (const char * fmt, Args && ... args) { return LogOut (enDebug, fmt, std::forward (args)...); } template inline int Debug (const char * fmt, Args && ... args) { if (gLogLevel > enLogLevel::enDebug) return 0; return LogOut (enDebug, fmt, std::forward (args)...); } template inline int Info (const char * fmt, Args && ... args) { if (gLogLevel > enLogLevel::enInfo) return 0; return LogOut (enInfo, fmt, std::forward (args)...); } template inline int Notice (const char * fmt, Args && ... args) { if (gLogLevel > enLogLevel::enNotice) return 0; return LogOut (enInfo, fmt, std::forward (args)...); } template inline int Warn (const char * fmt, Args && ... args) { if (gLogLevel > enLogLevel::enWarn) return 0; return LogOut (enWarn, fmt, std::forward (args)...); } template inline int Error (const char * fmt, Args && ... args) { if (gLogLevel > enLogLevel::enError) return 0; return LogOut (enError, fmt, std::forward (args)...); } template inline int Fatal (const char * fmt, Args && ... args) { if (gLogLevel > enLogLevel::enFatal) return 0; return LogOut (enFatal, fmt, std::forward (args)...); } int Flush (const char * buf, int len) { assert (buf); assert (fpLog); if (! fpLog) return 0; auto rc = (int) fwrite (buf, len, 1, fpLog); fflush (fpLog); return rc; } protected: template inline int LogOut (int Level, const char * fmt, Args && ... args) { if (! fpLog) return 0; static const int MaxLen = 8192; char * buf = new char [MaxLen]; struct timeb tp; ftime (&tp); tm tmNow; _localtime64_s (&tmNow, &tp.time); auto Y = tmNow.tm_year + 1900; auto M = tmNow.tm_mon + 1; auto D = tmNow.tm_mday; auto H = tmNow.tm_hour; auto T = tmNow.tm_min; auto S = tmNow.tm_sec; int len1 = ECOM::Utility::String::StringFormat (buf, MaxLen).Format ("{$} {$:d04}{$:d02}{$:d02} {$:d02}:{$:d02}:{$:d02}:{$:d03} [{$:x04}] ", LogLevelToChar (Level), Y, M, D, H, T, S, tp.millitm, GetCurrentThreadId ()); int len2 = ECOM::Utility::String::StringFormat (buf+len1, MaxLen-len1).Format (fmt, std::forward (args)...); buf [len1 + len2 + 0] = '\r'; buf [len1 + len2 + 1] = '\n'; return Flush (buf, len1+len2+2 ); } }; //----------------------------------------------------------------------------- // mLog 是对 gLogger 的简单封装 // mLog 可以理解为 myLog, 或者 mainLog 的短名称 //----------------------------------------------------------------------------- namespace mLog { inline SimpleLog gLogger; inline std::string ErrorCodeToString (DWORD errCode) { return ::ErrorCodeToString (errCode); } inline void Flush (const char * buf, int len) { gLogger.Flush (buf, len); } inline void NewLine () { gLogger.Flush ("\r\n", 2); } template inline void Force (const char * fmt, Args && ... args) { // assert (gLogger); // if (! gLogger) return; gLogger.Force (fmt, std::forward (args)...); } template inline void Trace (const char * fmt, Args && ... args) { // assert (gLogger); // if (! gLogger) return; gLogger.Trace (fmt, std::forward (args)...); } template inline void Debug (const char * fmt, Args && ... args) { // assert (gLogger); // if (! gLogger) return; gLogger.Debug (fmt, std::forward (args)...); } template inline void Info (const char * fmt, Args && ... args) { // assert (gLogger); // if (! gLogger) return; gLogger.Info (fmt, std::forward (args)...); } template inline void Notice (const char * fmt, Args && ... args) { // assert (gLogger); // if (! gLogger) return; gLogger.Notice (fmt, std::forward (args)...); } template inline void Warn (const char * fmt, Args && ... args) { // assert (gLogger); // if (! gLogger) return; gLogger.Warn (fmt, std::forward (args)...); } template inline void Warning (const char * fmt, Args && ... args) { // assert (gLogger); // if (! gLogger) return; gLogger.Warn (fmt, std::forward (args)...); } template inline void Error (const char * fmt, Args && ... args) { // assert (gLogger); // if (! gLogger) return; gLogger.Error (fmt, std::forward (args)...); } template inline void Fatal (const char * fmt, Args && ... args) { // assert (gLogger); // if (! gLogger) return; gLogger.Fatal (fmt, std::forward (args)...); } inline bool Open (const char * LogName) { return gLogger.Open (LogName); } inline void Close () { // assert (gLogger); // if (! gLogger) return; gLogger.Close (); } };