SHOGUN
v1.1.0
|
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 00021 #include <stdio.h> 00022 #include <stdarg.h> 00023 #include <ctype.h> 00024 00025 #include <stdlib.h> 00026 00027 using namespace shogun; 00028 00029 const EMessageType SGIO::levels[NUM_LOG_LEVELS]={MSG_GCDEBUG, MSG_DEBUG, MSG_INFO, MSG_NOTICE, 00030 MSG_WARN, MSG_ERROR, MSG_CRITICAL, MSG_ALERT, MSG_EMERGENCY, MSG_MESSAGEONLY}; 00031 00032 const char* SGIO::message_strings[NUM_LOG_LEVELS]={"[GCDEBUG] \0", "[DEBUG] \0", "[INFO] \0", 00033 "[NOTICE] \0", "[WARN] \0", "[ERROR] \0", 00034 "[CRITICAL] \0", "[ALERT] \0", "[EMERGENCY] \0", "\0"}; 00035 00036 const char* SGIO::message_strings_highlighted[NUM_LOG_LEVELS]={"[GCDEBUG] \0", "[DEBUG] \0", "[INFO] \0", 00037 "[NOTICE] \0", "\033[1;34m[WARN]\033[0m \0", "\033[1;31m[ERROR]\033[0m \0", 00038 "[CRITICAL] \0", "[ALERT] \0", "[EMERGENCY] \0", "\0"}; 00039 00041 char SGIO::file_buffer[FBUFSIZE]; 00042 00044 char SGIO::directory_name[FBUFSIZE]; 00045 00046 SGIO::SGIO() 00047 : target(stdout), last_progress_time(0), progress_start_time(0), 00048 last_progress(1), show_progress(false), show_file_and_line(false), 00049 syntax_highlight(true), loglevel(MSG_WARN), refcount(0) 00050 { 00051 } 00052 00053 SGIO::SGIO(const SGIO& orig) 00054 : target(orig.get_target()), last_progress_time(0), 00055 progress_start_time(0), last_progress(1), 00056 show_progress(orig.get_show_progress()), 00057 show_file_and_line(orig.get_show_file_and_line()), 00058 syntax_highlight(orig.get_syntax_highlight()), 00059 loglevel(orig.get_loglevel()), refcount(0) 00060 { 00061 } 00062 00063 void SGIO::message(EMessageType prio, const char* file, 00064 int32_t line, const char *fmt, ... ) const 00065 { 00066 const char* msg_intro=get_msg_intro(prio); 00067 00068 if (msg_intro) 00069 { 00070 char str[4096]; 00071 snprintf(str, sizeof(str), "%s", msg_intro); 00072 int len=strlen(msg_intro); 00073 char* s=str+len; 00074 00075 if (show_file_and_line && line>=0) 00076 { 00077 snprintf(s, sizeof(str)-len, "In file %s line %d: ", file, line); 00078 len=strlen(str); 00079 s=str+len; 00080 } 00081 00082 va_list list; 00083 va_start(list,fmt); 00084 vsnprintf(s, sizeof(str)-len, fmt, list); 00085 va_end(list); 00086 00087 switch (prio) 00088 { 00089 case MSG_GCDEBUG: 00090 case MSG_DEBUG: 00091 case MSG_INFO: 00092 case MSG_NOTICE: 00093 case MSG_MESSAGEONLY: 00094 if (sg_print_message) 00095 sg_print_message(target, str); 00096 break; 00097 00098 case MSG_WARN: 00099 if (sg_print_warning) 00100 sg_print_warning(target, str); 00101 break; 00102 00103 case MSG_ERROR: 00104 case MSG_CRITICAL: 00105 case MSG_ALERT: 00106 case MSG_EMERGENCY: 00107 if (sg_print_error) 00108 sg_print_error(target, str); 00109 throw ShogunException(str); 00110 break; 00111 default: 00112 break; 00113 } 00114 00115 fflush(target); 00116 } 00117 } 00118 00119 void SGIO::buffered_message(EMessageType prio, const char *fmt, ... ) const 00120 { 00121 const char* msg_intro=get_msg_intro(prio); 00122 00123 if (msg_intro) 00124 { 00125 fprintf(target, "%s", msg_intro); 00126 va_list list; 00127 va_start(list,fmt); 00128 vfprintf(target,fmt,list); 00129 va_end(list); 00130 } 00131 } 00132 00133 void SGIO::progress( 00134 float64_t current_val, float64_t min_val, float64_t max_val, 00135 int32_t decimals, const char* prefix) 00136 { 00137 if (!show_progress) 00138 return; 00139 00140 float64_t runtime = CTime::get_curtime(); 00141 00142 char str[1000]; 00143 float64_t v=-1, estimate=0, total_estimate=0 ; 00144 00145 if (max_val-min_val>0.0) 00146 v=100*(current_val-min_val+1)/(max_val-min_val+1); 00147 00148 if (decimals < 1) 00149 decimals = 1; 00150 00151 if (last_progress>v) 00152 { 00153 last_progress_time = runtime; 00154 progress_start_time = runtime; 00155 last_progress = v; 00156 } 00157 else 00158 { 00159 v=CMath::clamp(v,1e-5,100.0); 00160 last_progress = v-1e-6; 00161 00162 if ((v!=100.0) && (runtime - last_progress_time<0.5)) 00163 return; 00164 00165 last_progress_time = runtime; 00166 estimate = (1-v/100)*(last_progress_time-progress_start_time)/(v/100); 00167 total_estimate = (last_progress_time-progress_start_time)/(v/100); 00168 } 00169 00170 if (estimate>120) 00171 { 00172 snprintf(str, sizeof(str), "%%s %%%d.%df%%%% %%1.1f minutes remaining %%1.1f minutes total \r",decimals+3, decimals); 00173 message(MSG_MESSAGEONLY, "", -1, str, prefix, v, estimate/60, total_estimate/60); 00174 } 00175 else 00176 { 00177 snprintf(str, sizeof(str), "%%s %%%d.%df%%%% %%1.1f seconds remaining %%1.1f seconds total \r",decimals+3, decimals); 00178 message(MSG_MESSAGEONLY, "", -1, str, prefix, v, estimate, total_estimate); 00179 } 00180 00181 fflush(target); 00182 } 00183 00184 void SGIO::absolute_progress( 00185 float64_t current_val, float64_t val, float64_t min_val, float64_t max_val, 00186 int32_t decimals, const char* prefix) 00187 { 00188 if (!show_progress) 00189 return; 00190 00191 float64_t runtime = CTime::get_curtime(); 00192 00193 char str[1000]; 00194 float64_t v=-1, estimate=0, total_estimate=0 ; 00195 00196 if (max_val-min_val>0) 00197 v=100*(val-min_val+1)/(max_val-min_val+1); 00198 00199 if (decimals < 1) 00200 decimals = 1; 00201 00202 if (last_progress>v) 00203 { 00204 last_progress_time = runtime; 00205 progress_start_time = runtime; 00206 last_progress = v; 00207 } 00208 else 00209 { 00210 v=CMath::clamp(v,1e-5,100.0); 00211 last_progress = v-1e-6; 00212 00213 if ((v!=100.0) && (runtime - last_progress_time<100)) 00214 return; 00215 00216 last_progress_time = runtime; 00217 estimate = (1-v/100)*(last_progress_time-progress_start_time)/(v/100); 00218 total_estimate = (last_progress_time-progress_start_time)/(v/100); 00219 } 00220 00221 if (estimate>120) 00222 { 00223 snprintf(str, sizeof(str), "%%s %%%d.%df %%1.1f minutes remaining %%1.1f minutes total \r",decimals+3, decimals); 00224 message(MSG_MESSAGEONLY, "", -1, str, prefix, current_val, estimate/60, total_estimate/60); 00225 } 00226 else 00227 { 00228 snprintf(str, sizeof(str), "%%s %%%d.%df %%1.1f seconds remaining %%1.1f seconds total \r",decimals+3, decimals); 00229 message(MSG_MESSAGEONLY, "", -1, str, prefix, current_val, estimate, total_estimate); 00230 } 00231 00232 fflush(target); 00233 } 00234 00235 void SGIO::done() 00236 { 00237 if (!show_progress) 00238 return; 00239 00240 message(MSG_INFO, "", -1, "done.\n"); 00241 } 00242 00243 char* SGIO::skip_spaces(char* str) 00244 { 00245 int32_t i=0; 00246 00247 if (str) 00248 { 00249 for (i=0; isspace(str[i]); i++); 00250 00251 return &str[i]; 00252 } 00253 else 00254 return str; 00255 } 00256 00257 char* SGIO::skip_blanks(char* str) 00258 { 00259 int32_t i=0; 00260 00261 if (str) 00262 { 00263 for (i=0; isblank(str[i]); i++); 00264 00265 return &str[i]; 00266 } 00267 else 00268 return str; 00269 } 00270 00271 EMessageType SGIO::get_loglevel() const 00272 { 00273 return loglevel; 00274 } 00275 00276 void SGIO::set_loglevel(EMessageType level) 00277 { 00278 loglevel=level; 00279 } 00280 00281 void SGIO::set_target(FILE* t) 00282 { 00283 target=t; 00284 } 00285 00286 const char* SGIO::get_msg_intro(EMessageType prio) const 00287 { 00288 for (int32_t i=NUM_LOG_LEVELS-1; i>=0; i--) 00289 { 00290 // ignore msg if prio's level is under loglevel, 00291 // but not if prio's level higher than MSG_WARN 00292 if (levels[i]<loglevel && prio<=MSG_WARN) 00293 return NULL; 00294 00295 if (levels[i]==prio) 00296 { 00297 if (syntax_highlight) 00298 return message_strings_highlighted[i]; 00299 else 00300 return message_strings[i]; 00301 } 00302 } 00303 00304 return NULL; 00305 }