#ifndef CLASSES_LOGGING_H__
#define CLASSES_LOGGING_H__#include <iostream>
#include <iomanip>
#include <sstream>
#include <Windows.h>#define DISALLOW_EVIL_CONSTRUCTORS(TypeName) \
TypeName(const TypeName&); void operator=(const TypeName&)enum LoggingSeverity
{
LS_SENSITIVE,
LS_VERBOSE,
LS_INFO,
LS_WARNING,
LS_ERROR,
INFO = LS_INFO,
WARNING = LS_WARNING,
LERROR = LS_ERROR
};enum LogErrorContext
{
ERRCTX_NONE,
ERRCTX_ERRNO,
ERRCTX_HRESULT
};class LogMessage
{
public:
LogMessage(const char* file,
int line,
LoggingSeverity sev,
LogErrorContext err_ctx = ERRCTX_NONE,
int err = 0,
const char* module = NULL);~LogMessage();
std::ostream& stream()
{
return print_stream_;
}static void ResetTimestamps();
private:
static const char* Describe(LoggingSeverity sev);
static const char* DescribeFile(const char* file);
static long TimeDiff(unsigned long later, unsigned long earlier);
static bool TimeIsBetween(unsigned long later, unsigned long middle, unsigned long earlier);std::ostringstream print_stream_;
LoggingSeverity severity_;
std::string extra_;
static unsigned long start_;
HANDLE hFile_;
DISALLOW_EVIL_CONSTRUCTORS(LogMessage);
};#define LOG_INFO() LogMessage(__FILE__, __LINE__, LS_INFO).stream()
#define LOG(sev) LogMessage(__FILE__, __LINE__, sev).stream()
#define LOG_F(sev) LOG(sev) << __FUNCTION__ << ": "
#define PLOG(sev, err) LogMessage(__FILE__, __LINE__, sev, ERRCTX_ERRNO, err).stream()
#define LOG_ERR(sev) LogMessage(__FILE__, __LINE__, sev, ERRCTX_ERRNO, errno).stream()
#define LOG_GLE(sev) LogMessage(__FILE__, __LINE__, sev, \
ERRCTX_HRESULT, GetLastError()).stream()#define LOG_GLEM(sev, mod) LogMessage(__FILE__, __LINE__, sev, \
ERRCTX_HRESULT, GetLastError(), mod) .stream()
#endif
#include "logging.h"extern "C" BOOL WINAPI IsDebuggerPresent(void);
unsigned long LogMessage::start_ = GetTickCount();
LogMessage::LogMessage(const char* file, int line, LoggingSeverity sev,
LogErrorContext err_ctx, int err, const char* module)
: severity_(sev)
{
unsigned long time = TimeDiff(GetTickCount(), start_);
print_stream_ << "[" << std::setfill(‘0‘) << std::setw(3) << (time / 60000)
<< ":" << std::setw(2) << (time %60000)/1000
<< ":" << std::setw(3) << time %1000 << std::setfill(‘ ‘)
<< "] ";DWORD id = GetCurrentThreadId();
print_stream_ << "[0x" << std::setfill(‘0‘) << std::setw(8)
<< std::hex << id << std::dec << "] ";print_stream_ << Describe(sev) << "(" << DescribeFile(file)
<< ":" << line << "): ";if (err_ctx != ERRCTX_NONE)
{
std::ostringstream tmp;
tmp << "[0x" << std::setfill(‘0‘) << std::hex << std::setw(8) << err << "]";
switch (err_ctx)
{
case ERRCTX_ERRNO:
{
tmp << " " << strerror(err);
break;
}
case ERRCTX_HRESULT:
{
char msgbuf[256]={0};
DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM;
HMODULE hmod = GetModuleHandleA(module);
if (hmod)
flags |= FORMAT_MESSAGE_FROM_HMODULE;
if (DWORD len = FormatMessageA(
flags, hmod, err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
msgbuf, sizeof(msgbuf) / sizeof(msgbuf[0]), NULL))
{
while ((len > 0) &&
isspace(static_cast<unsigned char>(msgbuf[len-1])))
{
msgbuf[--len] = 0;
}
tmp << " " << msgbuf;
}
break;
}default:
break;
}
extra_ = tmp.str();
}
}LogMessage::~LogMessage()
{
if (!extra_.empty())
print_stream_ << " : " << extra_;
print_stream_ << "\r\n";
const std::string& str = print_stream_.str();static bool debugger_present = (IsDebuggerPresent() != FALSE);
if (debugger_present)
{
OutputDebugStringA(str.c_str());
}
else
{
hFile_ = ::CreateFileA("Test.txt",GENERIC_WRITE,0,0,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
if(INVALID_HANDLE_VALUE != hFile_)
{
unsigned long written=0L;::SetFilePointer (hFile_, 0, NULL, FILE_END);
::WriteFile(hFile_, str.data(), str.size(), &written, 0);FlushFileBuffers(hFile_);
::CloseHandle(hFile_);
}
else
{
hFile_ = NULL;
}
}
}void LogMessage::ResetTimestamps()
{
start_ = GetTickCount();
}const char* LogMessage::Describe(LoggingSeverity sev)
{
switch (sev)
{
case LS_SENSITIVE: return "Sensitive";
case LS_VERBOSE: return "Verbose";
case LS_INFO: return "Info";
case LS_WARNING: return "Warning";
case LS_ERROR: return "Error";
default: return "<unknown>";
}
}const char* LogMessage::DescribeFile(const char* file)
{
const char* end1 = ::strrchr(file, ‘/‘);
const char* end2 = ::strrchr(file, ‘\\‘);
if (!end1 && !end2)
return file;
else
return (end1 > end2) ? end1 + 1 : end2 + 1;
}bool LogMessage::TimeIsBetween(unsigned long later, unsigned long middle, unsigned long earlier)
{
if (earlier <= later)
{
return ((earlier <= middle) && (middle <= later));
}
else
{
return !((later < middle) && (middle < earlier));
}
}long LogMessage::TimeDiff(unsigned long later, unsigned long earlier)
{
unsigned long LAST = 0xFFFFFFFF;
unsigned long HALF = 0x80000000;
if (TimeIsBetween(earlier + HALF, later, earlier))
{
if (earlier <= later)
{
return static_cast<long>(later - earlier);
}
else
{
return static_cast<long>(later + (LAST - earlier) + 1);
}
}
else
{
if (later <= earlier)
{
return -static_cast<long>(earlier - later);
}
else
{
return -static_cast<long>(earlier + (LAST - later) + 1);
}
}
}
(转)日志类