io.cpp

Go to the documentation of this file.
00001 /*
00002  * This program is free software; you can redistribute it and/or modify
00003  * it under the terms of the GNU General Public License as published by
00004  * the Free Software Foundation; either version 3 of the License, or
00005  * (at your option) any later version.
00006  *
00007  * Written (W) 1999-2008 Soeren Sonnenburg
00008  * Written (W) 1999-2008 Gunnar Raetsch
00009  * Copyright (C) 1999-2008 Fraunhofer Institute FIRST and Max-Planck-Society
00010  */
00011 
00012 #include "lib/config.h"
00013 #include "lib/matlab.h"
00014 #include "lib/octave.h"
00015 #include "lib/r.h"
00016 #include "lib/python.h"
00017 
00018 #include "lib/io.h"
00019 #include "lib/ShogunException.h"
00020 #include "lib/Signal.h"
00021 #include "lib/common.h"
00022 #include "lib/Time.h"
00023 #include "lib/Mathematics.h"
00024 
00025 #include <sys/types.h>
00026 #include <sys/stat.h>
00027 
00028 #include <stdio.h>
00029 #include <stdarg.h>
00030 #include <ctype.h>
00031 #include <dirent.h>
00032 #include <stdlib.h>
00033 #include <unistd.h>
00034 
00035 const EMessageType CIO::levels[NUM_LOG_LEVELS]={M_DEBUG, M_INFO, M_NOTICE, M_WARN, M_ERROR, M_CRITICAL, M_ALERT, M_EMERGENCY, M_MESSAGEONLY};
00036 const char* CIO::message_strings[NUM_LOG_LEVELS]={"[DEBUG] ", "[INFO] ", "[NOTICE] ", "\033[1;34m[WARN]\033[0m ", "\033[1;31m[ERROR]\033[0m ", "[CRITICAL] ", "[ALERT] ", "[EMERGENCY] ", ""};
00037 
00039 CHAR file_buffer[FBUFSIZE];
00040 
00042 CHAR directory_name[FBUFSIZE];
00043 
00044 CIO::CIO() : target(stdout), last_progress_time(0), progress_start_time(0),
00045     last_progress(1), show_progress(false), loglevel(M_WARN)
00046 {
00047 }
00048 
00049 CIO::CIO(const CIO& orig) : target(orig.get_target()), last_progress_time(0),
00050     progress_start_time(0), last_progress(1), show_progress(orig.get_show_progress()),
00051     loglevel(orig.get_loglevel())
00052 {
00053 }
00054 
00055 void CIO::message(EMessageType prio, const CHAR *fmt, ... ) const
00056 {
00057     const CHAR* msg_intro=get_msg_intro(prio);
00058     if (!msg_intro)
00059         return;
00060 
00061     CHAR str[4096];
00062     va_list list;
00063     va_start(list,fmt);
00064     vsnprintf(str, sizeof(str), fmt, list);
00065     va_end(list);
00066 
00067     switch (prio)
00068     {
00069         case M_DEBUG:
00070         case M_INFO:
00071         case M_NOTICE:
00072         case M_MESSAGEONLY:
00073 #if defined(WIN32) && defined(HAVE_MATLAB)
00074             fprintf(target, "%s", msg_intro);
00075             mexPrintf("%s", str);
00076 #elif defined(HAVE_R)
00077             if (target==stdout)
00078             {
00079                 Rprintf((char*) "%s", msg_intro);
00080                 Rprintf((char*) "%s", str);
00081             }
00082             else
00083             {
00084                 fprintf(target, "%s", msg_intro);
00085                 fprintf(target, "%s", str);
00086             }
00087 #else
00088             fprintf(target, "%s", msg_intro);
00089             fprintf(target, "%s", str);
00090 #endif
00091             break;
00092 
00093         case M_WARN:
00094 #if defined(HAVE_MATLAB)
00095             mexWarnMsgTxt(str);
00096 #elif defined(HAVE_OCTAVE)
00097             ::warning(str);
00098 #elif defined(HAVE_PYTHON) // no check for swig necessary
00099             PyErr_Warn(NULL, str);
00100 #elif defined(HAVE_R)
00101             if (target==stdout)
00102             {
00103                 Rprintf((char*) "%s", msg_intro);
00104                 Rprintf((char*) "%s", str);
00105             }
00106             else
00107             {
00108                 fprintf(target, "%s", msg_intro);
00109                 fprintf(target, "%s", str);
00110             }
00111 #else
00112             fprintf(target, "%s", msg_intro);
00113             fprintf(target, "%s", str);
00114 #endif
00115             break;
00116 
00117         case M_ERROR:
00118         case M_CRITICAL:
00119         case M_ALERT:
00120         case M_EMERGENCY:
00121 #ifndef WIN32
00122             CSignal::unset_handler();
00123 #endif
00124 #if defined(WIN32) && defined(HAVE_MATLAB)
00125             mexPrintf("%s", str);
00126 #elif defined(HAVE_OCTAVE)
00127             error("%s", str);
00128 #elif defined(HAVE_PYTHON) && !defined(HAVE_SWIG)
00129             PyErr_SetString(PyExc_RuntimeError, str);
00130 #elif defined(HAVE_PYTHON) && defined(HAVE_SWIG)
00131             // nop
00132 #elif defined(HAVE_R)
00133             error("%s", str);
00134 #else
00135             fprintf(target, "%s", str);
00136 #endif
00137             throw ShogunException(str);
00138             break;
00139         default:
00140             break;
00141     }
00142 
00143     fflush(target);
00144 }
00145 
00146 void CIO::buffered_message(EMessageType prio, const CHAR *fmt, ... ) const
00147 {
00148     const CHAR* msg_intro=get_msg_intro(prio);
00149     if (!msg_intro)
00150         return;
00151 
00152     fprintf(target, "%s", msg_intro);
00153     va_list list;
00154     va_start(list,fmt);
00155     vfprintf(target,fmt,list);
00156     va_end(list);
00157 }
00158 
00159 void CIO::progress(DREAL current_val, DREAL min_val, DREAL max_val, INT decimals, const char* prefix)
00160 {
00161     if (!show_progress)
00162         return;
00163 
00164     LONG runtime = CTime::get_runtime() ;
00165 
00166     char str[1000];
00167     DREAL v=-1, estimate=0, total_estimate=0 ;
00168 
00169     if (max_val-min_val>0.0)
00170         v=100*(current_val-min_val+1)/(max_val-min_val+1);
00171 
00172     if (decimals < 1)
00173         decimals = 1;
00174 
00175     if (last_progress>v)
00176     {
00177         last_progress_time = runtime ;
00178         progress_start_time = runtime;
00179         last_progress = v ;
00180     }
00181     else
00182     {
00183         if (v>100) v=100.0 ;
00184         if (v<=0) v=1e-5 ;
00185         last_progress = v-1e-6 ; ;
00186 
00187         if ((v!=100.0) && (runtime - last_progress_time<10))
00188             return ;
00189 
00190         last_progress_time = runtime ;
00191         estimate = (1-v/100)*(last_progress_time-progress_start_time)/(v/100) ;
00192         total_estimate = (last_progress_time-progress_start_time)/(v/100) ;
00193     }
00194 
00195     if (estimate/100>120)
00196     {
00197         snprintf(str, sizeof(str), "%%s %%%d.%df%%%%    %%1.1f minutes remaining    %%1.1f minutes total    \r",decimals+3, decimals);
00198         message(M_MESSAGEONLY, str, prefix, v, (float)estimate/100/60, (float)total_estimate/100/60);
00199     }
00200     else
00201     {
00202         snprintf(str, sizeof(str), "%%s %%%d.%df%%%%    %%1.1f seconds remaining    %%1.1f seconds total    \r",decimals+3, decimals);
00203         message(M_MESSAGEONLY, str, prefix, v, (float)estimate/100, (float)total_estimate/100);
00204     }
00205 
00206     fflush(target);
00207 }
00208 
00209 void CIO::absolute_progress(DREAL current_val, DREAL val, DREAL min_val, DREAL max_val, INT decimals, const char* prefix)
00210 {
00211     if (!show_progress)
00212         return;
00213 
00214     LONG runtime = CTime::get_runtime() ;
00215 
00216     char str[1000];
00217     DREAL v=-1, estimate=0, total_estimate=0 ;
00218 
00219     if (max_val-min_val>0)
00220         v=100*(val-min_val+1)/(max_val-min_val+1);
00221 
00222     if (decimals < 1)
00223         decimals = 1;
00224 
00225     if (last_progress>v)
00226     {
00227         last_progress_time = runtime ;
00228         progress_start_time = runtime;
00229         last_progress = v ;
00230     }
00231     else
00232     {
00233         if (v>100) v=100.0 ;
00234         if (v<=0) v=1e-6 ;
00235         last_progress = v-1e-5 ; ;
00236 
00237         if ((v!=100.0) && (runtime - last_progress_time<100))
00238             return ;
00239 
00240         last_progress_time = runtime ;
00241         estimate = (1-v/100)*(last_progress_time-progress_start_time)/(v/100) ;
00242         total_estimate = (last_progress_time-progress_start_time)/(v/100) ;
00243     }
00244 
00245     if (estimate/100>120)
00246     {
00247         snprintf(str, sizeof(str), "%%s %%%d.%df    %%1.1f minutes remaining    %%1.1f minutes total    \r",decimals+3, decimals);
00248         message(M_MESSAGEONLY, str, prefix, current_val, (float)estimate/100/60, (float)total_estimate/100/60);
00249     }
00250     else
00251     {
00252         snprintf(str, sizeof(str), "%%s %%%d.%df    %%1.1f seconds remaining    %%1.1f seconds total    \r",decimals+3, decimals);
00253         message(M_MESSAGEONLY, str, prefix, current_val, (float)estimate/100, (float)total_estimate/100);
00254     }
00255 
00256     fflush(target);
00257 }
00258 
00259 void CIO::done()
00260 {
00261     if (!show_progress)
00262         return;
00263 
00264     message(M_INFO, "done.\n");
00265 }
00266 
00267 CHAR* CIO::skip_spaces(CHAR* str)
00268 {
00269     INT i=0;
00270 
00271     if (str)
00272     {
00273         for (i=0; isspace(str[i]); i++);
00274 
00275         return &str[i];
00276     }
00277     else
00278         return str;
00279 }
00280 
00281 CHAR* CIO::skip_blanks(CHAR* str)
00282 {
00283     INT i=0;
00284 
00285     if (str)
00286     {
00287         for (i=0; isblank(str[i]); i++);
00288 
00289         return &str[i];
00290     }
00291     else
00292         return str;
00293 }
00294 
00295 EMessageType CIO::get_loglevel() const
00296 {
00297     return loglevel;
00298 }
00299 
00300 void CIO::set_loglevel(EMessageType level)
00301 {
00302     loglevel=level;
00303 }
00304 
00305 bool CIO::get_show_progress() const
00306 {
00307     return show_progress;
00308 }
00309 
00310 void CIO::set_target(FILE* t)
00311 {
00312     target=t;
00313 }
00314 
00315 const CHAR* CIO::get_msg_intro(EMessageType prio) const
00316 {
00317     for (INT i=NUM_LOG_LEVELS-1; i>=0; i--)
00318     {
00319         // ignore msg if prio's level is under loglevel,
00320         // but not if prio's level higher than M_WARN
00321         if (levels[i]<loglevel && prio<=M_WARN)
00322             return NULL;
00323 
00324         if (levels[i]==prio)
00325             return message_strings[i];
00326     }
00327 
00328     return NULL;
00329 }
00330 
00331 CHAR* CIO::concat_filename(const CHAR* filename)
00332 {
00333     if (snprintf(file_buffer, FBUFSIZE, "%s/%s", directory_name, filename) > FBUFSIZE)
00334         SG_SERROR("filename too long");
00335     return file_buffer;
00336 }
00337 
00338 int CIO::filter(CONST_DIRENT_T* d)
00339 {
00340     if (d)
00341     {
00342         CHAR* fname=concat_filename(d->d_name);
00343 
00344         if (!access(fname, R_OK))
00345         {
00346             struct stat s;
00347             if (!stat(fname, &s) && S_ISREG(s.st_mode))
00348                 return 1;
00349         }
00350     }
00351 
00352     return 0;
00353 }

SHOGUN Machine Learning Toolbox - Documentation