I got tired of recreating something like it.
LoggingHack.h
#ifdef LOGGING_HACK
class JLogStream
{
public:
virtual ~JLogStream() {
}
};
extern JLogStream* jlogs;
extern JLogStream& operator<< (JLogStream& rlog, const std::string& val);
extern JLogStream& operator<< (JLogStream& rlog, const std::wstring& val);
extern JLogStream& operator<< (JLogStream& rlog, const char* zStr);
extern JLogStream& operator<< (JLogStream& rlog, const wchar_t* zStr);
extern JLogStream& operator<< (JLogStream& rlog, int val);
extern JLogStream& operator<< (JLogStream& rlog, std::stringstream &val);
extern JLogStream& operator<< (JLogStream& rlog, std::wstringstream &val);
#define JLOG( x ) { (*jlogs) << x << "\n"; }
#else
#define JLOG( x ) ;
#endif
LoggingHack.cpp
#ifdef LOGGING_HACK
#include <sstream>
#include "LoggingHack.h"
class JLogStreamImpl : public JLogStream
{
private:
FILE* jlog_fout1;
FILE* jlog_fout2;
FILE* jlog_fout3;
public:
JLogStreamImpl()
{
std::stringstream ss1;
ss1 << "c:\\delme\\" << LOGGING_HACK_FILE_BASE_NAME << ".log";
std::stringstream ss2;
ss2 << "c:\\delme\\" << LOGGING_HACK_FILE_BASE_NAME << " - " << ::GetTickCount() << ".log";
std::stringstream ss3;
ss3 << "c:\\delme\\" << LOGGING_HACK_FILE_BASE_NAME << "-rolling.log";
fopen_s(&jlog_fout1, ss1.str().c_str(), "wt");
fopen_s(&jlog_fout2, ss2.str().c_str(), "wt");
fopen_s(&jlog_fout3, ss3.str().c_str(), "at");
log(ss1.str().c_str());
}
void log(const char* zStr)
{
fwrite(zStr, strlen(zStr), 1, jlog_fout1);
fwrite(zStr, strlen(zStr), 1, jlog_fout2);
fwrite(zStr, strlen(zStr), 1, jlog_fout3);
fflush(jlog_fout1);
fflush(jlog_fout2);
fflush(jlog_fout3);
}
void log(const wchar_t* zStr)
{
int ncharLen;
ncharLen = WideCharToMultiByte(CP_UTF8, 0, zStr, -1, NULL, 0, NULL, NULL);
char* zstr = new char[ncharLen];
WideCharToMultiByte(CP_UTF8, 0, zStr, -1, zstr, ncharLen, NULL, NULL);
log("UNICODE:");
log(zstr);
}
void log(int val)
{
std::stringstream ss;
ss << val;
log(ss);
}
void log(std::stringstream &val)
{
log(val.str().c_str());
}
void log(std::wstringstream &val)
{
log(val.str().c_str());
}
};
extern JLogStream& operator<< (JLogStream& rlog, const std::string& val)
{
dynamic_cast<JLogStreamImpl*>(&rlog)->log(val.c_str());
return rlog;
}
extern JLogStream& operator<< (JLogStream& rlog, const std::wstring& val)
{
dynamic_cast<JLogStreamImpl*>(&rlog)->log(val.c_str());
return rlog;
}
extern JLogStream& operator<< (JLogStream& rlog, const char* zStr)
{
dynamic_cast<JLogStreamImpl*>(&rlog)->log(zStr);
return rlog;
}
extern JLogStream& operator<< (JLogStream& rlog, const wchar_t* zStr)
{
dynamic_cast<JLogStreamImpl*>(&rlog)->log(zStr);
return rlog;
}
extern JLogStream& operator<< (JLogStream& rlog, int val)
{
dynamic_cast<JLogStreamImpl*>(&rlog)->log(val);
return rlog;
}
extern JLogStream& operator<< (JLogStream& rlog, std::stringstream &val)
{
dynamic_cast<JLogStreamImpl*>(&rlog)->log(val);
return rlog;
}
extern JLogStream& operator<< (JLogStream& rlog, std::wstringstream &val)
{
dynamic_cast<JLogStreamImpl*>(&rlog)->log(val);
return rlog;
}
JLogStreamImpl theLogStream;
JLogStream* jlogs = &theLogStream;
#else
#define jlog(s) ;
#define jlog(s1, s2) ;
#endif
Include this in one cpp file of the dll or exe: Replacing LogBaseName with the desired name
#define LOGGING_HACK
#define LOGGING_HACK_FILE_BASE_NAME "LogBaseName"
#include "..\..\..\..\LoggingHack.cpp"
Include this in the other cpp files of the module:
#define LOGGING_HACK
#include "..\..\..\..\LoggingHack.h"
Use it like this:
JLOG(__FILE__ << "@" << __LINE__);