diff --git a/log.cc b/log.cc new file mode 100644 index 0000000000000000000000000000000000000000..40ce561c41a1ee1d6bb7882c6056d61cd6ab54fd --- /dev/null +++ b/log.cc @@ -0,0 +1,91 @@ +/* log.cc + + Mark Woolrich, FMRIB Image Analysis Group + + Copyright (C) 1999-2000 University of Oxford */ + +/* CCOPYRIGHT */ + +#include "log.h" + +namespace Utilities { + + Logger* LogSingleton::logger = NULL; + int LogSingleton::count = 0; + + void Logger::makeDir(const string& pdirname, const string& plogfilename, bool pstream_to_logfile, bool pstream_to_cout) + { + if(logEstablished) + { + logfileout.close(); + } + + dir = pdirname; + logfilename = plogfilename; + stream_to_logfile = pstream_to_logfile; + stream_to_cout = pstream_to_cout; + + // make directory to place results into: + // keep adding "+" until directory is made: + int count = 0; + while(true) + { + if(count >= 20) + { + string s("Cannot create directory " + dir); + throw Exception(s.c_str()); + } + + int ret = system(("mkdir "+ dir + " 2>/dev/null").c_str()); + if(ret == 0) + { + break; + } + dir = dir + "+"; + count++; + } + + // setup logfile + if(stream_to_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()); + } + } + + logEstablished = true; + } + + void Logger::setDir(const string& pdirname, const string& plogfilename, bool pstream_to_logfile, bool pstream_to_cout) + { + if(logEstablished) + { + logfileout.close(); + } + + dir = pdirname; + logfilename = plogfilename; + stream_to_logfile = pstream_to_logfile; + stream_to_cout = pstream_to_cout; + + // setup logfile + if(stream_to_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()); + } + } + + logEstablished = true; + } +} + + + + + + diff --git a/log.h b/log.h new file mode 100644 index 0000000000000000000000000000000000000000..6661af7ff92d5eb2a4506935acdb8f1e8e4561e6 --- /dev/null +++ b/log.h @@ -0,0 +1,198 @@ +/* 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 +