00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef QOLYESTER_UTL_LOG_HH
00021 # define QOLYESTER_UTL_LOG_HH 1
00022
00023 # include <ostream>
00024 # include <sstream>
00025 # include <cassert>
00026
00027 # include <sys/time.h>
00028
00029 namespace olsr {
00030
00031 extern unsigned current_log_level;
00032 extern bool timestamps;
00033
00034 namespace utl {
00035
00036 struct of {
00037 of(const double& v, char f = ' ', std::streamsize p = 2, int w = 6)
00038 : _val(v),
00039 _f(f),
00040 _p(p),
00041 _w(w)
00042 {}
00043 double _val;
00044 char _f;
00045 std::streamsize _p;
00046 int _w;
00047 };
00048
00049 inline
00050 std::ostream& operator<<(std::ostream& os, const of& f)
00051 {
00052 if (f._val <= -10.)
00053 return os << " < -10";
00054
00055 std::ios::fmtflags flags = os.setf(std::ios::showbase |
00056 std::ios::right |
00057 std::ios::fixed,
00058 std::ios::showbase |
00059 std::ios::right |
00060 std::ios::fixed);
00061 char c = os.fill(f._f);
00062 std::streamsize p = os.precision(f._p);
00063 int w = os.width(f._w);
00064 os << f._val;
00065 os.fill(c);
00066 os.precision(p);
00067 os.width(w);
00068 os.flags(flags);
00069 return os;
00070 }
00071
00072 class LevelableBuf {
00073 public:
00074 virtual ~LevelableBuf() {}
00075 virtual void increase_level(unsigned i = 1) = 0;
00076 virtual void decrease_level(unsigned i = 1) = 0;
00077 virtual void reset_level() = 0;
00078 };
00079
00080 template <class F, class C, class T = std::char_traits<C> >
00081 class PrefixBuf : public std::basic_streambuf<C, T>,
00082 public LevelableBuf {
00083 typedef PrefixBuf<F, C, T> This;
00084 typedef std::basic_streambuf<C, T> Super;
00085 typedef typename Super::char_type char_type;
00086 typedef typename Super::traits_type traits_type;
00087 typedef typename Super::int_type int_type;
00088 typedef typename Super::pos_type pos_type;
00089 typedef typename Super::off_type off_type;
00090 public:
00091 PrefixBuf(Super* other, bool m = true)
00092 : other_(other),
00093 proxy_(dynamic_cast<LevelableBuf*>(other_)),
00094 mark_(m)
00095 {}
00096
00097 PrefixBuf(Super* other, const F& f, bool m = true)
00098 : other_(other),
00099 proxy_(dynamic_cast<LevelableBuf*>(other_)),
00100 mark_(m),
00101 f_(f)
00102 {}
00103
00104 Super* get_streambuf() {
00105 return other_;
00106 }
00107
00108 void set_streambuf(Super* other) {
00109 other_->pubsync();
00110 other_ = other;
00111 proxy_ = dynamic_cast<LevelableBuf*>(other_);
00112 }
00113
00114 virtual void increase_level(unsigned i = 1) {
00115 if (proxy_)
00116 proxy_->increase_level(i);
00117 }
00118 virtual void decrease_level(unsigned i = 1) {
00119 if (proxy_)
00120 proxy_->decrease_level(i);
00121 }
00122 virtual void reset_level() {
00123 if (proxy_)
00124 proxy_->reset_level();
00125 }
00126 protected:
00127 virtual void imbue(const std::locale &l) {
00128 other_->pubimbue(l);
00129 }
00130
00131 virtual int_type overflow(int_type c = traits_type::eof()) {
00132 if (mark_) {
00133 mark_ = false;
00134 const std::basic_string<C, T> s = f_(c);
00135 other_->sputn(s.data(), s.size());
00136 }
00137 if (c == char_type('\n'))
00138 mark_ = true;
00139 return other_->sputc(c);
00140 }
00141
00142 virtual std::basic_streambuf<char_type, traits_type>*
00143 setbuf(char_type* s, std::streamsize n) {
00144 return other_->pubsetbuf(s, n);
00145 }
00146
00147 virtual int sync() {
00148 return other_->pubsync();
00149 }
00150 private:
00151 Super* other_;
00152 LevelableBuf* proxy_;
00153 bool mark_;
00154 F f_;
00155 };
00156
00157 struct StringPrefixer {
00158 StringPrefixer(const std::string& s,
00159 const std::string& vs = "")
00160 : s_(s),
00161 vs_(vs)
00162 {}
00163
00164 const std::string& operator()(int c = 0) const {
00165 if (c == '\n')
00166 return vs_;
00167 return s_;
00168 }
00169 private:
00170 std::string s_;
00171 std::string vs_;
00172 };
00173
00174 struct Timestamper {
00175 std::string operator()(int c = 0) const {
00176 ::timeval tv;
00177 gettimeofday(&tv, 0);
00178 ::tm tm;
00179 gmtime_r(&tv.tv_sec, &tm);
00180 char buf[9];
00181 strftime(buf, sizeof buf, "%T", &tm);
00182 std::ostringstream os;
00183 os << buf << '.';
00184 os.fill('0');
00185 os.width(6);
00186 os << std::right << tv.tv_usec << (c == '\n' ? "" : " ");
00187 return os.str();
00188 }
00189 };
00190
00191 template <class C, class T>
00192 inline
00193 std::basic_ostream<C, T>& indent(std::basic_ostream<C, T>& os)
00194 {
00195 os.rdbuf(new PrefixBuf<StringPrefixer, C, T>(os.rdbuf(),
00196 StringPrefixer(" ")));
00197 return os;
00198 }
00199
00200 template <class C, class T>
00201 inline
00202 std::basic_ostream<C, T>& deindent(std::basic_ostream<C, T>& os)
00203 {
00204 typedef PrefixBuf<StringPrefixer, C, T> pb_t;
00205 assert(dynamic_cast<pb_t*>(os.rdbuf()) != 0);
00206 pb_t* sb = static_cast<pb_t*>(os.rdbuf());
00207 os.rdbuf(sb->get_streambuf());
00208 delete sb;
00209 return os;
00210 }
00211
00212 template <typename C, typename T = std::char_traits<C> >
00213 struct basic_indent_ {
00214 std::basic_string<C, T> s;
00215 };
00216
00217 template <typename C, typename T>
00218 inline
00219 basic_indent_<C, T> basic_indent(const std::basic_string<C, T>& s =
00220 std::basic_string<C, T>(2, ' ')) {
00221 basic_indent_<C, T> indent__;
00222 indent__.s = s;
00223 return indent__;
00224 }
00225
00226 # define indent(S) utl::basic_indent<char, std::char_traits<char> >(S)
00227
00228 template <typename C, typename T>
00229 inline
00230 std::basic_ostream<C, T>&
00231 operator<<(std::basic_ostream<C, T>& os, const basic_indent_<C, T>& i)
00232 {
00233 os.rdbuf(new PrefixBuf<StringPrefixer, C, T>(os.rdbuf(),
00234 StringPrefixer(i.s)));
00235 return os;
00236 }
00237
00238 template <typename C, typename T = std::char_traits<C> >
00239 class basic_dummyostream : public std::basic_ostream<C, T> {
00240 typedef basic_dummyostream<C, T> This;
00241 typedef std::basic_ostream<C, T> Super;
00242 typedef typename Super::char_type char_type;
00243 typedef typename Super::traits_type traits_type;
00244 typedef typename Super::int_type int_type;
00245 typedef typename Super::pos_type pos_type;
00246 typedef typename Super::off_type off_type;
00247 public:
00248 explicit basic_dummyostream(std::basic_streambuf<C, T>* sb)
00249 : Super(sb)
00250 {}
00251 basic_dummyostream(Super& other)
00252 : Super(other.rdbuf()) {
00253 copyfmt(other);
00254 }
00255 template <typename U>
00256 const This& operator<<(const U&) const { return *this; }
00257 const This& operator<<(std::ostream& (*)(std::ostream&)) const {
00258 return *this;
00259 }
00260 };
00261
00262 template <typename C, typename T = std::char_traits<C> >
00263 class basic_ybuf : public std::basic_streambuf<C, T>,
00264 public LevelableBuf {
00265 typedef std::basic_streambuf<C, T> Super;
00266 typedef typename Super::char_type char_type;
00267 typedef typename Super::traits_type traits_type;
00268 typedef typename Super::int_type int_type;
00269 typedef typename Super::pos_type pos_type;
00270 typedef typename Super::off_type off_type;
00271 public:
00272 basic_ybuf(Super* other1, Super* other2)
00273 : other1_(other1),
00274 other2_(other2),
00275 proxy1_(dynamic_cast<LevelableBuf*>(other1_)),
00276 proxy2_(dynamic_cast<LevelableBuf*>(other2_))
00277 {}
00278 Super* get_streambuf1() {
00279 return other1_;
00280 }
00281 void set_streambuf1(Super* other) {
00282 other1_->pubsync();
00283 other1_ = other;
00284 proxy1_ = dynamic_cast<LevelableBuf*>(other1_);
00285 }
00286 Super* get_streambuf2() {
00287 return other2_;
00288 }
00289 void set_streambuf2(Super* other) {
00290 other2_->pubsync();
00291 other2_ = other;
00292 proxy2_ = dynamic_cast<LevelableBuf*>(other2_);
00293 }
00294 virtual void increase_level(unsigned i = 1) {
00295 if (proxy1_)
00296 proxy1_->increase_level(i);
00297 if (proxy2_)
00298 proxy2_->increase_level(i);
00299 }
00300 virtual void decrease_level(unsigned i = 1) {
00301 if (proxy1_)
00302 proxy1_->decrease_level(i);
00303 if (proxy2_)
00304 proxy2_->decrease_level(i);
00305 }
00306 virtual void reset_level() {
00307 if (proxy1_)
00308 proxy1_->reset_level();
00309 if (proxy2_)
00310 proxy2_->reset_level();
00311 }
00312 protected:
00313 virtual void imbue(const std::locale &l) {
00314 other1_->pubimbue(l);
00315 other2_->pubimbue(l);
00316 }
00317
00318 virtual int_type overflow(int_type c = traits_type::eof()) {
00319 int_type ret1 = other1_->sputc(c);
00320 int_type ret2 = other2_->sputc(c);
00321 if (ret1 == traits_type::eof() || ret2 == traits_type::eof())
00322 return traits_type::eof();
00323 return 0;
00324 }
00325
00326 virtual int sync() {
00327 int ret1 = other1_->pubsync();
00328 int ret2 = other2_->pubsync();
00329 if (ret1 < 0 || ret2 < 0)
00330 return -1;
00331 return 0;
00332 }
00333
00334 virtual std::streamsize xsputn(char_type* s, std::streamsize n) {
00335 std::streamsize ret1 = other1_->sputn(s, n);
00336 std::streamsize ret2 = other2_->sputn(s, n);
00337
00338 return ret1 < ret2 ? ret1 : ret2;
00339 }
00340 private:
00341 Super* other1_;
00342 Super* other2_;
00343 LevelableBuf* proxy1_;
00344 LevelableBuf* proxy2_;
00345 };
00346
00347 template <typename C, typename T = std::char_traits<C> >
00348 class basic_levelbuf : public std::basic_streambuf<C, T>,
00349 public LevelableBuf {
00350 typedef std::basic_streambuf<C, T> Super;
00351 typedef typename Super::char_type char_type;
00352 typedef typename Super::traits_type traits_type;
00353 typedef typename Super::int_type int_type;
00354 typedef typename Super::pos_type pos_type;
00355 typedef typename Super::off_type off_type;
00356 public:
00357 inline basic_levelbuf(unsigned level, Super* other,
00358 const unsigned& minlevel = current_log_level);
00359
00360 Super* get_streambuf() {
00361 return other_;
00362 }
00363
00364 void set_streambuf(Super* other) {
00365 other_->pubsync();
00366 other_ = other;
00367 }
00368
00369 virtual void increase_level(unsigned i = 1) {
00370 assert(level_ <= UINT_MAX - i);
00371 level_ += i;
00372 }
00373
00374 virtual void decrease_level(unsigned i = 1) {
00375 assert(level_ >= i);
00376 level_ -= i;
00377 }
00378
00379 virtual void reset_level() {
00380 level_ = baselevel_;
00381 }
00382 protected:
00383 virtual void imbue(const std::locale &l) {
00384 other_->pubimbue(l);
00385 }
00386
00387 virtual inline int_type overflow(int_type c = traits_type::eof());
00388
00389 virtual std::basic_streambuf<char_type, traits_type>*
00390 setbuf(char_type* s, std::streamsize n) {
00391 return other_->pubsetbuf(s, n);
00392 }
00393
00394 virtual int sync() {
00395 bool would = level_ <= minlevel_;
00396 if (would)
00397 return other_->pubsync();
00398 return 0;
00399 }
00400 private:
00401 Super* other_;
00402 unsigned level_;
00403 unsigned baselevel_;
00404 const unsigned& minlevel_;
00405 };
00406
00407 template <typename C, typename T = std::char_traits<C> >
00408 class basic_dummybuf : public std::basic_streambuf<C, T> {
00409 typedef std::basic_streambuf<C, T> Super;
00410 typedef typename Super::char_type char_type;
00411 typedef typename Super::traits_type traits_type;
00412 typedef typename Super::int_type int_type;
00413 typedef typename Super::pos_type pos_type;
00414 typedef typename Super::off_type off_type;
00415 public:
00416 basic_dummybuf() : Super() {}
00417 protected:
00418 virtual int_type overflow(int_type = traits_type::eof()) {
00419 return 0;
00420 }
00421
00422 virtual int_type pbackfail(int_type = traits_type::eof()) {
00423 return 0;
00424 }
00425 };
00426
00427 template <typename C, typename T>
00428 inline
00429 std::basic_ostream<C, T>& up(std::basic_ostream<C, T>& os) {
00430 LevelableBuf* l;
00431 if ((l = dynamic_cast<LevelableBuf*>(os.rdbuf())) == 0)
00432 return os;
00433 l->increase_level();
00434 return os;
00435 }
00436
00437 template <typename C, typename T>
00438 inline
00439 std::basic_ostream<C, T>& down(std::basic_ostream<C, T>& os) {
00440 LevelableBuf* l;
00441 if ((l = dynamic_cast<LevelableBuf*>(os.rdbuf())) == 0)
00442 return os;
00443 l->decrease_level();
00444 return os;
00445 }
00446
00447 template <typename C, typename T>
00448 inline
00449 std::basic_ostream<C, T>& reset(std::basic_ostream<C, T>& os) {
00450 LevelableBuf* l;
00451 if ((l = dynamic_cast<LevelableBuf*>(os.rdbuf())) == 0)
00452 return os;
00453 l->reset_level();
00454 return os;
00455 }
00456
00457 struct up_ {
00458 unsigned i;
00459 };
00460
00461 struct down_ {
00462 unsigned i;
00463 };
00464
00465 inline
00466 up_ up(unsigned i = 1) {
00467 up_ up__;
00468 up__.i = i;
00469 return up__;
00470 }
00471
00472 inline
00473 down_ down(unsigned i = 1) {
00474 down_ down__;
00475 down__.i = i;
00476 return down__;
00477 }
00478
00479 template <typename C, typename T>
00480 inline
00481 std::basic_ostream<C, T>&
00482 operator<<(std::basic_ostream<C, T>& os, const up_& u)
00483 {
00484 LevelableBuf* l;
00485 if ((l = dynamic_cast<LevelableBuf*>(os.rdbuf())) == 0)
00486 return os;
00487 l->increase_level(u.i);
00488 return os;
00489 }
00490
00491 template <typename C, typename T>
00492 inline
00493 std::basic_ostream<C, T>&
00494 operator<<(std::basic_ostream<C, T>& os, const down_& d)
00495 {
00496 LevelableBuf* l;
00497 if ((l = dynamic_cast<LevelableBuf*>(os.rdbuf())) == 0)
00498 return os;
00499 l->decrease_level(d.i);
00500 return os;
00501 }
00502
00503 }
00504
00505 using utl::of;
00506
00507 using utl::StringPrefixer;
00508 using utl::Timestamper;
00509
00510 typedef utl::PrefixBuf<StringPrefixer, char> StringPrefixBuf;
00511 typedef utl::PrefixBuf<Timestamper, char> TimestampBuf;
00512
00513 typedef utl::basic_dummyostream<char> DummyOStream;
00514 typedef utl::basic_levelbuf<char> LevelBuf;
00515 typedef utl::basic_ybuf<char> YBuf;
00516 typedef utl::basic_dummybuf<char> DummyBuf;
00517
00518 # ifdef DEBUG
00519 typedef std::ostream debug_ostream_t;
00520 # else // !DEBUG
00521 typedef DummyOStream debug_ostream_t;
00522 # endif
00523
00524 using utl::up;
00525 using utl::down;
00526 using utl::reset;
00527 using utl::indent;
00528 using utl::deindent;
00529
00530 }
00531
00532 # include "log.hxx"
00533
00534 #endif // ! QOLYESTER_LOG_HH