|
#include <Windows.h>
#include "Log_msg.h"

int TestWinerrReturn()
  {
LOG_WINERROR_MSG_RETURN(10, 5);
return -100;
}

int TestErrmsgReturn()
  {
LOG_WINERROR_MSG_RETURN(10, 5);
return -100;
}

int TestCombine()
  {
LOG_MSG_ERROR_RETURN(10, _T("ERRORNO:%d, description: %s, return val:%d"), 5, LOG_WIN32ERROR_TO_MSG_WRAPPER(5), 10);
return 1;
}
int TestWrapper()
  {
LOG_MSG_ERROR(LOG_WIN32ERROR_TO_MSG_WRAPPER(5));
return 0;
}


int _tmain(int argc, _TCHAR* argv[])
  {
 LOG_CONFIGURATION conf = {true, Log_entity::LL_INFO, Log_entity::LO_FILE, _T("c:\\987.log")};
LOG_MSG_INITIALIZE(conf);
LOG_MSG_INFO(_T("LOG_MSG_INFO1"));
LOG_MSG_INFO(_T("LOG_MSG_INFO1:%s"), _T("info2"));
LOG_MSG_WARNING((_T("LOG_MSG_WARNING")));
LOG_MSG_WARNING(_T("LOG_MSG_WARNING1:%s"), _T("warning"));
LOG_MSG_ERROR((_T("LOG_MSG_ERROR")));
LOG_MSG_ERROR(_T("LOG_MSG_ERROR1:%s"), _T("Error"));
if(TestWinerrReturn() != 10)
 {
printf("TestWinerrReturn failed");
}
if(TestErrmsgReturn() != 10)
 {
printf("TestErrmsgReturn failed");
}
LOG_WINERROR_MSG((5));
if(TestCombine() != 10)
 {
printf("TestCombine failed");
}
system("pause");
return 0;
}
 /**/////////////////////////////////////////////////////////////////////////// // file Log_msg.h
//
// Copyright (c) 2010 robert xiao. All Rights Reserved. robert.xiao2010@gmail.com
//
// Permission to use, copy, modify, and distribute this software and its
// documentation for any purpose, without fee, and without a written
// agreement, is hereby granted, provided that the above copyright notice,
// this paragraph and the following two paragraphs appear in all copies,
// modifications, and distributions.
//
//
// IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT,
// INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST
// PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
// EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
// PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF
// ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". THE AUTHOR HAS NO OBLIGATION
// TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
//
 /**///////////////////////////////////////////////////////////////////////////
 /**//**
* @file: Log_msg.h
*
* @brief: provide write log message function, macro, and assistant class.
*
* @author: Robert xiao
*
*/

#pragma once

#if !defined (__TFILE__)
#define __TFILE__ _T(__FILE__)
#endif
 /**//* get description from a windows error. */
#if !defined LOG_WIN32ERROR_TO_MSG_WRAPPER
#define LOG_WIN32ERROR_TO_MSG_WRAPPER(x) \
Log_winErrorMsg(x)
#endif

 /**//* Intend to initialize the logger instance */
#if !defined (LOG_MSG_INITIALIZE)
#define LOG_MSG_INITIALIZE(conf) \
 { Log_entity::Initialize(conf);}
#endif

 /**//* Intend to print information */
#if !defined (LOG_MSG_INFO)
#define LOG_MSG_INFO(x, ) \
 do { \
Log_entity::GetInstance()->Log(Log_entity::LL_INFO, __TFILE__, __LINE__, x, __VA_ARGS__);\
}while(0)
#endif

 /**//* print warning message */
#if !defined (LOG_MSG_WARNING)
#define LOG_MSG_WARNING(x, ) \
 do {\
Log_entity::GetInstance()->Log(Log_entity::LL_WARNING, __TFILE__, __LINE__, x, __VA_ARGS__); \
}while(0)
#endif

 /**//* print error message */
#if !defined (LOG_MSG_ERROR)
#define LOG_MSG_ERROR(x, ) \
 do {\
Log_entity::GetInstance()->Log(Log_entity::LL_ERROR, __TFILE__, __LINE__, x, __VA_ARGS__); \
}while(0)
#endif

 /**//* print error message and return y */
#if !defined (LOG_MSG_ERROR_RETURN)
#define LOG_MSG_ERROR_RETURN(y, x, ) \
 do {\
Log_entity::GetInstance()->Log(Log_entity::LL_ERROR, __TFILE__, __LINE__, x, __VA_ARGS__); \
return y;\
}while(0)
#endif

 /**//* print fatal message */
#if !defined (LOG_MSG_FATAL)
#define LOG_MSG_FATAL(x, ) \
 do {\
Log_entity::GetInstance()->Log(Log_entity::LL_FATAL, __TFILE__, __LINE__, x, __VA_ARGS__); \
}while(0)
#endif

 /**//* print fatal message and return */
#if !defined (LOG_MSG_FATAL_RETURN)
#define LOG_MSG_FATAL_RETURN(y, x, ) \
 do {\
Log_entity::GetInstance()->Log(Log_entity::LL_FATAL, __TFILE__, __LINE__, x , __VA_ARGS__); \
return y;\
}while(0)
#endif

 /**//* print error no. description */
#if !defined (LOG_WINERROR_MSG)
#define LOG_WINERROR_MSG(x)\
 do { \
Log_entity::GetInstance()->Log(Log_entity::LL_ERROR, __TFILE__, __LINE__, Log_winErrorMsg(x));\
}while(0)
#endif

 /**//* print error no. description and return */
#if !defined (LOG_WINERROR_MSG_RETURN)
#define LOG_WINERROR_MSG_RETURN(y, x)\
 do { \
Log_entity::GetInstance()->Log(Log_entity::LL_ERROR, __TFILE__, __LINE__, Log_winErrorMsg(x));\
return y; \
}while(0)
#endif

 /**//* print COM result description */
#if !defined (LOG_HRESULT_MSG)
#define LOG_HRESULT_MSG(x) \
 do {\
Log_entity::GetInstance()->Log(Log_entity::LL_ERROR, __TFILE__, __LINE__, Log_winErrorMsg(x & 0x0000ffff));\
}while(0)
#endif

 /**//* print COM result description and return */
#if !defined (LOG_HRESULT_MSG_RETURN)
#define LOG_HRESULT_MSG_RETURN(y, x) \
 do {\
Log_entity::GetInstance()->Log(Log_entity::LL_ERROR, __TFILE__, __LINE__, Log_winErrorMsg(x & 0x0000ffff));\
return y; \
}while(0)
#endif

#include <Windows.h>

#define LOG_API

 class LOG_API Log_critical {
public:
 Log_critical() {
m_lEntered = 0;
::InitializeCriticalSection(&m_sec);
}

 ~Log_critical() {
::DeleteCriticalSection(&m_sec);
}
 void Lock(DWORD) {
::EnterCriticalSection(&m_sec);
++m_lEntered;
}

 void UnLock() {
if(m_lEntered > 0)
 {
--m_lEntered;
::LeaveCriticalSection(&m_sec);
}
}
private:
CRITICAL_SECTION m_sec;
LONG m_lEntered;
};

template<typename T, DWORD dwWaitTime = INFINITE>
 class LOG_API Log_manualLock {

public:

Log_manualLock(T& t, bool bLock)
:m_lock(t)
 ,m_bLocked(false) {
m_lock = t;
 if(bLock) {
Lock();
}
}

 ~Log_manualLock() {
 if(m_bLocked) {
UnLock();
}
}

 void Lock() {
m_lock->Lock(dwWaitTime);
m_bLocked = true;
}

 void UnLock() {
 if(m_bLocked) {
m_lock->UnLock();
m_bLocked = false;
}
}

private:
T &m_lock;
bool m_bLocked;
};

template<typename T, DWORD dwWaitTimeOut = INFINITE>
 class LOG_API Log_autoLock {
public:
Log_autoLock(T &t)
 :m_lock(t) {
m_lock.Lock(dwWaitTimeOut);
}

 ~Log_autoLock() {
m_lock.UnLock();
}

private:
T &m_lock;
};


 class LOG_API Log_winErrorMsg {

typedef TCHAR _character_type;
typedef _character_type* _p_character_type;
typedef const TCHAR* _pc_character_type;

public:
Log_winErrorMsg(int nError)
 :_szBuf(NULL) {
::FormatMessage (
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_MAX_WIDTH_MASK | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
nError,
MAKELANGID (LANG_NEUTRAL,SUBLANG_DEFAULT),
(LPTSTR ) &_szBuf,
0,
NULL);
}
 ~Log_winErrorMsg() {
if(_szBuf)
LocalFree(_szBuf);
}

 operator _pc_character_type() {
return _szBuf;
};

 _pc_character_type c_str() {
return _szBuf;
}

private:
_p_character_type _szBuf;
};
struct _LOG_CONFIGURATION;
 /**//**
* @class Log_entity
*
* @brief provide a variable length argument message logging
*
* @This class is liable for write the log message to standard output,
* DebugView tool , File.
*
*
*/
class LOG_API Log_entity
  {
typedef Log_autoLock< Log_critical > _AutoCritical;
public: // embed custom type
 enum LOG_LEVEL {
LL_INFO = 0,
LL_WARNING,
LL_ERROR,
LL_FATAL
};

 enum LOG_OUTPUT {
LO_NONE = 0x0,
LO_DEBUG = 0x2,
LO_STANDARD = 0x4,
LO_STANDARD_DEBUG = 0X6,
LO_FILE = 0x8,
LO_FILE_DEBUG = 0X0A,
LO_FILE_STANDARD =0X0C,
};

public:
static Log_entity* GetInstance();
static void Initialize(struct _LOG_CONFIGURATION& con);
void Log(LOG_LEVEL le, LPCTSTR szMsg, );
void Log(LOG_LEVEL le, LPCTSTR szFile, int nLine, LPCTSTR szMsg, );

 static void Dumb(LPCTSTR szMsg, ) {}
private:
void _write(LPCTSTR szMsg);

 /**//* Do nothing */
 void _writeNone( LPCTSTR) {}

 /**//* Write the message to DebugView */
void _writeDebug( LPCTSTR szMsg);

 /**//* Write the message to stderr */
void _writeStandard( LPCTSTR szMsg);

 /**//* Write the message to the file */
void _writeFile( LPCTSTR szMsg);

bool CanLog(LOG_LEVEL le);
private:
static Log_critical m_sCritical;
};

 typedef struct _LOG_CONFIGURATION {
bool _bNeedTime;
Log_entity::LOG_LEVEL _lowerLevel;
Log_entity::LOG_OUTPUT _output;
TCHAR _szLogFile[MAX_PATH];
}LOG_CONFIGURATION, *LPLOG_CONFIGURATION;

 /**/////////////////////////////////////////////////////////////////////////// // file Log_msg.cpp
//
// Copyright (c) 2010 robert xiao. All Rights Reserved. robert.xiao2010@gmail.com
//
// Permission to use, copy, modify, and distribute this software and its
// documentation for any purpose, without fee, and without a written
// agreement, is hereby granted, provided that the above copyright notice,
// this paragraph and the following two paragraphs appear in all copies,
// modifications, and distributions.
//
//
// IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT,
// INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST
// PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
// EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
// PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF
// ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". THE AUTHOR HAS NO OBLIGATION
// TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
//
 /**///////////////////////////////////////////////////////////////////////////
 /**//**
* @file: Log_msg.cpp
*
* @author: Robert xiao
*
*/

#include "stdafx.h"
#include <io.h>
#include "Log_msg.h"

 /**//**
* @global variable
*
* Log_entity g_logger
*
* g_config
*
* DEBUGFUFFERLEN
*/
static Log_entity g_logger;
 static LOG_CONFIGURATION g_config = {true, Log_entity::LL_ERROR, Log_entity::LO_NONE, _T('\0')};
const USHORT DEBUGFUFFERLEN = 4096;

#define LOG_MSG_SECTION "log_msg"
#define LOG_LEVEL_CAPTION "log_level"
#define LOG_OUTPUT_CAPTION "log_output"
#define LOG_FILE_CAPTION "log_file"

 namespace {

 /**//* if szPath is file name, then convert it to full path name */
 bool _ValidateLogFilePath(LPTSTR szPath) {
 if(!_tcslen(szPath)) {
return false;
}

 if(TCHAR *p = _tcsrchr(szPath, _T('\\'))) {
 TCHAR szDirectory[MAX_PATH] = {_T('\0')};
_tcsncpy_s(szDirectory, MAX_PATH, szPath, p - szPath);
WIN32_FIND_DATA data;
HANDLE h;
 if((h = FindFirstFile(szDirectory, &data)) != INVALID_HANDLE_VALUE) {
FindClose(h);
 if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
return true;
}
}
return false;
}
 TCHAR szDirectory[MAX_PATH] = {_T('\0')};
GetModuleFileName(NULL, szDirectory, MAX_PATH);
_tcscat_s(szDirectory, MAX_PATH, szPath);
_tcscpy_s(szPath, MAX_PATH, szDirectory);
return true;
}

int PrintCurrentTimeString(LPTSTR szTime, int nBufferLen)
 {
SYSTEMTIME stLocalTime;
FILETIME ftLocalTime;
GetSystemTime(&stLocalTime);
GetSystemTimeAsFileTime(&ftLocalTime);

return _stprintf_s(szTime,
nBufferLen,
_T("thread--0x%04x %02d:%02d:%02d.%03d%s %02d-%02d-%4d: "),
GetCurrentThreadId(),
(stLocalTime.wHour <= 12)?stLocalTime.wHour:stLocalTime.wHour-12,
stLocalTime.wMinute,
stLocalTime.wSecond,
stLocalTime.wMilliseconds,
(stLocalTime.wHour <= 12)?_T("AM"):_T("PM"),
stLocalTime.wMonth,
stLocalTime.wDay,
stLocalTime.wYear);
}

 int PrintMsgTypeString(Log_entity::LOG_LEVEL le, LPTSTR szBuf) {
 if(!szBuf) {
return 0;
}
 static TCHAR msgTopics[][20] = {
_T("INFO: "),
_T("WARNING: "),
_T("ERROR: "),
_T("FATAL: ")
};
_tcscpy_s(szBuf, 20, msgTopics[le]);
return static_cast<int>(_tcslen(szBuf));
}

 class Log_file {
public:
 Log_file() {
pf = 0;
}

 int Open(LPCTSTR szFileName) {
 if(!szFileName) {
return EXIT_FAILURE;
}

LPCTSTR szParams = _T("a+,ccs=UTF-8");
#if defined (_MSC_VER) && (_MSC_VER >= 1500)
int err = _tfopen_s(&pf, szFileName, szParams);
#else
pf = _tfopen(szFileName, szParams);
#endif
 if(pf) {
return EXIT_SUCCESS;
}
else
 {
//File IO failed - complain - not using error macros since we may not have debug output here
TCHAR szErr[256];
DWORD dwErr = GetLastError();
HRESULT hRes = HRESULT_FROM_WIN32(dwErr);
LPTSTR szSysErr = NULL;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
0,
dwErr,
0,
(LPTSTR)&szSysErr,
0,
0);

_stprintf_s(szErr,sizeof(szErr) / sizeof(TCHAR),
_T("_tfopen failed, hRes = 0x%08X, dwErr = 0x%08X = \"%s\"\n"),
HRESULT_FROM_WIN32(dwErr),
dwErr,
szSysErr);

OutputDebugString(szErr);
LocalFree(szSysErr);
return NULL;
}
return EXIT_FAILURE;
}

 int WriteLine(LPCTSTR szMsg) {
 if(pf && szMsg) {
 if(_fputts(szMsg, pf) >= 0) {
_fputts(_T("\n"), pf);
return EXIT_SUCCESS;
}
}
return EXIT_FAILURE;
}

~Log_file()
 {
 if(pf) {
fclose(pf);
}
}
private:
FILE *pf;
};
}


Log_critical Log_entity::m_sCritical;

 Log_entity* Log_entity::GetInstance() {
return &g_logger;
}

 void Log_entity::Initialize( struct _LOG_CONFIGURATION& con ) {
 if(con._output & LO_FILE) {
TCHAR szTemp[MAX_PATH];
_tcscpy_s(szTemp, MAX_PATH, con._szLogFile);
 if(!_ValidateLogFilePath(szTemp)) {
return ;
}
_tcscpy_s(g_config._szLogFile, MAX_PATH, szTemp);
}
g_config._lowerLevel = con._lowerLevel;
g_config._output = con._output;
g_config._bNeedTime = con._bNeedTime;
}

 void Log_entity::Log( LOG_LEVEL le, LPCTSTR szMsg, ) {
 if(!CanLog(le)) {
return;
}

 if(!szMsg) {
return;
}

 TCHAR szDebugBuffer[DEBUGFUFFERLEN] = {_T('\0')};
TCHAR *p = szDebugBuffer;
int nRemainBuffer = DEBUGFUFFERLEN;
int nUse = PrintMsgTypeString(le, p);
p += nUse;
 if(g_config._bNeedTime) {
nUse = PrintCurrentTimeString(p, DEBUGFUFFERLEN - (p -szDebugBuffer));
 if(nUse >= 0) {
p += nUse;
}
}

nRemainBuffer = DEBUGFUFFERLEN - (p - szDebugBuffer);
 if(_tcsrchr(szMsg, _T('%'))) {
va_list argList = NULL;
va_start(argList, szMsg);
int nWrite = _vsntprintf_s(p,
nRemainBuffer - 1,
nRemainBuffer,
szMsg,
argList);
 if(nWrite >= nRemainBuffer) {
szDebugBuffer[DEBUGFUFFERLEN - 1] = _T('\0');
}
va_end(argList);
}
 else {
_tcscat_s(p, nRemainBuffer, szMsg);
}

_write(szDebugBuffer);
}

 void Log_entity::Log( LOG_LEVEL le, LPCTSTR szFile, int nLine, LPCTSTR szMsg, ) {
 if(!CanLog(le)) {
return;
}

 if(!szMsg) {
return;
}

 TCHAR szDebugBuffer[DEBUGFUFFERLEN] = {_T('\0')};
TCHAR *p = szDebugBuffer;
int nRemainBuffer = DEBUGFUFFERLEN;
int nUse = PrintMsgTypeString(le, p);
p += nUse;
 if(szFile) {
TCHAR szSourceBuffer[MAX_PATH * 2];
_stprintf_s(szSourceBuffer,
MAX_PATH * 2,
_T("File:'%s' Line: %d; "),
szFile,
nLine);
_tcscat_s(szDebugBuffer, nRemainBuffer, szSourceBuffer);
p += _tcslen(szSourceBuffer);
}
 if(g_config._bNeedTime) {
nUse = PrintCurrentTimeString(p, DEBUGFUFFERLEN - (p - szDebugBuffer));
 if(nUse >= 0) {
p += nUse;
}
}

nRemainBuffer = DEBUGFUFFERLEN - (p - szDebugBuffer);
 if(_tcsrchr(szMsg, _T('%'))) {
va_list argList;
va_start(argList, szMsg);
int nWrite = _vsntprintf_s(p,
nRemainBuffer - 1,
nRemainBuffer,
szMsg,
argList);
 if(nWrite >= nRemainBuffer) {
szDebugBuffer[DEBUGFUFFERLEN - 1] = _T('\0');
}
va_end(argList);
}
 else {
_tcscat_s(p, nRemainBuffer, szMsg);
}
_write(szDebugBuffer);
}

 void Log_entity::_write(LPCTSTR szMsg ) {
 if(g_config._output & LO_FILE) {
_writeFile(szMsg);
}

 if(g_config._output & LO_STANDARD) {
_writeStandard(szMsg);
}

 if(g_config._output & LO_DEBUG) {
_writeDebug(szMsg);
}
}

 bool Log_entity::CanLog( LOG_LEVEL le ) {
return le >= g_config._lowerLevel && g_config._output != LO_NONE;
}

 void Log_entity::_writeDebug( LPCTSTR szMsg ) {
OutputDebugString(szMsg);
}

 void Log_entity::_writeStandard( LPCTSTR szMsg ) {
_tprintf(szMsg);
_tprintf(_T("\n"));
}

 void Log_entity::_writeFile( LPCTSTR szMsg ) {
_AutoCritical singleLock(m_sCritical);
Log_file logFile;
 if(logFile.Open(g_config._szLogFile) == EXIT_SUCCESS) {
logFile.WriteLine(szMsg);
}
}
|