Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

log.hh

Go to the documentation of this file.
00001 // Copyright (C) 2003, 2004, 2005 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, Boston, MA  02110-1301, USA.
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   } // namespace utl
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 } // namespace olsr
00528 
00529 # ifndef QOLYESTER_DONTINCLUDE_HXX
00530 #  include "log.hxx"
00531 # endif
00532 
00533 #endif // ! QOLYESTER_LOG_HH

Generated on Thu Jul 28 21:21:47 2005 for Qolyester daemon by  doxygen 1.4.1