Click here to Skip to main content
15,884,080 members
Articles / Programming Languages / C++

yaolog: A powerful, easy-use, cross-platform C++ log utility

Rate me:
Please Sign up or sign in to vote.
4.82/5 (12 votes)
30 Mar 2013CPOL5 min read 161.2K   1.3K   65  
A powerful, easy-use, cross-platform C++ log utility.
/*******************************************************************************
YaoLog v1.6

Description: A powerful, easy-use, cross-platform C++ log utility
Updated:     Mar 31, 2013
Author:      Neil.L
E-mail:      Neil.L@qq.com
See detail:  http://www.codeproject.com/Articles/508529/yaolog-A-powerful-easy-use-cross-platform-Cplusplu
********************************************************************************/


#ifndef _YAOLOG_H_
#define _YAOLOG_H_

///////////////////////////////////////////////////////////////
// platform
///////////////////////////////////////////////////////////////
#ifndef _YAOLOG_PLATFORM_DEFINED_
    #if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__)
        #define _YAOLOG_WIN32_
    #else
        #define _YAOLOG_POSIX_
    #endif
    #define _YAOLOG_PLATFORM_DEFINED_
#endif


///////////////////////////////////////////////////////////////
// include
///////////////////////////////////////////////////////////////
#ifdef _YAOLOG_WIN32_
#include <winsock2.h>
#include <windows.h>
#include <tchar.h>
#pragma warning(push)
#pragma warning(disable : 4251)
#else
#include <stdarg.h>
#include <pthread.h>
#include <arpa/inet.h>
#endif

#include <string>
#include <map>
#include <vector>
#include <cassert>


///////////////////////////////////////////////////////////////
// Uncomment the block below if you want to compile yaolog.dll
// define YAOLOG_EXPORTS for dll itself.
// And, you must guarantee that your yaolog.dll and invoker.exe are built with the same toolchain.
///////////////////////////////////////////////////////////////
/*
#ifdef _YAOLOG_WIN32_
    #ifdef YAOLOG_EXPORTS
        #define YAOLOG_EXPORT_API _declspec(dllexport)
    #else
        #define YAOLOG_EXPORT_API _declspec(dllimport)
    #endif
#else
    #define YAOLOG_EXPORT_API
#endif
*/


///////////////////////////////////////////////////////////////
// for protect... 
///////////////////////////////////////////////////////////////
#ifndef YAOLOG_EXPORT_API
#define YAOLOG_EXPORT_API
#endif


///////////////////////////////////////////////////////////////
// charset
///////////////////////////////////////////////////////////////
#ifndef _YAOLOG_CHARSET_DEFINED_
    #if defined(_YAOLOG_WIN32_) && defined(_UNICODE)
        #define _YAOLOG_UNICODE_
    #else
        #define _YAOLOG_ANSI_
    #endif
    #define _YAOLOG_CHARSET_DEFINED_
#endif


///////////////////////////////////////////////////////////////
// string
///////////////////////////////////////////////////////////////
#ifndef yao_tstring
    #ifdef _YAOLOG_UNICODE_
        #define yao_tstring   std::wstring
    #else
        #define yao_tstring   std::string
        #ifndef _T
        #define _T(x)     x
        #endif
        typedef char      TCHAR;
    #endif
#endif


///////////////////////////////////////////////////////////////
// Macros for log
// These log marcos will not be compiled if _NO_YAOLOG defined...
///////////////////////////////////////////////////////////////
#ifdef _NO_YAOLOG

#ifndef YAOLOG_INIT
#define YAOLOG_INIT
#endif
#ifndef YAOLOG_EXIT
#define YAOLOG_EXIT
#endif
#ifndef YAOLOG_CREATE
#define YAOLOG_CREATE(szLogID, bEnable, logType)
#endif
#ifndef YAOLOG_DISABLE_ALL
#define YAOLOG_DISABLE_ALL(bDisableAll)
#endif
#ifndef YAOLOG_SET_LOG_ATTR
#define YAOLOG_SET_LOG_ATTR(szLogID, bEnable, nOutFlag, bWithTime,\
    bWithMillisecond, bWithSrcFile, bWithFunction, szDestUrl)
#endif
#ifndef YAOLOG_SET_LOGFILE_ATTR
#define YAOLOG_SET_LOGFILE_ATTR(szLogID, bOverwrite, bFlushBufferImmediately,\
    bGenNewLogFileDaily, szLogFileDir, szLogFileName)
#endif
#ifndef YAOLOG_SET_ATTR_FROM_CONFIG_FILE
#define YAOLOG_SET_ATTR_FROM_CONFIG_FILE(szLogID, szINI)
#endif
#ifndef LOGBIN__
#define LOGBIN__(szLogID, pData, nSize)
#endif
#ifndef LOGBIN_F__
#define LOGBIN_F__(szLogID, szTitle, pData, nSize)
#endif
#ifndef LOG__
#define LOG__(szLogID, szFormat, ...)
#endif
#ifndef LOGA__
#define LOGA__(szLogID, szFormat, ...)
#endif
#ifndef LOGW__
#define LOGW__(szLogID, szFormat, ...)
#endif

#else

#ifndef YAOLOG_INIT
#define YAOLOG_INIT YaoUtil::LogFactory::Init()
#endif

#ifndef YAOLOG_EXIT
#define YAOLOG_EXIT YaoUtil::LogFactory::Exit()
#endif

#ifndef YAOLOG_CREATE
#define YAOLOG_CREATE(szLogID, bEnable, logType) \
    YaoUtil::LogFactory::Create(szLogID, bEnable, logType)
#endif

#ifndef YAOLOG_DISABLE_ALL
#define YAOLOG_DISABLE_ALL(bDisableAll) \
    YaoUtil::LogFactory::DisableAllLogs(bDisableAll)
#endif

#ifndef YAOLOG_SET_LOG_ATTR
#define YAOLOG_SET_LOG_ATTR(szLogID, bEnable, nOutFlag, bWithTime,\
    bWithMillisecond, bWithSrcFile, bWithFunction, szDestUrl) \
    YaoUtil::LogFactory::SetLogAttr(szLogID, bEnable, nOutFlag, bWithTime,\
    bWithMillisecond, bWithSrcFile, bWithFunction, szDestUrl)
#endif

#ifndef YAOLOG_SET_LOGFILE_ATTR
#define YAOLOG_SET_LOGFILE_ATTR(szLogID, bOverwrite, bFlushBufferImmediately,\
    bGenNewLogFileDaily, szLogFileDir, szLogFileName) \
    YaoUtil::LogFactory::SetLogFileAttr(szLogID, bOverwrite, bFlushBufferImmediately,\
    bGenNewLogFileDaily, szLogFileDir, szLogFileName)
#endif

#ifndef YAOLOG_SET_ATTR_FROM_CONFIG_FILE
#define YAOLOG_SET_ATTR_FROM_CONFIG_FILE(szLogID, szINI) \
    YaoUtil::LogFactory::SetAttrFromConfigFile(szLogID, szINI)
#endif

// for LOG_TYPE_BIN
#ifndef LOGBIN__
    #define LOGBIN__(szLogID, pData, nSize) do {\
        if (YaoUtil::LogFactory::Disabled()) break;\
        YaoUtil::LogFactory::m_tm.Lock();\
        YaoUtil::BaseLog *p = YaoUtil::LogFactory::Get(szLogID);\
        if ((!p) || (p->IsTextLog())) { YaoUtil::LogFactory::m_tm.Unlock(); break; }\
        p->LogBin(pData, nSize);\
        YaoUtil::LogFactory::m_tm.Unlock();\
        } while (0)
#endif

// for LOG_TYPE_FORMATTED_BIN
#ifndef LOGBIN_F__
    #define LOGBIN_F__(szLogID, szTitle, pData, nSize) do {\
        if (YaoUtil::LogFactory::Disabled()) break;\
        YaoUtil::LogFactory::m_tm.Lock();\
        YaoUtil::BaseLog *p = YaoUtil::LogFactory::Get(szLogID);\
        if ((!p) || (!p->IsTextLog())) { YaoUtil::LogFactory::m_tm.Unlock(); break; }\
        p->LogFormattedBin(__FILE__, __FUNCTION__, __LINE__, szTitle, pData, nSize);\
        YaoUtil::LogFactory::m_tm.Unlock();\
        } while (0)
#endif

// for LOG_TYPE_TEXT
#ifndef LOG__
    #ifdef _YAOLOG_WIN32_
        #define LOG__(szLogID, szFormat, ...) do {\
            if (YaoUtil::LogFactory::Disabled()) break;\
            YaoUtil::LogFactory::m_tm.Lock();\
            YaoUtil::BaseLog *p = YaoUtil::LogFactory::Get(szLogID);\
            if ((!p) || (!p->IsTextLog())) { YaoUtil::LogFactory::m_tm.Unlock(); break; }\
            p->Log(__FILE__, __FUNCTION__, __LINE__, szFormat, __VA_ARGS__);\
            YaoUtil::LogFactory::m_tm.Unlock();\
            } while (0)
    #else
        #define LOG__(szLogID, szFormat, ...) do {\
            if (YaoUtil::LogFactory::Disabled()) break;\
            YaoUtil::LogFactory::m_tm.Lock();\
            YaoUtil::BaseLog *p = YaoUtil::LogFactory::Get(szLogID);\
            if ((!p) || (!p->IsTextLog())) { YaoUtil::LogFactory::m_tm.Unlock(); break; }\
            p->Log(__FILE__, __FUNCTION__, __LINE__, szFormat, ##__VA_ARGS__);\
            YaoUtil::LogFactory::m_tm.Unlock();\
            } while (0)
    #endif
#endif
#ifndef LOGA__
    #ifdef _YAOLOG_WIN32_
        #define LOGA__(szLogID, szFormat, ...) do {\
            if (YaoUtil::LogFactory::Disabled()) break;\
            YaoUtil::LogFactory::m_tm.Lock();\
            YaoUtil::BaseLog *p = YaoUtil::LogFactory::Get(szLogID);\
            if ((!p) || (!p->IsTextLog())) { YaoUtil::LogFactory::m_tm.Unlock(); break; }\
            p->LogA(__FILE__, __FUNCTION__, __LINE__, szFormat, __VA_ARGS__);\
            YaoUtil::LogFactory::m_tm.Unlock();\
            } while (0)
    #else
        // linux has no LOGA__...
    #endif
#endif
#ifndef LOGW__
    #ifdef _YAOLOG_WIN32_
        #define LOGW__(szLogID, szFormat, ...) do {\
            if (YaoUtil::LogFactory::Disabled()) break;\
            YaoUtil::LogFactory::m_tm.Lock();\
            YaoUtil::BaseLog *p = YaoUtil::LogFactory::Get(szLogID);\
            if ((!p) || (!p->IsTextLog())) { YaoUtil::LogFactory::m_tm.Unlock(); break; }\
            p->LogW(__FILE__, __FUNCTION__, __LINE__, szFormat, __VA_ARGS__);\
            YaoUtil::LogFactory::m_tm.Unlock();\
            } while (0)
    #else
        // linux has no LOGW__...
    #endif
#endif

#endif


namespace YaoUtil {
///////////////////////////////////////////////////////////////
// TinyMutex
///////////////////////////////////////////////////////////////
class YAOLOG_EXPORT_API TinyMutex
{
public:
    TinyMutex();
    ~TinyMutex();
    void Lock();
    void Unlock();

private:
#ifdef _YAOLOG_WIN32_
    CRITICAL_SECTION m_handle;
#else
    pthread_mutex_t m_handle;
#endif

private:
    TinyMutex(const TinyMutex&);
    const TinyMutex& operator=(const TinyMutex&);
};


///////////////////////////////////////////////////////////////
// StrUtil
///////////////////////////////////////////////////////////////
class StrUtil
{
public:
    static void vFormat(yao_tstring& s, const TCHAR *fmt, va_list ap);
    static void vFormatA(std::string& s, const char *fmt, va_list ap);
    static bool CompareNoCase(const std::string& strIn1, const std::string& strIn2);
    static std::string GetSysTimeStr(bool withMillisecond);
    static std::string GetSysTimeStrForFileName(bool isTextFile);
    static int SplitString(
        const std::string& strIn,
        const std::string& strDelimiter,
        std::vector<std::string>& ret,
        bool retWithEmpty);
    static size_t IndexOfFirst(const std::string& strIn, const std::string& strMatch);
    static size_t IndexOfLast(const std::string& strIn, const std::string& strMatch);

    //in:  http://www.baidu.com:80/1.html
    //out: www.baidu.com  /1.html  80
    static bool ParseUrl(
        const std::string& strUrl,
        std::string& strServer,
        std::string& strPath,
        int& nPort);

#ifdef _YAOLOG_WIN32_
    static void vFormatW(std::wstring& s, const wchar_t *fmt, va_list ap);
    static std::string WStrToStr(const std::wstring& strIn);
    static std::wstring StrToWStr(const std::string& strIn);
#endif
};


///////////////////////////////////////////////////////////////
// PathUtil
///////////////////////////////////////////////////////////////
class PathUtil
{
public:
    static std::string ModuleFileDirectory_();

    static std::string GetDirectory_(const std::string& fileFullPath);

    static std::string GetFile_(const std::string& fileFullPath);

    // directory+folder or directory+file
    static std::string PathCombine_(const std::string& path1, const std::string& path2);

    // path_ -> directory or fileFullPath
    static bool PathFileExists_(const std::string& path_);

    static bool IsStrJustFileName_(const std::string& str);

    static void CreateFolder_(const std::string& directory_);
};


///////////////////////////////////////////////////////////////
// IniReader
///////////////////////////////////////////////////////////////
class IniReader
{
public:
    static bool ReadStrA(const std::string& section, const std::string& key_,
        std::string& value_, const std::string& defaultValue,
        const std::string& filePath);

    static int ReadIntA(const std::string& section, const std::string& key_,
        int defaultValue, std::string& filePath);

private:
    static int ReadStr_(const char *section, const char *key_, char *value_,
        int size_, const char *defaultValue, const char *file);
    static int LoadIniFile(const char *file, char *buf, int *file_size);
    static int NewLine(char c);
    static int EndOfStr(char c);
    static int LeftBrace(char c);
    static int RightBrace(char c);
    static int ParseFile(
        const char *section, const char *key_, const char *buf,
        int *sec_s, int *sec_e, int *key_s, int *key_e, int *value_s, int *value_e);
};


///////////////////////////////////////////////////////////////
// MachineID
///////////////////////////////////////////////////////////////
class YAOLOG_EXPORT_API MachineID
{
public:
    // I use MAC address as a machine's unique identifier.
    // Maybe it is not an "absolute unique identifier" in reality,
    // but it is good enough to meet our requirements here.
    static std::string GetMachineID();

private:
#ifdef _YAOLOG_WIN32_
    static long GetMACAddressMSW(unsigned char * result);
#else
    static long GetMACAddressLinux(unsigned char * result);
#endif
};


///////////////////////////////////////////////////////////////
// FileUtil
///////////////////////////////////////////////////////////////
#ifdef _YAOLOG_WIN32_
typedef HANDLE P_FILE;
#else
typedef FILE* P_FILE;
#endif
class FileUtil
{
public:
    static P_FILE Open(const std::string& path_, bool overwrite_);
    static void Write(P_FILE pFile, const char *pBuf, unsigned int bufSize, bool bFlushBuffer);
    static void Close(P_FILE pFile);
    static bool Valid(P_FILE pFile);
};


///////////////////////////////////////////////////////////////
// Encoding
///////////////////////////////////////////////////////////////
class Encoding
{
public:
    // base64 without newline
    static std::string Base64Encode(const unsigned char *bytes_to_encode, unsigned int in_len);
    static std::string Base64Decode(std::string const& encoded_string);

    // see http://en.wikipedia.org/wiki/Percent-encoding
    static std::string UrlEncode(const std::string& str);
    static std::string UrlDecode(const std::string& str);

private:
    static bool IsBase64(unsigned char c);
    static unsigned char ToHex(unsigned char x);
    static unsigned char FromHex(unsigned char x);
    const static std::string base64_chars;
};


///////////////////////////////////////////////////////////////
// HttpConn
///////////////////////////////////////////////////////////////
class HttpConn
{
public:
    HttpConn(const std::string& host_, int port_);
    ~HttpConn();

    bool connect();
    void close();

    // method_  -> "GET", "POST" etc...
    // path_    -> "/index.html"
    void putrequest(const char *method_, const char *path_);
    void putheader(const std::string& header_, const std::string& value_);
    void putheader(const std::string& header_, int numericvalue);
    void endheaders();
    void send(const unsigned char *buf, int numbytes);
    void rev();

private:
    // Try to work out address from string
    // returns 0 if bad
    struct in_addr host2addr(const char *host_name);

    std::string m_host;
    int m_port;
    int m_sock;
    std::vector<std::string> m_buffer;
};


///////////////////////////////////////////////////////////////
// TinyThread
///////////////////////////////////////////////////////////////
class TinyThread;

struct ThreadStartInfo
{
    void (*pFn)(void *);
    void *pArg;
    int cycleSpanMilliseconds;
    bool *pThreadEnd;
    TinyThread *pThread;
};

class TinyThread
{
public:
    TinyThread();

    void SetSig(int timeout_millisecond);
    void Join(int timeout_millisecond);
    bool Start(
        void (*pFn)(void *),
        void *pArg,
        int cycleSpanMilliseconds,
        bool *pThreadEnd);

private:
#ifdef _YAOLOG_WIN32_
    HANDLE m_handle;
    unsigned int m_threadID;
    HANDLE m_event;
#else
    pthread_t m_handle;
    pthread_cond_t m_cond;
    pthread_mutex_t m_mutex;
#endif

#ifdef _YAOLOG_WIN32_
    static unsigned WINAPI Run(void *pArg);
#else
    static void *Run(void *pArg);
#endif
};


///////////////////////////////////////////////////////////////
// Log classes
///////////////////////////////////////////////////////////////
enum LOG_TYPE
{
    LOG_TYPE_TEXT,
    LOG_TYPE_BIN,
    LOG_TYPE_FORMATTED_BIN
};

enum OUT_FLAG
{
    OUT_FLAG_FILE               = 1<<0,
    OUT_FLAG_STDOUT             = 1<<1,
    OUT_FLAG_REMOTE             = 1<<2,
    OUT_FLAG_OUTPUTDEBUGSTRING  = 1<<3  // windows only
};

struct LogParams
{
    bool bEnable;
    int nOutFlag;
    bool bWithTime;
    bool bWithMillisecond;
    bool bWithSrcFile;
    bool bWithFunction;
    std::string destUrl;

    // for OUT_FLAG_FILE
    bool bOverwrite;              
    bool bFlushBufferImmediately;
    bool bGenNewLogFileDaily;
    std::string logFileDir;
    std::string logFileName;
    
    LogParams()
    {
        Reset();
    }

    void Reset()
    {
        bEnable = false;
        nOutFlag = OUT_FLAG_STDOUT;
        bWithTime = true;
        bWithMillisecond = false;
        bWithSrcFile = false;
        bWithFunction = false;
        destUrl.clear();

        bOverwrite = true;
        bFlushBufferImmediately = false;
        bGenNewLogFileDaily = false;
        logFileDir.clear();
        logFileName.clear();
    }

    bool operator==(const LogParams &lp) const
    {
        return (bEnable == lp.bEnable &&
            nOutFlag == lp.nOutFlag &&
            bWithTime == lp.bWithTime &&
            bWithMillisecond == lp.bWithMillisecond &&
            bWithSrcFile == lp.bWithSrcFile &&
            bWithFunction == lp.bWithFunction &&
            destUrl == lp.destUrl &&
            bOverwrite == lp.bOverwrite &&
            bFlushBufferImmediately == lp.bFlushBufferImmediately &&
            bGenNewLogFileDaily == lp.bGenNewLogFileDaily &&
            logFileDir == lp.logFileDir &&
            logFileName == lp.logFileName);
    }  
};

class BaseLog;

class YAOLOG_EXPORT_API LogFactory
{
public:
    static void Init();
    static void Exit();

    static bool Create(const char *szLogID, bool bEnable, LOG_TYPE logType);

    static BaseLog *Get(const char *szLogID);

    // 1. szDestUrl -> http server address, for example "http://192.168.1.200/default.aspx"
    // 2. post data content:
    //    logID=v1&isText=v2&machineID=v3&logData=v4
    //    v2 -> 0 or 1
    //    v4 -> log data, have used base64encode and urlencode
    static void SetLogAttr(
        const char *szLogID,
        bool bEnable,
        int nOutFlag,
        bool bWithTime,
        bool bWithMillisecond,
        bool bWithSrcFile,
        bool bWithFunction,
        const char *szDestUrl);

    // 1. if szLogFileDir is NULL or "", it means
    //    use default dir -> "module file dir\log\"
    // 2. if szLogFileName is NULL or "", it means
    //    use default filename -> "logID_time.log" or "logID_time.bl"
    // 3. bGenNewLogFileDaily takes effect
    //    only if szLogFileName is NULL or ""
    static void SetLogFileAttr(
        const char *szLogID,
        bool bOverwrite,
        bool bFlushBufferImmediately,
        bool bGenNewLogFileDaily,
        const char *szLogFileDir,
        const char *szLogFileName);

    // szINI: config file name(in module file dir) or config file full path
    static void SetAttrFromConfigFile(const char *szLogID, const char *szINI);

    // call DisableAllLogs(true) will disable all logs totally, 
    // then all logs are disabled and cannot be enable,
    // the only way to cancel it is by calling DisableAllLogs(false)
    static void DisableAllLogs(bool disableAll) { m_disableAll = disableAll; }
    static bool Disabled() { return m_disableAll; }

    static TinyMutex m_tm;

private:
    //static void Destroy(const char *szLogID);
    static bool Exists(const char *szLogID);
    static void BkWorker(void *pArg);
    static void PostData(const std::string& logID, const std::vector<std::string>& logData);

    static std::map<std::string, BaseLog*> m_allLoggers;
    static bool m_threadEnd;
    static TinyThread *m_pTT;
    static bool m_inited;
    static bool m_disableAll;

    LogFactory(const LogFactory&);
    const LogFactory& operator=(const LogFactory&);
};

class YAOLOG_EXPORT_API BaseLog
{
    friend class LogFactory;

public:
    BaseLog(const char *szLogID, bool bEnable);
    virtual ~BaseLog();

    void SetAttr(
        bool bEnable,
        int nOutFlag,
        bool bWithTime,
        bool bWithMillisecond,
        bool bWithSrcFile,
        bool bWithFunction,
        const std::string& destUrl,
        bool bOverwrite,
        bool bFlushBufferImmediately,
        bool bGenNewLogFileDaily,
        const std::string& logFileDir,
        const std::string& logFileName);

    void SetAttrFromConfigFile(const char *szINI);

    const LogParams* GetLogParams() { return &m_params; }

    // LOG_TYPE_FORMATTED_BIN is essentially a text logger
    bool IsTextLog() { return m_logType != LOG_TYPE_BIN; }

    virtual void Log(const char *szSrcFile, const char *szFunction,
        int nLine, const TCHAR *szFormat, ...) = 0;
#ifdef _YAOLOG_WIN32_
    virtual void LogA(const char *szSrcFile, const char *szFunction,
        int nLine, const char *szFormat, ...) = 0;
    virtual void LogW(const char *szSrcFile, const char *szFunction,
        int nLine, const wchar_t *szFormat, ...) = 0;
#endif
    virtual void LogBin(const void *pData, int nSize) = 0;
    virtual void LogFormattedBin(const char *szSrcFile,
        const char *szFunction, int nLine, const char *szTitle,
        const void *pData, int nSize) = 0;

protected:
    LOG_TYPE m_logType;
    LogParams m_params;
    std::string m_iniFullPath;
    std::string m_logFullPath;
    std::string m_logID;
    tm m_localTime;

    bool NewDay();
    bool NeedChangeLogFilePath(
        const LogParams& lp1, const LogParams& lp2);
    void SetLogFilePath();
    bool ParseConfigFile(LogParams& lp);

    // lazy-init: doesn't open the log file until actually start to write...
    P_FILE GetFilePointer();

    int MakeLogText(
        const std::string& str,
        const std::string& srcFile,
        const std::string& function_,
        int nLine);

private:
    BaseLog(const BaseLog&);
    const BaseLog& operator=(const BaseLog&);
};

class YaoLog : public BaseLog
{
public:
    YaoLog(const char *szLogID, bool bEnable);
    virtual ~YaoLog();
    virtual void Log(const char *szSrcFile, const char *szFunction,
        int nLine, const TCHAR *szFormat, ...);
#ifdef _YAOLOG_WIN32_
    virtual void LogA(const char *szSrcFile, const char *szFunction,
        int nLine, const char *szFormat, ...);
    virtual void LogW(const char *szSrcFile, const char *szFunction,
        int nLine, const wchar_t *szFormat, ...);
#endif

private:
    void DoLog(
        const std::string& str,
        const std::string& srcFile,
        const std::string& function_,
        int nLine);

    // unuseful...
    virtual void LogBin(const void *pData, int nSize) { assert(0); }
    virtual void LogFormattedBin(const char *szSrcFile,
        const char *szFunction, int nLine, const char *szTitle,
        const void *pData, int nSize) { assert(0); }
};

class YaoBinLog : public BaseLog
{
public:
    YaoBinLog(const char *szLogID, bool bEnable);
    virtual void LogBin(const void *pData, int nSize);

private:
    // unuseful...
    virtual void Log(const char *szSrcFile, const char *szFunction,
        int nLine, const TCHAR *szFormat, ...) { assert(0); }
#ifdef _YAOLOG_WIN32_
    virtual void LogA(const char *szSrcFile, const char *szFunction,
        int nLine, const char *szFormat, ...) { assert(0); }
    virtual void LogW(const char *szSrcFile, const char *szFunction,
        int nLine, const wchar_t *szFormat, ...) { assert(0); }
#endif
    virtual void LogFormattedBin(const char *szSrcFile,
        const char *szFunction, int nLine, const char *szTitle,
        const void *pData, int nSize) { assert(0); }
};

class YaoFormattedBinLog : public BaseLog
{
public:
    YaoFormattedBinLog(const char *szLogID, bool bEnable);
    virtual void LogFormattedBin(const char *szSrcFile,
        const char *szFunction, int nLine, const char *szTitle,
        const void *pData, int nSize);

private:
    std::string FormatBin(const std::string& title, const void *pData, int nSize);

    // unuseful...
    virtual void Log(const char *szSrcFile, const char *szFunction,
        int nLine, const TCHAR *szFormat, ...) { assert(0); }
#ifdef _YAOLOG_WIN32_
    virtual void LogA(const char *szSrcFile, const char *szFunction,
        int nLine, const char *szFormat, ...) { assert(0); }
    virtual void LogW(const char *szSrcFile, const char *szFunction,
        int nLine, const wchar_t *szFormat, ...) { assert(0); }
#endif
    virtual void LogBin(const void *pData, int nSize) { assert(0); }
};

} // namespace YaoUtil

#ifdef _YAOLOG_WIN32_
#pragma warning(pop)
#endif

#endif // _YAOLOG_H_

//////////////////////////////////////////////////////////
// config file example
//
// [MyLogID]
// Enable = 1
// OutFlag = file|stdout|remote|outputdebugstring
// WithTime = 1
// WithMillisecond = 0
// WithSrcFile = 0
// WithFunction = 0
// DestUrl = http://...
// Overwrite = 1
// FlushBufferImmediately = 0
// GenNewLogFileDaily = 0
// LogFileDir = c:\logfile
// LogFileName = log1.txt
//////////////////////////////////////////////////////////

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
China China
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions