I've been always updating my log methods, because I started SDL and I needed some new methods. First, I made difference between debug and release, and so console and file. But now I want a more powerful method, which handles the console with implicating the file, and works like C++ streams. I would like to know if it's a good design.
#ifndef LOGGING_INCLUDED
#define LOGGING_INCLUDED
#include <ostream>
#include <vector>
#include <ctime>
#include <iomanip>
namespace BSSE_System
{
/*bool addStream(std::ostream* os);
bool addStream(std::ostream* os, unsigned short& channel);
void doLog(const unsigned short& channel, const std::string& message, bool doTime = true);*/ //on specific channel;
/*void doLog(const std::string& message, bool doTime = true);*/ //on all channels
class LogObject
{
public:
LogObject()
{
streams.resize(0);
doTime = true;
}
bool addStream(std::ostream* os)
{
if (os == NULL)
{
return false;
}
else
{
streams.push_back(os);
return true;
}
}
bool addStream(std::ostream* os, unsigned short& channel)
{
if (os == NULL)
{
return false;
}
else
{
streams.push_back(os);
channel = streams.size() - 1;
return true;
}
}
void set_printTime(const bool& state)
{
doTime = state;
}
template <typename T>
friend LogObject& operator<< (LogObject& lo, const T& message)
{
for (std::vector<std::ostream*>::iterator it = lo.streams.begin();
it < lo.streams.end(); ++it)
{
if (lo.doTime)
{
time_t rawTime = time(NULL);
tm * timeStruct = localtime(&rawTime);
**it << std::setw(2) << timeStruct->tm_hour << ':'
<< std::setw(2) << timeStruct->tm_min << ':'
<< std::setw(2) << timeStruct->tm_sec << " - ";
}
**it << message;
}
return lo;
}
void stringOut(const std::string& stringmes, const unsigned int channel)
{
if (doTime)
{
time_t rawTime = time(NULL);
tm * timeStruct = localtime(&rawTime);
*(streams.at(channel)) << std::setw(2) << timeStruct->tm_hour
<< ':' << std::setw(2) << timeStruct->tm_min << ':'
<< std::setw(2) << timeStruct->tm_sec << " - ";
}
*(streams.at(channel)) << stringmes;
}
void stringOut(const std::string& stringmes)
{
for (unsigned int i = 0; i < streams.size(); ++i)
{
stringOut(stringmes, i);
}
}
private:
std::vector<std::ostream*> streams;
bool doTime;
bool timeSwitch;
};
extern LogObject logger;
}
#endif // LOGGING_INCLUDED
extern LoggerClass logger; //defined in cpp like for std's cout and cin
So, is this a good, safe method for managing log? I can simply add pointers from iostream objects, and also from fstream objects after opening files. One problem is the time management. I currently don't have method, how to concatenate strings without problems on time (BUT this is not a main problem, it seems resolvable for me).
Also, it's different from classical operator<<
overloads, because we need to define the "very left-hand" part of operation and not the data what is written in streams.
So, is it a good method, should I try to create an inherited ostream class or I should look for a different method?