log.hh

Go to the documentation of this file.
00001 // Copyright (C) 2003-2006 Laboratoire de Recherche en Informatique
00002 
00003 // This file is part of Qolyester.
00004 
00005 // Qolyester is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU General Public License
00007 // as published by the Free Software Foundation; either version 2
00008 // of the License, or (at your option) any later version.
00009 
00010 // Qolyester is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program; if not, write to the Free Software
00017 // Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018 // Boston, MA  02110-1301, USA.
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   } // namespace utl
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 } // namespace olsr
00531 
00532 # include "log.hxx"
00533 
00534 #endif // ! QOLYESTER_LOG_HH

Generated on Mon Sep 10 17:02:12 2007 for Qolyester daemon by  doxygen 1.5.1