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