00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifndef UTILS_LOG_H
00010 #define UTILS_LOG_H
00011
00012 #include <string>
00013 #include <list>
00014 #include <strstream>
00015 #include <fstream>
00016
00017 #include "receiver.h"
00018
00019 using namespace std;
00020
00021 namespace utils {
00022
00024
00046 namespace logging {
00047
00049
00054 class msg: public string
00055 {
00056 public:
00058
00059 const char* file;
00060
00062
00063 int line;
00064
00066 msg(const char* f, int l):
00067 file(f), line(l)
00068 { }
00069
00071 msg(const msg& m): string(m), file(m.file), line(m.line)
00072 { }
00073
00075 msg& operator = (const msg& m)
00076 {
00077 string::operator = (m); file = m.file; line = m.line;
00078 return *this;
00079 }
00080 };
00081
00082
00084
00092 class listener {
00093 public:
00095 listener();
00096
00098 virtual ~listener();
00099
00101
00107 virtual bool onMsg(const msg& msg) = 0;
00108
00109 protected:
00111
00113 void attach();
00114
00116
00118 void detach();
00119 };
00120
00122
00146 struct ostream_listener: public listener
00147 {
00148 ostream& out;
00149 public:
00150 ostream_listener(ostream& o = cerr);
00151 ~ostream_listener();
00152
00153 bool onMsg(const msg& msg);
00154 };
00155
00157 struct file_listener: private ofstream, public ostream_listener
00158 {
00159 public:
00160 file_listener(const string& name):
00161 ofstream(name.c_str()),
00162 ostream_listener((ofstream&)*this)
00163 { }
00164 };
00165
00166
00168
00169 struct logfunc
00170 {
00171 void operator()(const msg&);
00172 };
00173
00175
00182 class logger: public utils::receiver<msg, logfunc> {
00183 public:
00184 logger();
00185 ~logger();
00186
00187 void attach(listener* p);
00188 bool detach(listener* p);
00189
00190 void handle(const msg& m);
00191
00192 private:
00193 boost::mutex list_mutex;
00194 list<listener*> listeners;
00195
00196 public:
00197 static logger the_logger;
00198 };
00199
00201
00218 class dolog: public msg
00219 {
00220 public:
00221 dolog(const char* file, int line): msg(file, line) {};
00222 dolog(): msg(0, -1) {};
00223 ~dolog();
00224
00225 mutable ostrstream buf;
00226 };
00227
00229
00232 const dolog& operator << (const dolog& l, const string& s);
00233
00235
00236 template <class T>
00237 const dolog& operator << (const dolog& l, const T& val)
00238 {
00239 l.buf << val;
00240 return l;
00241 }
00242
00244 struct nolog
00245 {
00246 nolog(const char* file, int line) {};
00247 nolog() {};
00248 };
00249
00250 template <class T>
00251 inline const nolog& operator << (const nolog& l, const T& val)
00252 { return l; }
00253
00254
00255 }
00256 };
00257
00259
00265 #define log utils::logging::dolog(__FILE__, __LINE__)
00266
00267 #ifdef NDEBUG
00268 #define dlog utils::logging::nolog()
00269 #else
00270
00271
00276 #define dlog utils::logging::dolog(__FILE__, __LINE__)
00277 #endif
00278
00280
00283 #define LOG(v) log << #v << '=' << v << endl;
00284
00286
00290 #define DLOG(v) dlog << #v << '=' << v << endl;
00291
00292 #endif