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

SHOGUN Machine Learning Toolbox - Documentation