在一个项目的开发中,经常会需要写一些运行的log啊,debug信息啊.正好我正在学习GP 相关的东西,就写了这个东西,希望能抛砖引玉了.
/*@$***************************************************************************
* File Name : MjLog.h
*
* COPYRIGHT Chen Mingjie 2001 bloodchen@hotmail.com
*******************************************************************************/
#ifndef _MjTools_CMjLog_
#define _MjTools_CMjLog_
namespace MjTools //Namespace defination for my tools
{
class GeneralLogControl //Base class of any specific log control class,providing basic controls
{
protected:
bool m_bEnabled;
public:
GeneralLogControl(const std::string ControlStr):m_bEnabled(true){};//log is enabled by default
GeneralLogControl():m_bEnabled(true){};
virtual ~GeneralLogControl(){};
virtual void Pause(){m_bEnabled=false;}
virtual void Resume(){m_bEnabled=true;}
virtual bool CanAdd(std::string& LogStr){return m_bEnabled;}
};
#ifdef WIN32 //RegistryLogControl only valid in Windows system
class RegistryLogControl:public GeneralLogControl
{
protected:
std::string m_ControlReg;
bool CheckReg(const std::string& reg);
public:
RegistryLogControl(const std::string ControlStr)
:m_ControlReg(ControlStr){m_bEnabled=CheckReg(ControlStr);}
void Resume(){m_bEnabled=CheckReg(m_ControlReg);}
virtual ~RegistryLogControl(){};
};
#endif
class FileLogImpl //class that implements file logging ability
{
protected:
std::string m_LogFileName;
public:
FileLogImpl(const std::string FileName):m_LogFileName(FileName)
{
if(m_LogFileName=="")m_LogFileName="log.txt"; //default file name
};
virtual void AddTimeStamp(std::string& LogStr); //you may want to override this method to provide your time stamp style
virtual ~FileLogImpl(){};
virtual bool AddLog(std::string& LogStr); //you may want to override this method to provide your log style
virtual void Clear(); //clear log file content
};
template<class ImplT, class ControlT>
class CMjLog
{
protected:
ControlT m_Control; //log control class
ImplT m_Impl; //log implementation class
public:
CMjLog(const std::string ImplStr="",const std::string ControlStr="")
:m_Control(ControlStr),m_Impl(ImplStr){};
virtual ~CMjLog(){};
bool AddLog(const std::string& LogStr) //Add one piece of log message
{
return AddLog(LogStr.c_str());
}
bool AddLog(const char* pLogStr) //Add one piece of log message
{
std::string log=pLogStr;
if(m_Control.CanAdd(log))
return m_Impl.AddLog(log);
else return false;
}
void Pause() //Pause log process
{
m_Control.Pause();
}
void Resume() //Resume log process
{
m_Control.Resume();
}
void Clear() //Clear log content
{
m_Impl.Clear();
}
};
/*--------------CFileLog definition------------------*/
typedef CMjLog<FileLogImpl,GeneralLogControl> CFileLog;
/*------------CFileLog Usage-------------------------
MjTools::CFileLog log("C:\\test.log"); //Construct a new logfile or open a existing log file
log.Clear(); //Delete previous logs.
log.AddLog("This is a test line"); //Add one log message
---------------------------------------------------*/
#ifdef WIN32 //RegistryLogControl only valid in Windows system
/*--------------CRegFileLog definition------------------*/
typedef CMjLog<FileLogImpl,RegistryLogControl> CRegFileLog;
/*------------CRegFileLog Usage-------------------------
MjTools::CRegFileLog log("C:\\test.log","HKEY_LOCAL_MACHINE\\Software\\YourLogControlKey"); //Construct a new logfile or open a existing log file
log.Clear(); //Delete previous logs.
log.AddLog("This is a test line"); //Add one log message
---------------------------------------------------*/
#endif
}
#endif
/*@$***************************************************************************
* File Name : MjLog.cpp
*
* COPYRIGHT Chen Mingjie 2001 bloodchen@hotmail.com
*******************************************************************************/
#include <sstream>
#include <fstream>
#include <string>
#include "MjLog.h"
#include "time.h"
#ifdef WIN32
#include <windows.h>
#include <Winreg.h>
#endif
namespace MjTools
{
void FileLogImpl::AddTimeStamp(std::string& LogStr)
{
time_t long_time;
time( &long_time );
struct tm *pt = localtime( &long_time );
if(pt)
{
std::ostringstream stream;
stream<<"AT:"<<pt->tm_hour<<':'<<pt->tm_min<<':'<<pt->tm_sec<<','<<pt->tm_year+1900<<'/'<<pt->tm_mon+1<<'/'<<pt->tm_mday<<"-------->";
LogStr=stream.str()+LogStr;
}
}
bool FileLogImpl::AddLog(std::string& LogStr)
{
AddTimeStamp(LogStr);
std::ofstream os(m_LogFileName.c_str(),std::ios::app);
os<<LogStr;
os<<std::endl;
os.flush();
os.close();
return true;
}
void FileLogImpl::Clear() //clear file content
{
std::ofstream os(m_LogFileName.c_str(),std::ios::out);
os.flush();
os.close();
}
#ifdef WIN32 //RegistryLogControl only valid in Windows system
bool RegistryLogControl::CheckReg(const std::string& reg) //Check if required reg key exists
{
HKEY hKey;
HKEY hKeyRoot;
bool ret=true;
if(m_ControlReg!="") //if no control_reg_key provided,it means "no reg_key control"
{
int nPos=m_ControlReg.find('\\');
if(nPos==-1)ret=false;
else
{
std::string root=m_ControlReg.substr(0,nPos);
std::string rest=m_ControlReg.substr(nPos+1);
if(root=="HKEY_LOCAL_MACHINE")hKeyRoot=HKEY_LOCAL_MACHINE;
if(root=="HKEY_CLASSES_ROOT")hKeyRoot=HKEY_CLASSES_ROOT;
if(root=="HKEY_CURRENT_CONFIG")hKeyRoot=HKEY_CURRENT_CONFIG;
if(root=="HKEY_CURRENT_USER")hKeyRoot=HKEY_CURRENT_USER;
if(root=="HKEY_USERS")hKeyRoot=HKEY_USERS;
if(root=="HKEY_PERFORMANCE_DATA")hKeyRoot=HKEY_PERFORMANCE_DATA;
if(root=="HKEY_DYN_DATA")hKeyRoot=HKEY_DYN_DATA ;
ret=(::RegOpenKey (hKeyRoot,rest.c_str(),&hKey)==ERROR_SUCCESS);
::RegCloseKey(hKey);
}
}
return ret;
};
#endif
}
#ifdef _TEST_
int main()
{
MjTools::CFileLog m_Log("test.log");
std::string a="aaa";
m_Log.Clear();
m_Log.AddLog("Abc");
m_Log.AddLog(a);
MjTools::CFileLog m_Log1=m_Log;
m_Log1.AddLog("From Log1");
#ifdef WIN32 //RegistryLogControl only valid in Windows system
//construct a registry key controled log object. If the specified registry key is found,the log is enabled
MjTools::CRegFileLog m_regLog("reglog.log","HKEY_LOCAL_MACHINE\\Software\\YourLogControlKey");
m_regLog.AddLog("reglog");
m_regLog.Pause();
m_regLog.AddLog("reglog1");
m_regLog.Resume();
m_regLog.AddLog("reglog2");
#endif
return 0;
}
#endif
如何编译
这两个文件本身就可以在不同的os下编译,比如
VC++: cl /D"_TEST_" MjLog.cpp /用命令行link会有个错,我也不知为什么,建一个空win32 console project再加入这两个文件就没有错了(别忘了predefine _TEST_)
BC++: BCC32 /D_TEST_ MjLog.cpp
g++: g++ /D_TEST MjLog.cpp
如何扩展
只要建立(或者继承)自己的control class 或者 impl class就可以用于各种用途,但对用户的接口是不变的