SHOGUN
v2.0.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-2008 Gunnar Raetsch 00009 * Copyright (C) 1999-2009 Fraunhofer Institute FIRST and Max-Planck-Society 00010 */ 00011 00012 #ifndef __SGIO_H__ 00013 #define __SGIO_H__ 00014 00015 #include <stdio.h> 00016 #include <stdarg.h> 00017 #include <string.h> 00018 #include <dirent.h> 00019 #include <unistd.h> 00020 #include <locale.h> 00021 00022 #include <sys/types.h> 00023 #include <sys/stat.h> 00024 00025 #include <shogun/lib/common.h> 00026 #include <shogun/base/init.h> 00027 00028 namespace shogun 00029 { 00030 class SGIO; 00032 extern SGIO* sg_io; 00033 } 00034 00035 00036 namespace shogun 00037 { 00042 enum EMessageType 00043 { 00044 MSG_GCDEBUG, 00045 MSG_DEBUG, 00046 MSG_INFO, 00047 MSG_NOTICE, 00048 MSG_WARN, 00049 MSG_ERROR, 00050 MSG_CRITICAL, 00051 MSG_ALERT, 00052 MSG_EMERGENCY, 00053 MSG_MESSAGEONLY 00054 }; 00055 00056 00057 #define NUM_LOG_LEVELS 10 00058 #define FBUFSIZE 4096 00059 00060 #ifdef DARWIN 00061 #include <Availability.h> 00062 #if __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_8 00063 #define CONST_DIRENT_T struct dirent 00064 #else 00065 #define CONST_DIRENT_T const struct dirent 00066 #endif // Mountain Lion or earlier 00067 #else //DARWIN 00068 #define CONST_DIRENT_T const struct dirent 00069 #endif //DARWIN 00070 00071 #define SG_SET_LOCALE_C setlocale(LC_ALL, "C") 00072 #define SG_RESET_LOCALE setlocale(LC_ALL, "") 00073 00074 // printf like funktions (with additional severity level) 00075 // for object derived from CSGObject 00076 #define SG_GCDEBUG(...) io->message(MSG_GCDEBUG, __FILE__, __LINE__, __VA_ARGS__) 00077 #define SG_DEBUG(...) io->message(MSG_DEBUG, __FILE__, __LINE__, __VA_ARGS__) 00078 #define SG_INFO(...) io->message(MSG_INFO, __FILE__, __LINE__, __VA_ARGS__) 00079 #define SG_WARNING(...) io->message(MSG_WARN, __FILE__, __LINE__, __VA_ARGS__) 00080 #define SG_ERROR(...) io->message(MSG_ERROR, __FILE__, __LINE__, __VA_ARGS__) 00081 #define SG_UNSTABLE(func, ...) io->message(MSG_WARN, __FILE__, __LINE__, \ 00082 __FILE__ ":" func ": Unstable method! Please report if it seems to " \ 00083 "work or not to the Shogun mailing list. Thanking you in " \ 00084 "anticipation. " __VA_ARGS__) 00085 00086 #define SG_PRINT(...) io->message(MSG_MESSAGEONLY, __FILE__, __LINE__, __VA_ARGS__) 00087 #define SG_NOTIMPLEMENTED io->not_implemented(__FILE__, __LINE__) 00088 #define SG_DEPRECATED io->deprecated(__FILE__, __LINE__) 00089 00090 #define SG_PROGRESS(...) io->progress(__VA_ARGS__) 00091 #define SG_ABS_PROGRESS(...) io->absolute_progress(__VA_ARGS__) 00092 #define SG_DONE() io->done() 00093 00094 // printf like function using the global sg_io object 00095 #define SG_SGCDEBUG(...) sg_io->message(MSG_GCDEBUG,__FILE__, __LINE__, __VA_ARGS__) 00096 #define SG_SDEBUG(...) sg_io->message(MSG_DEBUG,__FILE__, __LINE__, __VA_ARGS__) 00097 #define SG_SINFO(...) sg_io->message(MSG_INFO,__FILE__, __LINE__, __VA_ARGS__) 00098 #define SG_SWARNING(...) sg_io->message(MSG_WARN,__FILE__, __LINE__, __VA_ARGS__) 00099 #define SG_SERROR(...) sg_io->message(MSG_ERROR,__FILE__, __LINE__, __VA_ARGS__) 00100 #define SG_SPRINT(...) sg_io->message(MSG_MESSAGEONLY,__FILE__, __LINE__, __VA_ARGS__) 00101 #define SG_SPROGRESS(...) sg_io->progress(__VA_ARGS__) 00102 #define SG_SABS_PROGRESS(...) sg_io->absolute_progress(__VA_ARGS__) 00103 #define SG_SDONE() sg_io->done() 00104 #define SG_SNOTIMPLEMENTED sg_io->not_implemented(__FILE__, __LINE__) 00105 #define SG_SDEPRECATED sg_io->deprecated(__FILE__, __LINE__) 00106 00107 #define ASSERT(x) { if (!(x)) SG_SERROR("assertion %s failed in file %s line %d\n",#x, __FILE__, __LINE__);} 00108 #define REQUIRE(x, ...) { if (!(x)) SG_SERROR(__VA_ARGS__); } 00109 00110 00117 class SGIO 00118 { 00119 public: 00121 SGIO(); 00123 SGIO(const SGIO& orig); 00124 00129 void set_loglevel(EMessageType level); 00130 00135 EMessageType get_loglevel() const; 00136 00141 inline bool get_show_progress() const 00142 { 00143 return show_progress; 00144 } 00145 00150 inline bool get_show_file_and_line() const 00151 { 00152 return show_file_and_line; 00153 } 00154 00159 inline bool get_syntax_highlight() const 00160 { 00161 return syntax_highlight; 00162 } 00163 00174 void message(EMessageType prio, const char* file, 00175 int32_t line, const char *fmt, ... ) const; 00176 00185 void progress( 00186 float64_t current_val, 00187 float64_t min_val=0.0, float64_t max_val=1.0, int32_t decimals=1, 00188 const char* prefix="PROGRESS:\t"); 00189 00199 void absolute_progress( 00200 float64_t current_val, float64_t val, 00201 float64_t min_val=0.0, float64_t max_val=1.0, int32_t decimals=1, 00202 const char* prefix="PROGRESS:\t"); 00203 00208 void done(); 00209 00211 inline void not_implemented(const char* file, int32_t line) const 00212 { 00213 message(MSG_ERROR, file, line, "Sorry, not yet implemented .\n"); 00214 } 00215 00217 inline void deprecated(const char* file, int32_t line) const 00218 { 00219 message(MSG_WARN, file, line, 00220 "This function is deprecated and will be removed soon.\n"); 00221 } 00222 00228 void buffered_message(EMessageType prio, const char *fmt, ... ) const; 00229 00235 static char* skip_spaces(char* str); 00236 00242 static char* skip_blanks(char* str); 00243 00248 inline FILE* get_target() const 00249 { 00250 return target; 00251 } 00252 00257 void set_target(FILE* target); 00258 00260 inline void set_target_to_stderr() { set_target(stderr); } 00261 00263 inline void set_target_to_stdout() { set_target(stdout); } 00264 00266 inline void enable_progress() 00267 { 00268 show_progress=true; 00269 00270 // static functions like CSVM::classify_example_helper call SG_PROGRESS 00271 if (sg_io!=this) 00272 sg_io->enable_progress(); 00273 } 00274 00276 inline void disable_progress() 00277 { 00278 show_progress=false; 00279 00280 // static functions like CSVM::classify_example_helper call SG_PROGRESS 00281 if (sg_io!=this) 00282 sg_io->disable_progress(); 00283 } 00284 00286 inline void enable_file_and_line() 00287 { 00288 show_file_and_line=true; 00289 00290 if (sg_io!=this) 00291 sg_io->enable_file_and_line(); 00292 } 00293 00295 inline void disable_file_and_line() 00296 { 00297 show_file_and_line=false; 00298 00299 if (sg_io!=this) 00300 sg_io->disable_file_and_line(); 00301 } 00302 00304 inline void enable_syntax_highlighting() 00305 { 00306 syntax_highlight=true; 00307 00308 if (sg_io!=this) 00309 sg_io->enable_syntax_highlighting(); 00310 } 00311 00313 inline void disable_syntax_highlighting() 00314 { 00315 syntax_highlight=false; 00316 00317 if (sg_io!=this) 00318 sg_io->disable_syntax_highlighting(); 00319 } 00320 00325 static inline void set_dirname(const char* dirname) 00326 { 00327 strncpy(directory_name, dirname, FBUFSIZE); 00328 } 00329 00336 static inline char* concat_filename(const char* filename) 00337 { 00338 if (snprintf(file_buffer, FBUFSIZE, "%s/%s", directory_name, filename) > FBUFSIZE) 00339 SG_SERROR("filename too long"); 00340 SG_SDEBUG("filename=\"%s\"\n", file_buffer); 00341 return file_buffer; 00342 } 00343 00349 static inline int filter(CONST_DIRENT_T* d) 00350 { 00351 if (d) 00352 { 00353 char* fname=concat_filename(d->d_name); 00354 00355 if (!access(fname, R_OK)) 00356 { 00357 struct stat s; 00358 if (!stat(fname, &s) && S_ISREG(s.st_mode)) 00359 return 1; 00360 } 00361 } 00362 00363 return 0; 00364 } 00365 00370 inline int32_t ref() 00371 { 00372 ++refcount; 00373 return refcount; 00374 } 00375 00380 inline int32_t ref_count() const 00381 { 00382 return refcount; 00383 } 00384 00390 inline int32_t unref() 00391 { 00392 if (refcount==0 || --refcount==0) 00393 { 00394 delete this; 00395 return 0; 00396 } 00397 else 00398 return refcount; 00399 } 00400 00402 inline const char* get_name() { return "SGIO"; } 00403 00404 protected: 00411 const char* get_msg_intro(EMessageType prio) const; 00412 00413 protected: 00415 FILE* target; 00417 float64_t last_progress_time; 00419 float64_t progress_start_time; 00421 float64_t last_progress; 00423 bool show_progress; 00426 bool show_file_and_line; 00428 bool syntax_highlight; 00429 00431 EMessageType loglevel; 00433 static const EMessageType levels[NUM_LOG_LEVELS]; 00435 static const char* message_strings_highlighted[NUM_LOG_LEVELS]; 00437 static const char* message_strings[NUM_LOG_LEVELS]; 00438 00440 static char file_buffer[FBUFSIZE]; 00442 static char directory_name[FBUFSIZE]; 00443 00444 private: 00445 int32_t refcount; 00446 }; 00447 00455 struct substring 00456 { 00458 char *start; 00460 char *end; 00461 }; 00462 00463 00469 inline char* c_string_of_substring(substring s) 00470 { 00471 uint32_t len = s.end - s.start+1; 00472 char* ret = SG_CALLOC(char, len); 00473 memcpy(ret,s.start,len-1); 00474 return ret; 00475 } 00476 00481 inline void print_substring(substring s) 00482 { 00483 char* c_string = c_string_of_substring(s); 00484 SG_SPRINT("%s\n", c_string); 00485 SG_FREE(c_string); 00486 } 00487 00494 inline float32_t float_of_substring(substring s) 00495 { 00496 char* endptr = s.end; 00497 float32_t f = strtof(s.start,&endptr); 00498 if (endptr == s.start && s.start != s.end) 00499 SG_SERROR("error: %s is not a float!\n", c_string_of_substring(s)); 00500 00501 return f; 00502 } 00503 00509 inline float64_t double_of_substring(substring s) 00510 { 00511 char* endptr = s.end; 00512 float64_t f = strtod(s.start,&endptr); 00513 if (endptr == s.start && s.start != s.end) 00514 SG_SERROR("Error!:%s is not a double!\n", c_string_of_substring(s)); 00515 00516 return f; 00517 } 00518 00524 inline int32_t int_of_substring(substring s) 00525 { 00526 char* c_string = c_string_of_substring(s); 00527 int32_t int_val = atoi(c_string); 00528 SG_FREE(c_string); 00529 00530 return int_val; 00531 } 00532 00538 inline uint32_t ulong_of_substring(substring s) 00539 { 00540 return strtoul(s.start,NULL,10); 00541 } 00542 00548 inline uint32_t ss_length(substring s) 00549 { 00550 return (s.end - s.start); 00551 } 00552 00553 } 00554 #endif // __SGIO_H__