-
Mark Woolrich authoredMark Woolrich authored
log.h 4.99 KiB
/* log.h
Mark Woolrich, FMRIB Image Analysis Group
Copyright (C) 1999-2000 University of Oxford */
/* CCOPYRIGHT */
#if !defined(log_h)
#define log_h
#include <iostream>
#include <fstream>
#include <string>
#include <strstream>
#include "newmatap.h"
#include "newmatio.h"
// for the Exception class:
using namespace NEWMAT;
namespace Utilities{
template<class t> string tostring(const t obj)
{
char strc[100];
ostrstream str(strc,100);
str << obj << '\0';
return string(strc);
}
class Logger;
template<class t> Logger& operator<<(Logger& log, const t& obj)
{
if(log.stream_to_logfile)
log.logfileout << obj;
if(log.stream_to_cout)
cout << obj;
return log;
}
class Logger
{
public:
Logger():logEstablished(false) {}
Logger(const string& pdirname, const string& plogfilename = "logfile", bool pstream_to_logfile = true, bool pstream_to_cout = false, bool makedir = true):logEstablished(false)
{
if(makedir)
makeDir(pdirname, plogfilename, pstream_to_logfile, pstream_to_cout);
else
setDir(pdirname, plogfilename, pstream_to_logfile, pstream_to_cout);
}
~Logger() { logfileout.close(); }
/** Need to call makeDir or setDir before Logger can be used */
/** Makes a directory to place results into:
keeps adding "+" to pdirname until unique directory is made. */
/** The stream_to* variables define the streaming behaviour */
void makeDir(const string& pdirname, const string& plogfilename = "logfile", bool pstream_to_logfile = true, bool pstream_to_cout = false);
/** Sets an existing directory to place results into. */
/** The stream_to* variables define the streaming behaviour */
void setDir(const string& pdirname, const string& plogfilename = "logfile", bool pstream_to_logfile = true, bool pstream_to_cout = false);
/** Closes old logfile buffer and attempts to open new one with name specified and sets streaming to logfile on */
void setLogFile(const string& plogfilename);
const string& getDir() const { if(!logEstablished)throw Exception("Log not setup");return dir; }
const string& getLogFileName() const { if(!logEstablished)throw Exception("Log not setup");return logfilename; }
/** returns passed in filename appended onto the end of the dir name */
const string appendDir(const string& filename) const;
/** allows streaming into cout and/or logfile depending upon the */
/** stream_to_cout and stream_to_logfile respectively */
/** use like a normal ostream, e.g. log.str() << "hello" << endl */
/** NOTE: can simply stream straight to Log instead, e.g. log << "hello" << endl */
Logger& str();
/** sets whether or not you stream to cout */
void set_stream_to_cout(bool in = true) { stream_to_cout = in; }
/** sets whether or not you stream to logfile */
void set_stream_to_logfile(bool in = true) {
if(!stream_to_logfile && in)
{
if(logfileout.bad())
{
cerr << "Warning: Unable to stream to logfile " << logfilename << ". Need to have called log.setLogFile. Therefore, no streaming to logfile will be performed" << endl;
}
}
else stream_to_logfile = in;
}
private:
const Logger& operator=(Logger&);
Logger(Logger&);
string dir;
ofstream logfileout;
string logfilename;
bool logEstablished;
bool stream_to_logfile;
bool stream_to_cout;
template<class t>
friend Logger& operator<<(Logger& log, const t& obj);
};
class LogSingleton
{
public:
static Logger& getInstance();
~LogSingleton() { delete logger; }
/** hacked in utility provides a global counter for general use: */
static int counter() { return count++; }
private:
LogSingleton() {}
const LogSingleton& operator=(LogSingleton&);
LogSingleton(LogSingleton&);
static Logger* logger;
static int count;
};
typedef LogSingleton Log;
inline Logger& LogSingleton::getInstance(){
if(logger == NULL)
logger = new Logger();
return *logger;
}
inline void Logger::setLogFile(const string& plogfilename) {
if(!logEstablished)
{
throw Exception("Log not setup");
}
logfileout.close();
logfilename = plogfilename;
// setup logfile
logfileout.open((dir + "/" + logfilename).c_str(), ios::out);
if(logfileout.bad())
{
throw Exception(string(string("Unable to setup logfile ")+logfilename+string(" in directory ")+dir).c_str());
}
stream_to_logfile = true;
logEstablished = true;
}
inline Logger& Logger::str() {
if(!logEstablished)
{
throw Exception("Log not setup");
}
return *this;
}
inline const string Logger::appendDir(const string& filename) const {
if(!logEstablished)
{
throw Exception("Log not setup");
}
return dir + "/" + filename;
}
}
#endif