// log.h #ifndef LOG_H_INCLUDED #define LOG_H_INCLUDED #include #include #include using std::string; enum loglevel { LOGLEVEL_INFO, LOGLEVEL_STATUS, LOGLEVEL_WARN, LOGLEVEL_ERROR, LOGLEVEL_CRITICAL }; enum logopt { LOGOPT_USE_FILE = 0x1, LOGOPT_USE_CONSOLE = 0x2, LOGOPT_USE_STDOUT = 0x4, LOGOPT_LOG_TIME = 0x8, LOGOPT_LOG_LEVEL = 0x10, LOGOPT_OVERWRITE_FILE = 0x20 }; class Log { public: Log(int, string = ""); ~Log(); string log(loglevel, string); std::string formatLog(loglevel, string); template Log& operator<<(T t); private: std::fstream logfile; std::ostringstream msgStream; bool usingFile, usingConsole, usingStdout, loggingTime, loggingLevel; }; #endif // LOG_H_INCLUDED // log.cpp #include #include #include #include #include #include "log.h" using std::string; using std::cout; using std::cerr; Log::Log(int options, string path) { usingFile = false; usingConsole = false; usingStdout = false; loggingLevel = false; loggingTime = false; if(options & LOGOPT_USE_FILE) { usingFile = true; if(options & LOGOPT_OVERWRITE_FILE) // Append by default, overwrite if specified. logfile.open(path.data(), std::fstream::trunc); else logfile.open(path.data(), std::fstream::app); } if(options & LOGOPT_USE_CONSOLE) usingConsole = true; if(options & LOGOPT_USE_STDOUT) usingStdout = true; if(options & LOGOPT_LOG_TIME) loggingTime = true; if(options & LOGOPT_LOG_LEVEL) loggingLevel = true; } string Log::formatLog(loglevel level, string message) { static time_t timer = time(NULL); string logMessage; if(loggingTime) logMessage = asctime(localtime(&timer)); logMessage += " | "; if(loggingLevel) { switch(level) { case LOGLEVEL_INFO: break; case LOGLEVEL_STATUS: logMessage += "STATUS: "; break; case LOGLEVEL_WARN: logMessage += "WARNING: "; break; case LOGLEVEL_ERROR: logMessage += "ERROR: "; break; case LOGLEVEL_CRITICAL: logMessage += "***CRITICAL***: "; break; default: break; } } logMessage += message; return message.data(); } string Log::log(loglevel level, string message) { string formatted = formatLog(level, message); if(usingFile) logfile << formatted; //if(usingConsole) // Output to GUI console - NOT IMPLEMENTED if(usingStdout) { if(level < LOGLEVEL_WARN) cout << formatted; else cerr << formatted; } return formatted; } template Log& Log::operator<<(T t) { msgStream << t; return *this; } Log::~Log() { if(logfile.is_open()) logfile.close(); }