presage  0.8.7
logger.h
Go to the documentation of this file.
00001 
00002 /******************************************************
00003  *  Presage, an extensible predictive text entry system
00004  *  ---------------------------------------------------
00005  *
00006  *  Copyright (C) 2008  Matteo Vescovi <matteo.vescovi@yahoo.co.uk>
00007 
00008     This program is free software; you can redistribute it and/or modify
00009     it under the terms of the GNU General Public License as published by
00010     the Free Software Foundation; either version 2 of the License, or
00011     (at your option) any later version.
00012 
00013     This program is distributed in the hope that it will be useful,
00014     but WITHOUT ANY WARRANTY; without even the implied warranty of
00015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016     GNU General Public License for more details.
00017 
00018     You should have received a copy of the GNU General Public License along
00019     with this program; if not, write to the Free Software Foundation, Inc.,
00020     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00021     *
00022     **********(*)*/
00023 
00024 
00025 #ifndef PRESAGE_LOGGER
00026 #define PRESAGE_LOGGER
00027 
00028 #if HAVE_CONFIG_H
00029 #  include <config.h>
00030 #endif
00031 
00032 #include <iostream>
00033 
00034 
00035 // manipulators
00036 struct _SetLevel { std::string _level; };
00037 
00045 inline _SetLevel
00046 setlevel(std::string __l)
00047 {
00048     _SetLevel __x;
00049     __x._level = __l;
00050     return __x;
00051 }
00052 
00053 
00054 
00055 template <class _charT, class _Traits=std::char_traits<_charT> >
00056 class Logger
00057 {
00058 public:
00059     // type definitions
00060     enum Level
00061     {
00062         EMERG  = 0,
00063         FATAL  = 0,
00064         ALERT  = 100,
00065         CRIT   = 200,
00066         ERROR  = 300,
00067         WARN   = 400,
00068         NOTICE = 500,
00069         INFO   = 600,
00070         DEBUG  = 700,
00071         ALL    = 800
00072     };
00073 
00074     // constructors
00075     inline
00076     Logger (std::string logger_name,
00077             std::basic_ostream<_charT,_Traits>& ostr)
00078         : outstream(ostr)
00079         {
00080             init(logger_name, "ERROR");
00081         }
00082 
00083     inline
00084     Logger (std::string logger_name,
00085             std::basic_ostream<_charT,_Traits>& ostr,
00086             const std::string& lvl)
00087         : outstream(ostr)
00088         {
00089             init(logger_name, lvl);
00090         }
00091 
00092     inline
00093     void init(const std::string& name, const std::string& lvl)
00094         {
00095             set_name(name);
00096             state = new LoggerState();
00097             set (state->loggerLevel, lvl);
00098             set (state->currentLevel, lvl);
00099             state->line_beginning = true;
00100         }
00101 
00102     // destructor
00103     inline
00104     ~Logger ()
00105         {
00106             outstream.flush();
00107             delete state;
00108         }
00109 
00110 
00111     // level getters/setters
00112     inline
00113     void
00114     setLevel(const std::string& lvl) const
00115         {
00116             set(state->loggerLevel, lvl);
00117         }
00118 
00119     inline
00120     void
00121     setLevel (Level lvl) const
00122         {
00123             state->loggerLevel = lvl;
00124         }
00125 
00126     inline
00127     Level
00128     getLevel () const
00129         {
00130             return state->loggerLevel;
00131         }
00132 
00133     inline
00134     void
00135     setCurrentLevel (Level lvl) const
00136         {
00137             state->currentLevel = lvl;
00138         }
00139 
00140     inline
00141     Level
00142     getCurrentLevel() const
00143         {
00144             return state->currentLevel;
00145         }
00146 
00147     inline
00148     bool
00149     shouldLog() const
00150         {
00151             return (state->loggerLevel >= state->currentLevel);
00152         }
00153 
00154     // logging method
00155     template<typename T>
00156     friend inline
00157     const Logger&
00158     operator<< (const Logger& lgr, const T& msg)
00159         {
00160             //if (lgr.state->loggerLevel >= lgr.state->currentLevel)
00161             if (lgr.shouldLog())
00162             {
00163                 if (lgr.state->line_beginning) {
00164                     lgr.outstream << lgr.name;
00165                     lgr.state->line_beginning = false;
00166                 }
00167                 lgr.outstream << msg;
00168             }
00169             return lgr;
00170         }
00171 
00172     // this method is needed by the functions defined by macro
00173     // define_logger_level_manipulator(LEVEL)
00174     //
00175     friend inline
00176     const Logger&
00177     operator<< (const Logger& lgr, const Logger& (*fp)(const Logger&))
00178         {
00179             (*fp)(lgr);
00180             return lgr;
00181         }
00182 
00183     inline
00184     const Logger&
00185     operator<< (_SetLevel __l) const
00186         {
00187             setLevel(__l._level);
00188             return *this;
00189         }
00190 
00191     inline
00192     void endl() const
00193         {
00194             //if (state->loggerLevel >= state->currentLevel)
00195             if (shouldLog())
00196             {
00197                 outstream << std::endl;
00198                 state->line_beginning = true;
00199             }
00200         }
00201 
00202 private:
00203     inline
00204     void
00205     set(Level& level, const std::string& lvl) const
00206         {
00207             if (lvl == "EMERG") {
00208                 level = EMERG;
00209             } else if (lvl == "FATAL") {
00210                 level = FATAL;
00211             } else if (lvl == "ALERT") {
00212                 level = ALERT;
00213             } else if (lvl == "CRIT") {
00214                 level = CRIT;
00215             } else if (lvl == "ERROR") {
00216                 level = ERROR;
00217             } else if (lvl == "WARN") {
00218                 level = WARN;
00219             } else if (lvl == "NOTICE") {
00220                 level = NOTICE;
00221             } else if (lvl == "INFO") {
00222                 level = INFO;
00223             } else if (lvl == "DEBUG") {
00224                 level = DEBUG;
00225             } else if (lvl == "ALL") {
00226                 level = ALL;
00227             } else {
00228                 level = ERROR;
00229             }
00230         }
00231 
00232     inline
00233     void
00234     set_name(const std::string& logger_name)
00235         {
00236             name = "[" + logger_name + "] ";
00237         }
00238 
00239     std::string name;
00240     std::basic_ostream <_charT, _Traits>& outstream;
00241 
00242     class LoggerState {
00243     public:
00244         bool line_beginning;
00245         Level loggerLevel;
00246         Level currentLevel;
00247 
00248     };
00249 
00250     LoggerState* state;
00251 };
00252 
00253 
00254 
00255 #define define_logger_level_manipulator(LEVEL)                  \
00256     template <typename _charT, typename _Traits>                \
00257     inline const Logger<_charT, _Traits>&                       \
00258     LEVEL (const Logger<_charT, _Traits>& lgr)                  \
00259     {                                                           \
00260         lgr.setCurrentLevel(Logger<_charT, _Traits>::LEVEL);    \
00261         return lgr;                                             \
00262     }
00263 
00264 define_logger_level_manipulator(EMERG );
00265 define_logger_level_manipulator(FATAL );
00266 define_logger_level_manipulator(ALERT );
00267 define_logger_level_manipulator(CRIT  );
00268 define_logger_level_manipulator(ERROR );
00269 define_logger_level_manipulator(WARN  );
00270 define_logger_level_manipulator(NOTICE);
00271 define_logger_level_manipulator(INFO  );
00272 define_logger_level_manipulator(DEBUG );
00273 define_logger_level_manipulator(ALL   );
00274 
00275 
00276 template <typename _charT, typename _Traits>
00277 inline const Logger<_charT, _Traits>&
00278 endl (const Logger<_charT, _Traits>& lgr)
00279 {
00280     lgr.endl();
00281     return lgr;
00282 }
00283 
00284 
00285 #endif // PRESAGE_LOGGER