openModeller  Version 1.4.0
Log.cpp
Go to the documentation of this file.
00001 
00028 #include <openmodeller/Log.hh>
00029 
00030 
00031 #include <openmodeller/Exceptions.hh>
00032 
00033 //Needed for strlen calls otherwise gcc 4.3.2 throws error
00034 #include <string.h>
00035 
00036 using std::ostream;
00037 using std::ios_base;
00038 using std::fstream;
00039 using std::endl;
00040 using std::string;
00041 //
00042 // Static calls to enforce singleton behaviour
00043 //
00044 Log *Log::mpInstance = 0;
00045 Log *Log::instance()
00046 {
00047   if (mpInstance == 0)
00048   {
00049     mpInstance = new Log();
00050   }
00051   return mpInstance;
00052 }
00053 
00054 //
00055 // WIN32 function defines
00056 //
00057 #ifdef WIN32
00058 #define snprintf    _snprintf
00059 #define vsnprintf   _vsnprintf
00060 #endif
00061 
00062 /****************************************************************/
00063 /******************** StdFileLogCallback ************************/
00064 
00065 class StdFileLogCallback : public Log::LogCallback {
00066 public:
00067 
00068   StdFileLogCallback( std::string fileName ) {
00069 
00070     file.open( fileName.c_str(), ios_base::out );
00071 
00072     if ( file.fail() ) {
00073 
00074       fprintf( stderr, "Could not open log file!\n" );
00075     }
00076   }
00077 
00078   ~StdFileLogCallback() {
00079 
00080     file.close();
00081   }
00082 
00083   void operator()( Log::Level level, const std::string& msg ) {
00084 
00085     if ( file.is_open() ) {
00086 
00087       file << msg.c_str();
00088       file.flush();
00089     }
00090   }
00091 
00092   std::fstream file;
00093 };
00094 
00095 /****************************************************************/
00096 /******************** OstreamCallback ***************************/
00097 
00098 Log::OstreamCallback::OstreamCallback( ostream& os ) :
00099   os( os )
00100 {}
00101 
00102 void
00103 Log::OstreamCallback::operator()(Level level, const string& msg ) {
00104   os << msg;
00105 }
00106 
00107 /****************************************************************/
00108 /******************** output function ***************************/
00109 const char *
00110 LevelLabels[5] =
00111   {
00112     "[Debug] ",
00113     "", 
00114     "[Info] ",
00115     "[Warn] ",
00116     "[Error] "
00117   };
00118 
00119 void
00120 Log::FormatAndWrite( Log::LogCallback& lc, Log::Level level, std::string pref, const char* format, va_list ap ) {
00121 
00122   const int buf_size = 1024;
00123   char buf[buf_size];
00124 
00125   // Print in 'buf'.
00126   //
00127   // Header.
00128   snprintf( buf, buf_size, "%s%s", LevelLabels[level], pref.c_str() );
00129 
00130   // Print message after header.
00131   int len = strlen( buf );
00132   char *end = buf + len;
00133   vsnprintf( end, buf_size - len, format, ap );
00134 
00135   lc( level, buf );
00136 }
00137 
00138 /****************************************************************/
00139 /****************************** Log *****************************/
00140 
00141 std::string
00142 Log::format( const char *fmt, ... )
00143 {
00144    std::string ret_str("");
00145 
00146    if ( NULL != fmt ) {
00147 
00148       va_list marker;
00149 
00150       // initalize variable arguments
00151       va_start( marker, fmt );
00152 
00153       const int buf_size = 1024;
00154       char buf[buf_size];
00155       char *end = buf;
00156 
00157       vsnprintf( end, buf_size, fmt, marker );
00158 
00159       // reset variable arguments
00160       va_end( marker );
00161 
00162       ret_str = buf;
00163    }
00164 
00165    return ret_str;
00166 }
00167 
00168 /*******************/
00169 /*** constructor ***/
00170 
00171 Log::Log( ) :
00172   callback( new Log::OstreamCallback( std::cerr ) )
00173 {
00174   _level = Log::Debug ; 
00175    setPrefix( "" );
00176   _deleteCallback = true;
00177 }
00178 
00179 
00180 /******************/
00181 /*** destructor ***/
00182 
00183 Log::~Log()
00184 {
00185   if ( callback && _deleteCallback ) {
00186 
00187     delete callback;
00188   }
00189 }
00190 
00191 /**************************/
00192 /*** set all parameters ***/
00193 //void
00194 //Log::set( Log::Level level, FILE* out, char const *pref )
00195 void
00196 Log::set( Log::Level level, std::string fileName, char const *pref )
00197 {
00198   setLevel( level );
00199   setCallback( new StdFileLogCallback( fileName ) );
00200   setPrefix( pref );
00201   _deleteCallback = true;
00202 }
00203 
00204 /********************/
00205 /*** set Callback ***/
00206 void
00207 Log::setCallback( LogCallback *lc )
00208 {
00209   if ( callback && _deleteCallback ) {
00210 
00211     delete callback;
00212     _deleteCallback = false;
00213   }
00214 
00215   callback = lc;
00216 }
00217 
00218 
00219 /******************/
00220 /*** set Prefix ***/
00221 void
00222 Log::setPrefix( const char *pref )
00223 {
00224   _pref.assign( pref );
00225 
00226   // If prefix is non-empty, we need a trailing space
00227   if ( _pref.size() > 0 ) {
00228 
00229     _pref.append(" ");
00230   }
00231 }
00232 
00233 
00234 /*************/
00235 /*** debug ***/
00236 void
00237 Log::debug( const char *format, ... )
00238 {
00239   if ( _level > Debug || ! callback ) {
00240 
00241     return;
00242   }
00243 
00244   va_list ap;
00245   va_start( ap, format );
00246   FormatAndWrite( *callback, Debug, _pref, format, ap );
00247   va_end( ap );
00248 
00249   return;
00250 }
00251 
00252 
00253 /************/
00254 /*** info ***/
00255 void
00256 Log::info( const char *format, ... )
00257 {
00258   if ( _level > Info || !callback )
00259     return;
00260 
00261   va_list ap;
00262   va_start( ap, format );
00263   FormatAndWrite( *callback, Info, _pref, format, ap );
00264   va_end( ap );
00265 
00266   return;
00267 }
00268 
00269 
00270 /************/
00271 /*** warn ***/
00272 void
00273 Log::warn( const char *format, ... )
00274 {
00275   if ( _level > Warn || !callback )
00276     return;
00277 
00278   va_list ap;
00279   va_start( ap, format );
00280   FormatAndWrite( *callback, Warn, _pref, format, ap );
00281   va_end( ap );
00282 
00283   return;
00284 }
00285 
00286 
00287 /*************/
00288 /*** error ***/
00289 void
00290 Log::error( const char *format, ... )
00291 {
00292   if ( _level > Error || !callback )
00293     return;
00294 
00295   va_list ap;
00296   va_start( ap, format );
00297   FormatAndWrite( *callback, Error, _pref, format, ap );
00298   va_end( ap );
00299 
00300   return;
00301 }
00302 
00303 
00304 /*******************/
00305 /*** operator () ***/
00306 void
00307 Log::operator()( const char *format, ... )
00308 {
00309   if ( _level > Default || !callback )
00310     return;
00311 
00312   va_list ap;
00313   va_start( ap, format );
00314   FormatAndWrite( *callback, Default, _pref, format, ap );
00315   va_end( ap );
00316 
00317   return;
00318 }