SHOGUN  4.1.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SGIO.cpp
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 3 of the License, or
5  * (at your option) any later version.
6  *
7  * Written (W) 1999-2009 Soeren Sonnenburg
8  * Written (W) 1999-2009 Gunnar Raetsch
9  * Copyright (C) 1999-2009 Fraunhofer Institute FIRST and Max-Planck-Society
10  */
11 
12 #include <shogun/io/SGIO.h>
14 #include <shogun/lib/common.h>
15 #include <shogun/base/init.h>
16 #include <shogun/lib/memory.h>
17 #include <shogun/lib/Time.h>
19 #include <shogun/lib/RefCount.h>
20 
21 #include <stdarg.h>
22 #include <ctype.h>
23 #include <dirent.h>
24 #include <sys/stat.h>
25 #include <unistd.h>
26 #include <stdlib.h>
27 
28 using namespace shogun;
29 
32 
33 const char* SGIO::message_strings[NUM_LOG_LEVELS]={"[GCDEBUG] \0", "[DEBUG] \0", "[INFO] \0",
34  "[NOTICE] \0", "[WARN] \0", "[ERROR] \0",
35  "[CRITICAL] \0", "[ALERT] \0", "[EMERGENCY] \0", "\0"};
36 
37 const char* SGIO::message_strings_highlighted[NUM_LOG_LEVELS]={"[GCDEBUG] \0", "[DEBUG] \0", "[INFO] \0",
38  "[NOTICE] \0", "\033[1;34m[WARN]\033[0m \0", "\033[1;31m[ERROR]\033[0m \0",
39  "[CRITICAL] \0", "[ALERT] \0", "[EMERGENCY] \0", "\0"};
40 
43 
46 
48 : target(stdout), last_progress_time(0), progress_start_time(0),
49  last_progress(1), show_progress(false), location_info(MSG_NONE),
50  syntax_highlight(true), loglevel(MSG_WARN)
51 {
52  m_refcount = new RefCount();
53 }
54 
55 SGIO::SGIO(const SGIO& orig)
56 : target(orig.get_target()), last_progress_time(0),
57  progress_start_time(0), last_progress(1),
58  show_progress(orig.get_show_progress()),
59  location_info(orig.get_location_info()),
60  syntax_highlight(orig.get_syntax_highlight()),
61  loglevel(orig.get_loglevel())
62 {
63  m_refcount = new RefCount();
64 }
65 
66 void SGIO::message(EMessageType prio, const char* function, const char* file,
67  int32_t line, const char *fmt, ... ) const
68 {
69  const char* msg_intro=get_msg_intro(prio);
70 
71  if (msg_intro)
72  {
73  char str[4096];
74  snprintf(str, sizeof(str), "%s", msg_intro);
75  int len=strlen(msg_intro);
76  char* s=str+len;
77 
78  /* file and line are shown for warnings and worse */
79  if (location_info==MSG_LINE_AND_FILE || prio==MSG_WARN || prio==MSG_ERROR)
80  {
81  snprintf(s, sizeof(str)-len, "In file %s line %d: ", file, line);
82  len=strlen(str);
83  s=str+len;
84  }
85  else if (location_info==MSG_FUNCTION)
86  {
87  snprintf(s, sizeof(str)-len, "%s: ", function);
88  len=strlen(str);
89  s=str+len;
90  }
91  else if (location_info==MSG_NONE)
92  {
93  ;
94  }
95 
96  va_list list;
97  va_start(list,fmt);
98  vsnprintf(s, sizeof(str)-len, fmt, list);
99  va_end(list);
100 
101  switch (prio)
102  {
103  case MSG_GCDEBUG:
104  case MSG_DEBUG:
105  case MSG_INFO:
106  case MSG_NOTICE:
107  case MSG_MESSAGEONLY:
108  if (sg_print_message)
109  sg_print_message(target, str);
110  break;
111 
112  case MSG_WARN:
113  if (sg_print_warning)
114  sg_print_warning(target, str);
115  break;
116 
117  case MSG_ERROR:
118  case MSG_CRITICAL:
119  case MSG_ALERT:
120  case MSG_EMERGENCY:
121  if (sg_print_error)
122  sg_print_error(target, str);
123  throw ShogunException(str);
124  break;
125  default:
126  break;
127  }
128 
129  fflush(target);
130  }
131 }
132 
133 void SGIO::buffered_message(EMessageType prio, const char *fmt, ... ) const
134 {
135  const char* msg_intro=get_msg_intro(prio);
136 
137  if (msg_intro)
138  {
139  fprintf(target, "%s", msg_intro);
140  va_list list;
141  va_start(list,fmt);
142  vfprintf(target,fmt,list);
143  va_end(list);
144  }
145 }
146 
148  float64_t current_val, float64_t min_val, float64_t max_val,
149  int32_t decimals, const char* prefix)
150 {
151  if (!show_progress)
152  return;
153 
154  float64_t runtime = CTime::get_curtime();
155 
156  char str[1000];
157  float64_t v=-1, estimate=0, total_estimate=0 ;
158 
159  if (max_val-min_val>0.0)
160  v=100*(current_val-min_val+1)/(max_val-min_val+1);
161 
162  if (decimals < 1)
163  decimals = 1;
164 
165  if (last_progress>v)
166  {
167  last_progress_time = runtime;
168  progress_start_time = runtime;
169  last_progress = v;
170  }
171  else
172  {
173  v=CMath::clamp(v,1e-5,100.0);
174  last_progress = v-1e-6;
175 
176  if ((v!=100.0) && (runtime - last_progress_time<0.5))
177  return;
178 
179  last_progress_time = runtime;
180  estimate = (1-v/100)*(last_progress_time-progress_start_time)/(v/100);
181  total_estimate = (last_progress_time-progress_start_time)/(v/100);
182  }
183 
184  if (estimate>120)
185  {
186  snprintf(str, sizeof(str), "%%s %%%d.%df%%%% %%1.1f minutes remaining %%1.1f minutes total \r",decimals+3, decimals);
187  message(MSG_MESSAGEONLY, "", "", -1, str, prefix, v, estimate/60, total_estimate/60);
188  }
189  else
190  {
191  snprintf(str, sizeof(str), "%%s %%%d.%df%%%% %%1.1f seconds remaining %%1.1f seconds total \r",decimals+3, decimals);
192  message(MSG_MESSAGEONLY, "", "", -1, str, prefix, v, estimate, total_estimate);
193  }
194 
195  fflush(target);
196 }
197 
199  float64_t current_val, float64_t val, float64_t min_val, float64_t max_val,
200  int32_t decimals, const char* prefix)
201 {
202  if (!show_progress)
203  return;
204 
205  float64_t runtime = CTime::get_curtime();
206 
207  char str[1000];
208  float64_t v=-1, estimate=0, total_estimate=0 ;
209 
210  if (max_val-min_val>0)
211  v=100*(val-min_val+1)/(max_val-min_val+1);
212 
213  if (decimals < 1)
214  decimals = 1;
215 
216  if (last_progress>v)
217  {
218  last_progress_time = runtime;
219  progress_start_time = runtime;
220  last_progress = v;
221  }
222  else
223  {
224  v=CMath::clamp(v,1e-5,100.0);
225  last_progress = v-1e-6;
226 
227  if ((v!=100.0) && (runtime - last_progress_time<100))
228  return;
229 
230  last_progress_time = runtime;
231  estimate = (1-v/100)*(last_progress_time-progress_start_time)/(v/100);
232  total_estimate = (last_progress_time-progress_start_time)/(v/100);
233  }
234 
235  if (estimate>120)
236  {
237  snprintf(str, sizeof(str), "%%s %%%d.%df %%1.1f minutes remaining %%1.1f minutes total \r",decimals+3, decimals);
238  message(MSG_MESSAGEONLY, "", "", -1, str, prefix, current_val, estimate/60, total_estimate/60);
239  }
240  else
241  {
242  snprintf(str, sizeof(str), "%%s %%%d.%df %%1.1f seconds remaining %%1.1f seconds total \r",decimals+3, decimals);
243  message(MSG_MESSAGEONLY, "", "", -1, str, prefix, current_val, estimate, total_estimate);
244  }
245 
246  fflush(target);
247 }
248 
250 {
251  if (!show_progress)
252  return;
253 
254  message(MSG_INFO, "", "", -1, "done.\n");
255 }
256 
257 char* SGIO::skip_spaces(char* str)
258 {
259  int32_t i=0;
260 
261  if (str)
262  {
263  for (i=0; isspace(str[i]); i++);
264 
265  return &str[i];
266  }
267  else
268  return str;
269 }
270 
271 char* SGIO::skip_blanks(char* str)
272 {
273  int32_t i=0;
274 
275  if (str)
276  {
277  for (i=0; isblank(str[i]); i++);
278 
279  return &str[i];
280  }
281  else
282  return str;
283 }
284 
286 {
287  return loglevel;
288 }
289 
291 {
292  loglevel=level;
293 }
294 
295 void SGIO::set_target(FILE* t)
296 {
297  target=t;
298 }
299 
300 const char* SGIO::get_msg_intro(EMessageType prio) const
301 {
302  for (int32_t i=NUM_LOG_LEVELS-1; i>=0; i--)
303  {
304  // ignore msg if prio's level is under loglevel,
305  // but not if prio's level higher than MSG_WARN
306  if (levels[i]<loglevel && prio<=MSG_WARN)
307  return NULL;
308 
309  if (levels[i]==prio)
310  {
311  if (syntax_highlight)
312  return message_strings_highlighted[i];
313  else
314  return message_strings[i];
315  }
316  }
317 
318  return NULL;
319 }
320 
322 {
323  uint32_t len = s.end - s.start+1;
324  char* ret = SG_CALLOC(char, len);
325  memcpy(ret,s.start,len-1);
326  return ret;
327 }
328 
330 {
331  char* c_string = c_string_of_substring(s);
332  SG_SPRINT("%s\n", c_string)
333  SG_FREE(c_string);
334 }
335 
337 {
338  char* endptr = s.end;
339  float32_t f = strtof(s.start,&endptr);
340  if (endptr == s.start && s.start != s.end)
341  SG_SERROR("error: %s is not a float!\n", c_string_of_substring(s))
342 
343  return f;
344 }
345 
347 {
348  char* endptr = s.end;
349  float64_t f = strtod(s.start,&endptr);
350  if (endptr == s.start && s.start != s.end)
351  SG_SERROR("Error!:%s is not a double!\n", c_string_of_substring(s))
352 
353  return f;
354 }
355 
357 {
358  char* c_string = c_string_of_substring(s);
359  int32_t int_val = atoi(c_string);
360  SG_FREE(c_string);
361 
362  return int_val;
363 }
364 
366 {
367  return strtoul(s.start,NULL,10);
368 }
369 
371 {
372  return (s.end - s.start);
373 }
374 
375 char* SGIO::concat_filename(const char* filename)
376 {
377  if (snprintf(file_buffer, FBUFSIZE, "%s/%s", directory_name, filename) > FBUFSIZE)
378  SG_SERROR("filename too long")
379 
380  SG_SDEBUG("filename=\"%s\"\n", file_buffer)
381  return file_buffer;
382 }
383 
385 {
386  if (d)
387  {
388  char* fname=concat_filename(d->d_name);
389 
390  if (!access(fname, R_OK))
391  {
392  struct stat s;
393  if (!stat(fname, &s) && S_ISREG(s.st_mode))
394  return 1;
395  }
396  }
397 
398  return 0;
399 }
400 
402 {
403  delete m_refcount;
404 }
405 
406 int32_t SGIO::ref()
407 {
408  return m_refcount->ref();
409 }
410 
411 int32_t SGIO::ref_count() const
412 {
413  return m_refcount->ref_count();
414 }
415 
416 int32_t SGIO::unref()
417 {
418  int32_t rc = m_refcount->unref();
419  if (rc==0)
420  {
421  delete this;
422  return 0;
423  }
424 
425  return rc;
426 }

SHOGUN Machine Learning Toolbox - Documentation