00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef _LOGSTREAM_H
00026 #define _LOGSTREAM_H
00027
00028 #include <simgear/compiler.h>
00029
00030 #ifdef _WIN32
00031 # include <windows.h>
00032 #endif
00033
00034 #include <streambuf>
00035 #include <ostream>
00036 #include <cstdio>
00037
00038 #include <simgear/debug/debug_types.h>
00039
00040 using std::streambuf;
00041 using std::ostream;
00042
00043
00044
00045
00046
00047
00048
00049
00050
00056 #ifdef SG_NEED_STREAMBUF_HACK
00057 class logbuf : public __streambuf
00058 #else
00059 class logbuf : public std::streambuf
00060 #endif
00061 {
00062 public:
00063
00065 logbuf();
00066
00068 ~logbuf();
00069
00073 bool enabled() { return logging_enabled; }
00074
00080 void set_log_state( sgDebugClass c, sgDebugPriority p );
00081
00082 bool would_log( sgDebugClass c, sgDebugPriority p ) const;
00083
00089 static void set_log_level( sgDebugClass c, sgDebugPriority p );
00090
00091
00096 static void set_log_classes (sgDebugClass c);
00097
00098
00103 static sgDebugClass get_log_classes ();
00104
00105
00110 static void set_log_priority (sgDebugPriority p);
00111
00112
00117 static sgDebugPriority get_log_priority ();
00118
00119
00124 void set_sb( std::streambuf* sb );
00125
00126 #ifdef _WIN32
00127 static void has_no_console() { has_console = false; }
00128 #endif
00129
00130 protected:
00131
00133 inline virtual int sync();
00134
00136 int_type overflow( int ch );
00137
00138
00139 private:
00140
00141
00142 static std::streambuf* sbuf;
00143
00144 static bool logging_enabled;
00145 #ifdef _WIN32
00146 static bool has_console;
00147 #endif
00148 static sgDebugClass logClass;
00149 static sgDebugPriority logPriority;
00150
00151 private:
00152
00153
00154 logbuf( const logbuf& );
00155 void operator= ( const logbuf& );
00156 };
00157
00158 inline int
00159 logbuf::sync()
00160 {
00161 return sbuf->pubsync();
00162 }
00163
00164 inline void
00165 logbuf::set_log_state( sgDebugClass c, sgDebugPriority p )
00166 {
00167 logging_enabled = ((c & logClass) != 0 && p >= logPriority);
00168 }
00169
00170 inline bool
00171 logbuf::would_log( sgDebugClass c, sgDebugPriority p ) const
00172 {
00173 return ((c & logClass) != 0 && p >= logPriority);
00174 }
00175
00176 inline logbuf::int_type
00177 logbuf::overflow( int c )
00178 {
00179 #ifdef _WIN32
00180 if ( logging_enabled ) {
00181 if ( !has_console ) {
00182 AllocConsole();
00183 freopen("conin$", "r", stdin);
00184 freopen("conout$", "w", stdout);
00185 freopen("conout$", "w", stderr);
00186 has_console = true;
00187 }
00188 return sbuf->sputc(c);
00189 }
00190 else
00191 return EOF == 0 ? 1: 0;
00192 #else
00193 return logging_enabled ? sbuf->sputc(c) : (EOF == 0 ? 1: 0);
00194 #endif
00195 }
00196
00200 struct loglevel
00201 {
00202 loglevel( sgDebugClass c, sgDebugPriority p )
00203 : logClass(c), logPriority(p) {}
00204
00205 sgDebugClass logClass;
00206 sgDebugPriority logPriority;
00207 };
00208
00216 struct logstream_base
00217 {
00218
00219 logstream_base() {}
00220
00221 logbuf lbuf;
00222 };
00223
00227 class logstream : private logstream_base, public std::ostream
00228 {
00229 public:
00234 logstream( std::ostream& out )
00235
00236 : logstream_base(),
00237 std::ostream(&lbuf) { lbuf.set_sb(out.rdbuf());}
00238
00243 void set_output( std::ostream& out ) { lbuf.set_sb( out.rdbuf() ); }
00244
00250 void setLogLevels( sgDebugClass c, sgDebugPriority p );
00251
00252 bool would_log( sgDebugClass c, sgDebugPriority p ) const
00253 {
00254 return lbuf.would_log( c, p );
00255 };
00256
00261 inline std::ostream& operator<< ( const loglevel& l );
00262 friend logstream& sglog();
00263 static logstream *initGlobalLogstream();
00264 protected:
00265 static logstream *global_logstream;
00266 };
00267
00268 inline std::ostream&
00269 logstream::operator<< ( const loglevel& l )
00270 {
00271 lbuf.set_log_state( l.logClass, l.logPriority );
00272 return *this;
00273 }
00274
00282 inline logstream&
00283 sglog()
00284 {
00285 return *logstream::initGlobalLogstream();
00286 }
00287
00288
00295 #ifdef FG_NDEBUG
00296 # define SG_LOG(C,P,M)
00297 #else
00298 # define SG_LOG(C,P,M) do { \
00299 logstream& __tmplogstreamref(sglog()); \
00300 if(__tmplogstreamref.would_log(C,P)) { \
00301 __tmplogstreamref << loglevel(C,P) << M << std::endl; } \
00302 } while(0)
00303 #endif
00304
00305 #define SG_ORIGIN __FILE__ ":" SG_STRINGIZE(__LINE__)
00306
00307 #endif // _LOGSTREAM_H
00308