SHOGUN  v3.2.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
SGIO.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-2009 Soeren Sonnenburg
00008  * Written (W) 1999-2009 Gunnar Raetsch
00009  * Copyright (C) 1999-2009 Fraunhofer Institute FIRST and Max-Planck-Society
00010  */
00011 
00012 #include <shogun/lib/config.h>
00013 
00014 #include <shogun/io/SGIO.h>
00015 #include <shogun/lib/ShogunException.h>
00016 #include <shogun/lib/Signal.h>
00017 #include <shogun/lib/common.h>
00018 #include <shogun/lib/Time.h>
00019 #include <shogun/mathematics/Math.h>
00020 #include <shogun/lib/RefCount.h>
00021 
00022 #include <stdio.h>
00023 #include <stdarg.h>
00024 #include <ctype.h>
00025 
00026 #include <stdlib.h>
00027 
00028 using namespace shogun;
00029 
00030 const EMessageType SGIO::levels[NUM_LOG_LEVELS]={MSG_GCDEBUG, MSG_DEBUG, MSG_INFO, MSG_NOTICE,
00031     MSG_WARN, MSG_ERROR, MSG_CRITICAL, MSG_ALERT, MSG_EMERGENCY, MSG_MESSAGEONLY};
00032 
00033 const char* SGIO::message_strings[NUM_LOG_LEVELS]={"[GCDEBUG] \0", "[DEBUG] \0", "[INFO] \0",
00034     "[NOTICE] \0", "[WARN] \0", "[ERROR] \0",
00035     "[CRITICAL] \0", "[ALERT] \0", "[EMERGENCY] \0", "\0"};
00036 
00037 const char* SGIO::message_strings_highlighted[NUM_LOG_LEVELS]={"[GCDEBUG] \0", "[DEBUG] \0", "[INFO] \0",
00038     "[NOTICE] \0", "\033[1;34m[WARN]\033[0m \0", "\033[1;31m[ERROR]\033[0m \0",
00039     "[CRITICAL] \0", "[ALERT] \0", "[EMERGENCY] \0", "\0"};
00040 
00042 char SGIO::file_buffer[FBUFSIZE];
00043 
00045 char SGIO::directory_name[FBUFSIZE];
00046 
00047 SGIO::SGIO()
00048 : target(stdout), last_progress_time(0), progress_start_time(0),
00049     last_progress(1), show_progress(false), location_info(MSG_NONE),
00050     syntax_highlight(true), loglevel(MSG_WARN)
00051 {
00052     m_refcount = new RefCount();
00053 }
00054 
00055 SGIO::SGIO(const SGIO& orig)
00056 : target(orig.get_target()), last_progress_time(0),
00057     progress_start_time(0), last_progress(1),
00058     show_progress(orig.get_show_progress()),
00059     location_info(orig.get_location_info()),
00060     syntax_highlight(orig.get_syntax_highlight()),
00061     loglevel(orig.get_loglevel())
00062 {
00063     m_refcount = new RefCount(orig.m_refcount->ref_count());
00064 }
00065 
00066 void SGIO::message(EMessageType prio, const char* function, const char* file,
00067         int32_t line, const char *fmt, ... ) const
00068 {
00069     const char* msg_intro=get_msg_intro(prio);
00070 
00071     if (msg_intro)
00072     {
00073         char str[4096];
00074         snprintf(str, sizeof(str), "%s", msg_intro);
00075         int len=strlen(msg_intro);
00076         char* s=str+len;
00077 
00078         /* file and line are shown for warnings and worse */
00079         if (location_info==MSG_LINE_AND_FILE || prio==MSG_WARN || prio==MSG_ERROR)
00080         {
00081             snprintf(s, sizeof(str)-len, "In file %s line %d: ", file, line);
00082             len=strlen(str);
00083             s=str+len;
00084         }
00085         else if (location_info==MSG_FUNCTION)
00086         {
00087             snprintf(s, sizeof(str)-len, "%s: ", function);
00088             len=strlen(str);
00089             s=str+len;
00090         }
00091         else if (location_info==MSG_NONE)
00092         {
00093             ;
00094         }
00095 
00096         va_list list;
00097         va_start(list,fmt);
00098         vsnprintf(s, sizeof(str)-len, fmt, list);
00099         va_end(list);
00100 
00101         switch (prio)
00102         {
00103             case MSG_GCDEBUG:
00104             case MSG_DEBUG:
00105             case MSG_INFO:
00106             case MSG_NOTICE:
00107             case MSG_MESSAGEONLY:
00108                 if (sg_print_message)
00109                     sg_print_message(target, str);
00110                 break;
00111 
00112             case MSG_WARN:
00113                 if (sg_print_warning)
00114                     sg_print_warning(target, str);
00115                 break;
00116 
00117             case MSG_ERROR:
00118             case MSG_CRITICAL:
00119             case MSG_ALERT:
00120             case MSG_EMERGENCY:
00121                 if (sg_print_error)
00122                     sg_print_error(target, str);
00123                 throw ShogunException(str);
00124                 break;
00125             default:
00126                 break;
00127         }
00128 
00129         fflush(target);
00130     }
00131 }
00132 
00133 void SGIO::buffered_message(EMessageType prio, const char *fmt, ... ) const
00134 {
00135     const char* msg_intro=get_msg_intro(prio);
00136 
00137     if (msg_intro)
00138     {
00139         fprintf(target, "%s", msg_intro);
00140         va_list list;
00141         va_start(list,fmt);
00142         vfprintf(target,fmt,list);
00143         va_end(list);
00144     }
00145 }
00146 
00147 void SGIO::progress(
00148     float64_t current_val, float64_t min_val, float64_t max_val,
00149     int32_t decimals, const char* prefix)
00150 {
00151     if (!show_progress)
00152         return;
00153 
00154     float64_t runtime = CTime::get_curtime();
00155 
00156     char str[1000];
00157     float64_t v=-1, estimate=0, total_estimate=0 ;
00158 
00159     if (max_val-min_val>0.0)
00160         v=100*(current_val-min_val+1)/(max_val-min_val+1);
00161 
00162     if (decimals < 1)
00163         decimals = 1;
00164 
00165     if (last_progress>v)
00166     {
00167         last_progress_time = runtime;
00168         progress_start_time = runtime;
00169         last_progress = v;
00170     }
00171     else
00172     {
00173         v=CMath::clamp(v,1e-5,100.0);
00174         last_progress = v-1e-6;
00175 
00176         if ((v!=100.0) && (runtime - last_progress_time<0.5))
00177             return;
00178 
00179         last_progress_time = runtime;
00180         estimate = (1-v/100)*(last_progress_time-progress_start_time)/(v/100);
00181         total_estimate = (last_progress_time-progress_start_time)/(v/100);
00182     }
00183 
00184     if (estimate>120)
00185     {
00186         snprintf(str, sizeof(str), "%%s %%%d.%df%%%%    %%1.1f minutes remaining    %%1.1f minutes total    \r",decimals+3, decimals);
00187         message(MSG_MESSAGEONLY, "", "", -1, str, prefix, v, estimate/60, total_estimate/60);
00188     }
00189     else
00190     {
00191         snprintf(str, sizeof(str), "%%s %%%d.%df%%%%    %%1.1f seconds remaining    %%1.1f seconds total    \r",decimals+3, decimals);
00192         message(MSG_MESSAGEONLY, "", "", -1, str, prefix, v, estimate, total_estimate);
00193     }
00194 
00195     fflush(target);
00196 }
00197 
00198 void SGIO::absolute_progress(
00199     float64_t current_val, float64_t val, float64_t min_val, float64_t max_val,
00200     int32_t decimals, const char* prefix)
00201 {
00202     if (!show_progress)
00203         return;
00204 
00205     float64_t runtime = CTime::get_curtime();
00206 
00207     char str[1000];
00208     float64_t v=-1, estimate=0, total_estimate=0 ;
00209 
00210     if (max_val-min_val>0)
00211         v=100*(val-min_val+1)/(max_val-min_val+1);
00212 
00213     if (decimals < 1)
00214         decimals = 1;
00215 
00216     if (last_progress>v)
00217     {
00218         last_progress_time = runtime;
00219         progress_start_time = runtime;
00220         last_progress = v;
00221     }
00222     else
00223     {
00224         v=CMath::clamp(v,1e-5,100.0);
00225         last_progress = v-1e-6;
00226 
00227         if ((v!=100.0) && (runtime - last_progress_time<100))
00228             return;
00229 
00230         last_progress_time = runtime;
00231         estimate = (1-v/100)*(last_progress_time-progress_start_time)/(v/100);
00232         total_estimate = (last_progress_time-progress_start_time)/(v/100);
00233     }
00234 
00235     if (estimate>120)
00236     {
00237         snprintf(str, sizeof(str), "%%s %%%d.%df    %%1.1f minutes remaining    %%1.1f minutes total    \r",decimals+3, decimals);
00238         message(MSG_MESSAGEONLY, "", "", -1, str, prefix, current_val, estimate/60, total_estimate/60);
00239     }
00240     else
00241     {
00242         snprintf(str, sizeof(str), "%%s %%%d.%df    %%1.1f seconds remaining    %%1.1f seconds total    \r",decimals+3, decimals);
00243         message(MSG_MESSAGEONLY, "", "", -1, str, prefix, current_val, estimate, total_estimate);
00244     }
00245 
00246     fflush(target);
00247 }
00248 
00249 void SGIO::done()
00250 {
00251     if (!show_progress)
00252         return;
00253 
00254     message(MSG_INFO, "", "", -1, "done.\n");
00255 }
00256 
00257 char* SGIO::skip_spaces(char* str)
00258 {
00259     int32_t i=0;
00260 
00261     if (str)
00262     {
00263         for (i=0; isspace(str[i]); i++);
00264 
00265         return &str[i];
00266     }
00267     else
00268         return str;
00269 }
00270 
00271 char* SGIO::skip_blanks(char* str)
00272 {
00273     int32_t i=0;
00274 
00275     if (str)
00276     {
00277         for (i=0; isblank(str[i]); i++);
00278 
00279         return &str[i];
00280     }
00281     else
00282         return str;
00283 }
00284 
00285 EMessageType SGIO::get_loglevel() const
00286 {
00287     return loglevel;
00288 }
00289 
00290 void SGIO::set_loglevel(EMessageType level)
00291 {
00292     loglevel=level;
00293 }
00294 
00295 void SGIO::set_target(FILE* t)
00296 {
00297     target=t;
00298 }
00299 
00300 const char* SGIO::get_msg_intro(EMessageType prio) const
00301 {
00302     for (int32_t i=NUM_LOG_LEVELS-1; i>=0; i--)
00303     {
00304         // ignore msg if prio's level is under loglevel,
00305         // but not if prio's level higher than MSG_WARN
00306         if (levels[i]<loglevel && prio<=MSG_WARN)
00307             return NULL;
00308 
00309         if (levels[i]==prio)
00310         {
00311             if (syntax_highlight)
00312                 return message_strings_highlighted[i];
00313             else
00314                 return message_strings[i];
00315         }
00316     }
00317 
00318     return NULL;
00319 }
00320 
00321 char* SGIO::c_string_of_substring(substring s)
00322 {
00323     uint32_t len = s.end - s.start+1;
00324     char* ret = SG_CALLOC(char, len);
00325     memcpy(ret,s.start,len-1);
00326     return ret;
00327 }
00328 
00329 void SGIO::print_substring(substring s)
00330 {
00331     char* c_string = c_string_of_substring(s);
00332     SG_SPRINT("%s\n", c_string)
00333     SG_FREE(c_string);
00334 }
00335 
00336 float32_t SGIO::float_of_substring(substring s)
00337 {
00338     char* endptr = s.end;
00339     float32_t f = strtof(s.start,&endptr);
00340     if (endptr == s.start && s.start != s.end)
00341         SG_SERROR("error: %s is not a float!\n", c_string_of_substring(s))
00342 
00343     return f;
00344 }
00345 
00346 float64_t SGIO::double_of_substring(substring s)
00347 {
00348     char* endptr = s.end;
00349     float64_t f = strtod(s.start,&endptr);
00350     if (endptr == s.start && s.start != s.end)
00351         SG_SERROR("Error!:%s is not a double!\n", c_string_of_substring(s))
00352 
00353     return f;
00354 }
00355 
00356 int32_t SGIO::int_of_substring(substring s)
00357 {
00358     char* c_string = c_string_of_substring(s);
00359     int32_t int_val = atoi(c_string);
00360     SG_FREE(c_string);
00361 
00362     return int_val;
00363 }
00364 
00365 uint32_t SGIO::ulong_of_substring(substring s)
00366 {
00367     return strtoul(s.start,NULL,10);
00368 }
00369 
00370 uint32_t SGIO::ss_length(substring s)
00371 {
00372     return (s.end - s.start);
00373 }
00374 
00375 char* SGIO::concat_filename(const char* filename)
00376 {
00377     if (snprintf(file_buffer, FBUFSIZE, "%s/%s", directory_name, filename) > FBUFSIZE)
00378         SG_SERROR("filename too long")
00379 
00380     SG_SDEBUG("filename=\"%s\"\n", file_buffer)
00381     return file_buffer;
00382 }
00383 
00384 int SGIO::filter(CONST_DIRENT_T* d)
00385 {
00386     if (d)
00387     {
00388         char* fname=concat_filename(d->d_name);
00389 
00390         if (!access(fname, R_OK))
00391         {
00392             struct stat s;
00393             if (!stat(fname, &s) && S_ISREG(s.st_mode))
00394                 return 1;
00395         }
00396     }
00397 
00398     return 0;
00399 }
00400 
00401 SGIO::~SGIO()
00402 {
00403     delete m_refcount;
00404 }
00405 
00406 int32_t SGIO::ref()
00407 {
00408     return m_refcount->ref();
00409 }
00410 
00411 int32_t SGIO::ref_count() const
00412 {
00413     return m_refcount->ref_count();
00414 }
00415 
00416 int32_t SGIO::unref()
00417 {
00418     int32_t rc = m_refcount->unref();
00419     if (rc==0)
00420     {
00421         delete this;
00422         return 0;
00423     }
00424 
00425     return rc;
00426 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

SHOGUN Machine Learning Toolbox - Documentation