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()
00045 : target(stdout), last_progress_time(0), progress_start_time(0),
00046     last_progress(1), show_progress(false), loglevel(M_WARN)
00047 {
00048 }
00049 
00050 CIO::CIO(const CIO& orig)
00051 : target(orig.get_target()), last_progress_time(0),
00052     progress_start_time(0), last_progress(1),
00053     show_progress(orig.get_show_progress()), loglevel(orig.get_loglevel())
00054 {
00055 }
00056 
00057 void CIO::message(EMessageType prio, const char *fmt, ... ) const
00058 {
00059     const char* msg_intro=get_msg_intro(prio);
00060     if (!msg_intro)
00061         return;
00062 
00063     char str[4096];
00064     va_list list;
00065     va_start(list,fmt);
00066     vsnprintf(str, sizeof(str), fmt, list);
00067     va_end(list);
00068 
00069     switch (prio)
00070     {
00071         case M_DEBUG:
00072         case M_INFO:
00073         case M_NOTICE:
00074         case M_MESSAGEONLY:
00075 #if defined(WIN32) && defined(HAVE_MATLAB)
00076             fprintf(target, "%s", msg_intro);
00077             mexPrintf("%s", str);
00078 #elif defined(HAVE_R)
00079             if (target==stdout)
00080             {
00081                 Rprintf((char*) "%s", msg_intro);
00082                 Rprintf((char*) "%s", str);
00083             }
00084             else
00085             {
00086                 fprintf(target, "%s", msg_intro);
00087                 fprintf(target, "%s", str);
00088             }
00089 #else
00090             fprintf(target, "%s", msg_intro);
00091             fprintf(target, "%s", str);
00092 #endif
00093             break;
00094 
00095         case M_WARN:
00096 #if defined(HAVE_MATLAB)
00097             mexWarnMsgTxt(str);
00098 #elif defined(HAVE_OCTAVE)
00099             ::warning(str);
00100 #elif defined(HAVE_PYTHON) // no check for swig necessary
00101             PyErr_Warn(NULL, str);
00102 #elif defined(HAVE_R)
00103             if (target==stdout)
00104             {
00105                 Rprintf((char*) "%s", msg_intro);
00106                 Rprintf((char*) "%s", str);
00107             }
00108             else
00109             {
00110                 fprintf(target, "%s", msg_intro);
00111                 fprintf(target, "%s", str);
00112             }
00113 #else
00114             fprintf(target, "%s", msg_intro);
00115             fprintf(target, "%s", str);
00116 #endif
00117             break;
00118 
00119         case M_ERROR:
00120         case M_CRITICAL:
00121         case M_ALERT:
00122         case M_EMERGENCY:
00123 #if defined(WIN32) && defined(HAVE_MATLAB)
00124             mexPrintf("%s", str);
00125 #elif defined(HAVE_PYTHON)
00126             // nop - str will be printed when exception is displayed in python
00127 #elif defined(HAVE_R)
00128             if (target==stdout)
00129             {
00130                 Rprintf((char*) "%s", msg_intro);
00131                 Rprintf((char*) "%s", str);
00132             }
00133             else
00134             {
00135                 fprintf(target, "%s", msg_intro);
00136                 fprintf(target, "%s", str);
00137             }
00138 #else
00139             fprintf(target, "%s", str);
00140 #endif
00141             throw ShogunException(str);
00142             break;
00143         default:
00144             break;
00145     }
00146 
00147     fflush(target);
00148 }
00149 
00150 void CIO::buffered_message(EMessageType prio, const char *fmt, ... ) const
00151 {
00152     const char* msg_intro=get_msg_intro(prio);
00153     if (!msg_intro)
00154         return;
00155 
00156     fprintf(target, "%s", msg_intro);
00157     va_list list;
00158     va_start(list,fmt);
00159     vfprintf(target,fmt,list);
00160     va_end(list);
00161 }
00162 
00163 void CIO::progress(
00164     float64_t current_val, float64_t min_val, float64_t max_val,
00165     int32_t decimals, const char* prefix)
00166 {
00167     if (!show_progress)
00168         return;
00169 
00170     int64_t runtime = CTime::get_runtime();
00171 
00172     char str[1000];
00173     float64_t v=-1, estimate=0, total_estimate=0 ;
00174 
00175     if (max_val-min_val>0.0)
00176         v=100*(current_val-min_val+1)/(max_val-min_val+1);
00177 
00178     if (decimals < 1)
00179         decimals = 1;
00180 
00181     if (last_progress>v)
00182     {
00183         last_progress_time = runtime ;
00184         progress_start_time = runtime;
00185         last_progress = v ;
00186     }
00187     else
00188     {
00189         if (v>100) v=100.0 ;
00190         if (v<=0) v=1e-5 ;
00191         last_progress = v-1e-6 ; ;
00192 
00193         if ((v!=100.0) && (runtime - last_progress_time<10))
00194             return ;
00195 
00196         last_progress_time = runtime ;
00197         estimate = (1-v/100)*(last_progress_time-progress_start_time)/(v/100) ;
00198         total_estimate = (last_progress_time-progress_start_time)/(v/100) ;
00199     }
00200 
00201     if (estimate/100>120)
00202     {
00203         snprintf(str, sizeof(str), "%%s %%%d.%df%%%%    %%1.1f minutes remaining    %%1.1f minutes total    \r",decimals+3, decimals);
00204         message(M_MESSAGEONLY, str, prefix, v, (float32_t)estimate/100/60, (float32_t)total_estimate/100/60);
00205     }
00206     else
00207     {
00208         snprintf(str, sizeof(str), "%%s %%%d.%df%%%%    %%1.1f seconds remaining    %%1.1f seconds total    \r",decimals+3, decimals);
00209         message(M_MESSAGEONLY, str, prefix, v, (float32_t)estimate/100, (float32_t)total_estimate/100);
00210     }
00211 
00212     fflush(target);
00213 }
00214 
00215 void CIO::absolute_progress(
00216     float64_t current_val, float64_t val, float64_t min_val, float64_t max_val,
00217     int32_t decimals, const char* prefix)
00218 {
00219     if (!show_progress)
00220         return;
00221 
00222     int64_t runtime = CTime::get_runtime();
00223 
00224     char str[1000];
00225     float64_t v=-1, estimate=0, total_estimate=0 ;
00226 
00227     if (max_val-min_val>0)
00228         v=100*(val-min_val+1)/(max_val-min_val+1);
00229 
00230     if (decimals < 1)
00231         decimals = 1;
00232 
00233     if (last_progress>v)
00234     {
00235         last_progress_time = runtime ;
00236         progress_start_time = runtime;
00237         last_progress = v ;
00238     }
00239     else
00240     {
00241         if (v>100) v=100.0 ;
00242         if (v<=0) v=1e-6 ;
00243         last_progress = v-1e-5 ; ;
00244 
00245         if ((v!=100.0) && (runtime - last_progress_time<100))
00246             return ;
00247 
00248         last_progress_time = runtime ;
00249         estimate = (1-v/100)*(last_progress_time-progress_start_time)/(v/100) ;
00250         total_estimate = (last_progress_time-progress_start_time)/(v/100) ;
00251     }
00252 
00253     if (estimate/100>120)
00254     {
00255         snprintf(str, sizeof(str), "%%s %%%d.%df    %%1.1f minutes remaining    %%1.1f minutes total    \r",decimals+3, decimals);
00256         message(M_MESSAGEONLY, str, prefix, current_val, (float32_t)estimate/100/60, (float32_t)total_estimate/100/60);
00257     }
00258     else
00259     {
00260         snprintf(str, sizeof(str), "%%s %%%d.%df    %%1.1f seconds remaining    %%1.1f seconds total    \r",decimals+3, decimals);
00261         message(M_MESSAGEONLY, str, prefix, current_val, (float32_t)estimate/100, (float32_t)total_estimate/100);
00262     }
00263 
00264     fflush(target);
00265 }
00266 
00267 void CIO::done()
00268 {
00269     if (!show_progress)
00270         return;
00271 
00272     message(M_INFO, "done.\n");
00273 }
00274 
00275 char* CIO::skip_spaces(char* str)
00276 {
00277     int32_t i=0;
00278 
00279     if (str)
00280     {
00281         for (i=0; isspace(str[i]); i++);
00282 
00283         return &str[i];
00284     }
00285     else
00286         return str;
00287 }
00288 
00289 char* CIO::skip_blanks(char* str)
00290 {
00291     int32_t i=0;
00292 
00293     if (str)
00294     {
00295         for (i=0; isblank(str[i]); i++);
00296 
00297         return &str[i];
00298     }
00299     else
00300         return str;
00301 }
00302 
00303 EMessageType CIO::get_loglevel() const
00304 {
00305     return loglevel;
00306 }
00307 
00308 void CIO::set_loglevel(EMessageType level)
00309 {
00310     loglevel=level;
00311 }
00312 
00313 bool CIO::get_show_progress() const
00314 {
00315     return show_progress;
00316 }
00317 
00318 void CIO::set_target(FILE* t)
00319 {
00320     target=t;
00321 }
00322 
00323 const char* CIO::get_msg_intro(EMessageType prio) const
00324 {
00325     for (int32_t i=NUM_LOG_LEVELS-1; i>=0; i--)
00326     {
00327         // ignore msg if prio's level is under loglevel,
00328         // but not if prio's level higher than M_WARN
00329         if (levels[i]<loglevel && prio<=M_WARN)
00330             return NULL;
00331 
00332         if (levels[i]==prio)
00333             return message_strings[i];
00334     }
00335 
00336     return NULL;
00337 }
00338 
00339 char* CIO::concat_filename(const char* filename)
00340 {
00341     if (snprintf(file_buffer, FBUFSIZE, "%s/%s", directory_name, filename) > FBUFSIZE)
00342         SG_SERROR("filename too long");
00343     return file_buffer;
00344 }
00345 
00346 int CIO::filter(CONST_DIRENT_T* d)
00347 {
00348     if (d)
00349     {
00350         char* fname=concat_filename(d->d_name);
00351 
00352         if (!access(fname, R_OK))
00353         {
00354             struct stat s;
00355             if (!stat(fname, &s) && S_ISREG(s.st_mode))
00356                 return 1;
00357         }
00358     }
00359 
00360     return 0;
00361 }

SHOGUN Machine Learning Toolbox - Documentation