SHOGUN
v3.2.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-2013 Soeren Sonnenburg 00008 * Written (W) 1999-2008 Gunnar Raetsch 00009 * Copyright (C) 1999-2009 Fraunhofer Institute FIRST and Max-Planck-Society 00010 * Copyright (C) 2010-2013 Soeren Sonnenburg 00011 */ 00012 00013 #ifndef __SGIO_H__ 00014 #define __SGIO_H__ 00015 00016 #include <stdio.h> 00017 #include <stdarg.h> 00018 #include <string.h> 00019 #include <dirent.h> 00020 #ifndef _WIN32 00021 #include <unistd.h> 00022 #endif 00023 #include <locale.h> 00024 00025 #include <sys/types.h> 00026 #include <sys/stat.h> 00027 00028 #include <shogun/lib/common.h> 00029 #include <shogun/base/init.h> 00030 00031 namespace shogun 00032 { 00033 class RefCount; 00034 class SGIO; 00036 extern SGIO* sg_io; 00037 } 00038 00039 00040 namespace shogun 00041 { 00046 enum EMessageType 00047 { 00048 MSG_GCDEBUG=0, 00049 MSG_DEBUG=1, 00050 MSG_INFO=2, 00051 MSG_NOTICE=3, 00052 MSG_WARN=4, 00053 MSG_ERROR=5, 00054 MSG_CRITICAL=6, 00055 MSG_ALERT=7, 00056 MSG_EMERGENCY=8, 00057 MSG_MESSAGEONLY=9 00058 }; 00059 00063 enum EMessageLocation 00064 { 00065 MSG_NONE=0, 00066 MSG_FUNCTION=1, 00067 MSG_LINE_AND_FILE=2 00068 }; 00069 00070 #define NUM_LOG_LEVELS 10 00071 #define FBUFSIZE 4096 00072 00073 #ifdef DARWIN 00074 #include <Availability.h> 00075 #ifndef __MAC_10_8 00076 #define __MAC_10_8 1080 00077 #endif 00078 #if __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_8 00079 #define CONST_DIRENT_T struct dirent 00080 #else 00081 #define CONST_DIRENT_T const struct dirent 00082 #endif // Lion or earlier 00083 #else //DARWIN 00084 #define CONST_DIRENT_T const struct dirent 00085 #endif //DARWIN 00086 00087 #define SG_SET_LOCALE_C setlocale(LC_ALL, "C") 00088 #define SG_RESET_LOCALE setlocale(LC_ALL, "") 00089 00090 #if !defined(SG_UNLIKELY) 00091 #if __GNUC__ >= 3 00092 #define SG_UNLIKELY(expr) __builtin_expect(expr, 0) 00093 #else 00094 #define SG_UNLIKELY(expr) expr 00095 #endif 00096 #endif 00097 00098 #ifdef _WIN32 00099 #define __PRETTY_FUNCTION__ __FUNCTION__ 00100 #endif 00101 00102 // printf like funktions (with additional severity level) 00103 // for object derived from CSGObject 00104 #define SG_GCDEBUG(...) { \ 00105 if (SG_UNLIKELY(io->loglevel_above(MSG_GCDEBUG))) \ 00106 io->message(MSG_GCDEBUG, __PRETTY_FUNCTION__, __FILE__, __LINE__, __VA_ARGS__); \ 00107 } 00108 00109 #define SG_DEBUG(...) { \ 00110 if (SG_UNLIKELY(io->loglevel_above(MSG_DEBUG))) \ 00111 io->message(MSG_DEBUG, __PRETTY_FUNCTION__, __FILE__, __LINE__, __VA_ARGS__); \ 00112 } 00113 00114 #define SG_OBJ_DEBUG(o,...) { \ 00115 if (SG_UNLIKELY(o->io->loglevel_above(MSG_DEBUG))) \ 00116 o->io->message(MSG_DEBUG, __PRETTY_FUNCTION__, __FILE__, __LINE__, __VA_ARGS__); \ 00117 } 00118 00119 00120 #define SG_INFO(...) { \ 00121 if (SG_UNLIKELY(io->loglevel_above(MSG_INFO))) \ 00122 io->message(MSG_INFO, __PRETTY_FUNCTION__, __FILE__, __LINE__, __VA_ARGS__); \ 00123 } 00124 00125 #define SG_CLASS_INFO(c, ...) { \ 00126 if (SG_UNLIKELY(c::io->loglevel_above(MSG_INFO))) \ 00127 c::io->message(MSG_INFO, __PRETTY_FUNCTION__, __FILE__, __LINE__, __VA_ARGS__); \ 00128 } 00129 00130 #define SG_WARNING(...) { io->message(MSG_WARN, __PRETTY_FUNCTION__, __FILE__, __LINE__, __VA_ARGS__); } 00131 #define SG_ERROR(...) { io->message(MSG_ERROR, __PRETTY_FUNCTION__, __FILE__, __LINE__, __VA_ARGS__); } 00132 #define SG_OBJ_ERROR(o, ...) { o->io->message(MSG_ERROR, __PRETTY_FUNCTION__, __FILE__, __LINE__, __VA_ARGS__); } 00133 #define SG_CLASS_ERROR(c, ...) { c::io->message(MSG_ERROR, __PRETTY_FUNCTION__, __FILE__, __LINE__, __VA_ARGS__); } 00134 #define SG_UNSTABLE(func, ...) { io->message(MSG_WARN, __PRETTY_FUNCTION__, __FILE__, __LINE__, \ 00135 __FILE__ ":" func ": Unstable method! Please report if it seems to " \ 00136 "work or not to the Shogun mailing list. Thanking you in " \ 00137 "anticipation. " __VA_ARGS__); } 00138 00139 #define SG_PRINT(...) { io->message(MSG_MESSAGEONLY, __PRETTY_FUNCTION__, __FILE__, __LINE__, __VA_ARGS__); } 00140 #define SG_OBJ_PRINT(o, ...) { o->io->message(MSG_MESSAGEONLY, __PRETTY_FUNCTION__, __FILE__, __LINE__, __VA_ARGS__); } 00141 #define SG_NOTIMPLEMENTED { io->not_implemented(__PRETTY_FUNCTION__, __FILE__, __LINE__); } 00142 #define SG_DEPRECATED { io->deprecated(__PRETTY_FUNCTION__, __FILE__, __LINE__); } 00143 00144 #define SG_PROGRESS(...) { \ 00145 if (SG_UNLIKELY(io->get_show_progress())) \ 00146 io->progress(__VA_ARGS__); \ 00147 } 00148 00149 #define SG_OBJ_PROGRESS(o, ...) { \ 00150 if (SG_UNLIKELY(o->io->get_show_progress()))\ 00151 o->io->progress(__VA_ARGS__); \ 00152 } 00153 00154 #define SG_ABS_PROGRESS(...) { \ 00155 if (SG_UNLIKELY(io->get_show_progress())) \ 00156 io->absolute_progress(__VA_ARGS__); \ 00157 } 00158 00159 #define SG_DONE() { \ 00160 if (SG_UNLIKELY(io->get_show_progress())) \ 00161 io->done(); \ 00162 } 00163 00164 // printf like function using the global sg_io object 00165 #define SG_SGCDEBUG(...) { \ 00166 if (SG_UNLIKELY(sg_io->loglevel_above(MSG_GCDEBUG))) \ 00167 sg_io->message(MSG_GCDEBUG,__PRETTY_FUNCTION__, __FILE__, __LINE__, __VA_ARGS__);\ 00168 } 00169 00170 #define SG_SDEBUG(...) { \ 00171 if (SG_UNLIKELY(sg_io->loglevel_above(MSG_DEBUG))) \ 00172 sg_io->message(MSG_DEBUG,__PRETTY_FUNCTION__, __FILE__, __LINE__, __VA_ARGS__); \ 00173 } 00174 00175 #define SG_SINFO(...) { \ 00176 if (SG_UNLIKELY(sg_io->loglevel_above(MSG_INFO))) \ 00177 sg_io->message(MSG_INFO,__PRETTY_FUNCTION__, __FILE__, __LINE__, __VA_ARGS__); \ 00178 } 00179 00180 #define SG_SWARNING(...) { sg_io->message(MSG_WARN,__PRETTY_FUNCTION__, __FILE__, __LINE__, __VA_ARGS__); } 00181 #define SG_SERROR(...) { sg_io->message(MSG_ERROR,__PRETTY_FUNCTION__, __FILE__, __LINE__, __VA_ARGS__); } 00182 #define SG_SPRINT(...) { sg_io->message(MSG_MESSAGEONLY,__PRETTY_FUNCTION__, __FILE__, __LINE__, __VA_ARGS__); } 00183 00184 00185 #define SG_SPROGRESS(...) { \ 00186 if (SG_UNLIKELY(sg_io->get_show_progress())) \ 00187 sg_io->progress(__VA_ARGS__); \ 00188 } 00189 00190 #define SG_SABS_PROGRESS(...) { \ 00191 if (SG_UNLIKELY(sg_io->get_show_progress())) \ 00192 sg_io->absolute_progress(__VA_ARGS__); \ 00193 } 00194 00195 #define SG_SDONE() { \ 00196 if (SG_UNLIKELY(sg_io->get_show_progress())) \ 00197 sg_io->done(); \ 00198 } 00199 00200 #define SG_SNOTIMPLEMENTED { sg_io->not_implemented(__PRETTY_FUNCTION__, __FILE__, __LINE__); } 00201 #define SG_SDEPRECATED { sg_io->deprecated(__PRETTY_FUNCTION__, __FILE__, __LINE__); } 00202 00203 #define ASSERT(x) { \ 00204 if (SG_UNLIKELY(!(x))) \ 00205 SG_SERROR("assertion %s failed in %s file %s line %d\n",#x, __PRETTY_FUNCTION__, __FILE__, __LINE__) \ 00206 } 00207 00208 #define REQUIRE(x, ...) { \ 00209 if (SG_UNLIKELY(!(x))) \ 00210 SG_SERROR(__VA_ARGS__) \ 00211 } 00212 00213 /* help clang static analyzer to identify custom assertation functions */ 00214 #ifdef __clang_analyzer__ 00215 void _clang_fail(void) __attribute__((analyzer_noreturn)); 00216 00217 #undef SG_ERROR(...) 00218 #undef SG_SERROR(...) 00219 #define SG_ERROR(...) _clang_fail(); 00220 #define SG_SERROR(...) _clang_fail(); 00221 00222 #endif /* __clang_analyzer__ */ 00223 00231 struct substring 00232 { 00234 char *start; 00236 char *end; 00237 }; 00238 00245 class SGIO 00246 { 00247 public: 00249 SGIO(); 00251 SGIO(const SGIO& orig); 00252 00254 virtual ~SGIO(); 00255 00260 void set_loglevel(EMessageType level); 00261 00266 EMessageType get_loglevel() const; 00267 00273 inline bool loglevel_above(EMessageType type) const 00274 { 00275 return loglevel <= type; 00276 } 00277 00282 inline bool get_show_progress() const 00283 { 00284 return show_progress; 00285 } 00286 00289 inline EMessageLocation get_location_info() const 00290 { 00291 return location_info; 00292 } 00293 00298 inline bool get_syntax_highlight() const 00299 { 00300 return syntax_highlight; 00301 } 00302 00314 void message(EMessageType prio, const char* function, const char* file, 00315 int32_t line, const char *fmt, ... ) const; 00316 00325 void progress( 00326 float64_t current_val, 00327 float64_t min_val=0.0, float64_t max_val=1.0, int32_t decimals=1, 00328 const char* prefix="PROGRESS:\t"); 00329 00339 void absolute_progress( 00340 float64_t current_val, float64_t val, 00341 float64_t min_val=0.0, float64_t max_val=1.0, int32_t decimals=1, 00342 const char* prefix="PROGRESS:\t"); 00343 00348 void done(); 00349 00351 inline void not_implemented(const char* function, const char* file, int32_t line) const 00352 { 00353 message(MSG_ERROR, function, file, line, "Sorry, not yet implemented .\n"); 00354 } 00355 00357 inline void deprecated(const char* function, const char* file, int32_t line) const 00358 { 00359 message(MSG_WARN, function, file, line, 00360 "This function is deprecated and will be removed soon.\n"); 00361 } 00362 00368 void buffered_message(EMessageType prio, const char *fmt, ... ) const; 00369 00375 static char* skip_spaces(char* str); 00376 00382 static char* skip_blanks(char* str); 00383 00388 inline FILE* get_target() const 00389 { 00390 return target; 00391 } 00392 00397 void set_target(FILE* target); 00398 00400 inline void set_target_to_stderr() { set_target(stderr); } 00401 00403 inline void set_target_to_stdout() { set_target(stdout); } 00404 00406 inline void enable_progress() 00407 { 00408 show_progress=true; 00409 00410 // static functions like CSVM::classify_example_helper call SG_PROGRESS 00411 if (sg_io!=this) 00412 sg_io->enable_progress(); 00413 } 00414 00416 inline void disable_progress() 00417 { 00418 show_progress=false; 00419 00420 // static functions like CSVM::classify_example_helper call SG_PROGRESS 00421 if (sg_io!=this) 00422 sg_io->disable_progress(); 00423 } 00424 00430 inline void set_location_info(EMessageLocation location) 00431 { 00432 location_info = location; 00433 00434 if (sg_io!=this) 00435 sg_io->set_location_info(location); 00436 } 00437 00439 inline void enable_syntax_highlighting() 00440 { 00441 syntax_highlight=true; 00442 00443 if (sg_io!=this) 00444 sg_io->enable_syntax_highlighting(); 00445 } 00446 00448 inline void disable_syntax_highlighting() 00449 { 00450 syntax_highlight=false; 00451 00452 if (sg_io!=this) 00453 sg_io->disable_syntax_highlighting(); 00454 } 00455 00460 static inline void set_dirname(const char* dirname) 00461 { 00462 strncpy(directory_name, dirname, FBUFSIZE); 00463 } 00464 00471 static char* concat_filename(const char* filename); 00472 00478 static int filter(CONST_DIRENT_T* d); 00479 00485 static char* c_string_of_substring(substring s); 00486 00491 static void print_substring(substring s); 00492 00499 static float32_t float_of_substring(substring s); 00500 00506 static float64_t double_of_substring(substring s); 00507 00513 static int32_t int_of_substring(substring s); 00514 00520 static uint32_t ulong_of_substring(substring s); 00521 00527 static uint32_t ss_length(substring s); 00528 00533 int32_t ref(); 00534 00539 int32_t ref_count() const; 00540 00546 int32_t unref(); 00547 00549 inline const char* get_name() { return "SGIO"; } 00550 00551 protected: 00558 const char* get_msg_intro(EMessageType prio) const; 00559 00560 protected: 00562 FILE* target; 00564 float64_t last_progress_time; 00566 float64_t progress_start_time; 00568 float64_t last_progress; 00570 bool show_progress; 00573 EMessageLocation location_info; 00575 bool syntax_highlight; 00576 00578 EMessageType loglevel; 00580 static const EMessageType levels[NUM_LOG_LEVELS]; 00582 static const char* message_strings_highlighted[NUM_LOG_LEVELS]; 00584 static const char* message_strings[NUM_LOG_LEVELS]; 00585 00587 static char file_buffer[FBUFSIZE]; 00589 static char directory_name[FBUFSIZE]; 00590 00591 private: 00592 RefCount* m_refcount; 00593 }; 00594 } 00595 #endif // __SGIO_H__