00001
00002
00003
00004
00005
00006
00007
00008
00009
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
00291
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 }