用template实现的可扩展的平台无关的 log Class

类别:VC语言 点击:0 评论:0 推荐:

在一个项目的开发中,经常会需要写一些运行的log啊,debug信息啊.正好我正在学习GP 相关的东西,就写了这个东西,希望能抛砖引玉了.

/*@$***************************************************************************
* File Name        : MjLog.h
*
*   COPYRIGHT Chen Mingjie 2001   [email protected]
*******************************************************************************/
#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   [email protected]
*******************************************************************************/

#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就可以用于各种用途,但对用户的接口是不变的

本文地址:http://com.8s8s.com/it/it2903.htm