lib/base/log.h
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00027 #ifndef EQBASE_LOG_H
00028 #define EQBASE_LOG_H
00029
00030 #include <eq/base/base.h>
00031 #include <eq/base/clock.h>
00032
00033 #include <assert.h>
00034 #include <iomanip>
00035 #include <iostream>
00036 #include <sstream>
00037 #include <time.h>
00038
00039 #ifdef WIN32_API
00040 # include <process.h>
00041 # define getpid _getpid
00042 #endif
00043
00044 namespace eq
00045 {
00046 namespace base
00047 {
00049 enum LogLevel
00050 {
00051 LOG_ERROR = 1,
00052 LOG_WARN,
00053 LOG_INFO,
00054 LOG_VERB,
00055 LOG_ALL
00056 };
00057
00063 enum LogTopic
00064 {
00065 LOG_CUSTOM = 0x10,
00066 LOG_ANY = 0xffffu
00067 };
00068
00070 class LogBuffer : public std::streambuf
00071 {
00072 public:
00073 LogBuffer( std::ostream& stream )
00074 : _line(0), _indent(0), _blocked(0), _noHeader(0),
00075 _newLine(true), _stream(stream)
00076 {}
00077 virtual ~LogBuffer() {}
00078
00079 void indent() { ++_indent; }
00080 void exdent() { --_indent; }
00081
00082 void disableFlush() { ++_blocked; }
00083 void enableFlush()
00084 {
00085 assert( _blocked );
00086 --_blocked;
00087 if( !_blocked )
00088 pubsync();
00089 }
00090
00091 void disableHeader() { ++_noHeader; }
00092 void enableHeader() { --_noHeader; }
00093
00094 #ifdef WIN32
00095 void setLogInfo( const char* subdir, const char* file, const int line )
00096 { _file = file; _line = line; }
00097 #else
00098 void setLogInfo( const char* subdir, const char* file, const int line )
00099 { _file = std::string( subdir ) + '/' + file; _line = line; }
00100 #endif
00101
00102 protected:
00103 virtual int_type overflow( LogBuffer::int_type c );
00104
00105 virtual int sync()
00106 {
00107 if( !_blocked )
00108 {
00109 const std::string& string = _stringStream.str();
00110 _stream.write( string.c_str(), string.length( ));
00111 _stringStream.str( "" );
00112 }
00113 _newLine = true;
00114 return 0;
00115 }
00116
00117 private:
00118 LogBuffer( const LogBuffer& );
00119 LogBuffer& operator = ( const LogBuffer& );
00120
00122 std::string _file;
00123
00125 int _line;
00126
00128 int _indent;
00129
00131 int _blocked;
00132
00134 int _noHeader;
00135
00137 bool _newLine;
00138
00140 std::ostringstream _stringStream;
00141
00143 std::ostream& _stream;
00144 };
00145
00147 class Log : public std::ostream
00148 {
00149 public:
00150
00151 Log() : std::ostream( &_logBuffer ), _logBuffer( getOutput( )){}
00152 virtual ~Log() { _logBuffer.pubsync(); }
00153
00154 void indent() { _logBuffer.indent(); }
00155 void exdent() { _logBuffer.exdent(); }
00156 void disableFlush() { _logBuffer.disableFlush(); }
00157 void enableFlush() { _logBuffer.enableFlush(); }
00158 void forceFlush() { _logBuffer.pubsync(); }
00159 void disableHeader() { _logBuffer.disableHeader(); }
00160 void enableHeader() { _logBuffer.enableHeader(); }
00161
00163 static EQ_EXPORT int level;
00164
00166 static EQ_EXPORT unsigned topics;
00167
00169 static EQ_EXPORT Log& instance( const char* subdir, const char* file,
00170 const int line );
00171
00173 static EQ_EXPORT void exit();
00174
00176 static std::string& getLogLevelString();
00177
00179 static EQ_EXPORT void setOutput( std::ostream& stream );
00180
00182 static std::ostream& getOutput ();
00183
00192 static EQ_EXPORT void setClock( Clock* clock );
00193
00194 void notifyPerThreadDelete() { delete this; }
00195
00196 private:
00197 LogBuffer _logBuffer;
00198
00199 Log( const Log& );
00200 Log& operator = ( const Log& );
00201
00202 void setLogInfo( const char* subdir, const char* file, const int line )
00203 { _logBuffer.setLogInfo( subdir, file, line ); }
00204
00205 };
00206
00211 EQ_EXPORT std::ostream& indent( std::ostream& os );
00213 EQ_EXPORT std::ostream& exdent( std::ostream& os );
00214
00216 EQ_EXPORT std::ostream& disableFlush( std::ostream& os );
00218 EQ_EXPORT std::ostream& enableFlush( std::ostream& os );
00220 EQ_EXPORT std::ostream& forceFlush( std::ostream& os );
00221
00223 EQ_EXPORT std::ostream& disableHeader( std::ostream& os );
00225 EQ_EXPORT std::ostream& enableHeader( std::ostream& os );
00226
00227 #ifdef WIN32
00228
00229 inline std::string getErrorString( const DWORD error )
00230 {
00231 char text[512] = "";
00232 FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, 0, error, 0, text, 511, 0 );
00233 const size_t length = strlen( text );
00234 if( length>2 && text[length-2] == '\r' )
00235 text[length-2] = '\0';
00236 return std::string( text );
00237 }
00239 inline std::string getLastErrorString()
00240 {
00241 return getErrorString( GetLastError( ));
00242 }
00243 #endif
00244 }
00245 }
00246
00247 #ifndef SUBDIR
00248 # define SUBDIR ""
00249 #endif
00250
00252 #define EQERROR (eq::base::Log::level >= eq::base::LOG_ERROR) && \
00253 eq::base::Log::instance( SUBDIR, __FILE__, __LINE__ )
00254
00255 #define EQWARN (eq::base::Log::level >= eq::base::LOG_WARN) && \
00256 eq::base::Log::instance( SUBDIR, __FILE__, __LINE__ )
00257
00258 #define EQINFO (eq::base::Log::level >= eq::base::LOG_INFO) && \
00259 eq::base::Log::instance( SUBDIR, __FILE__, __LINE__ )
00260
00261 #define EQVERB (eq::base::Log::level >= eq::base::LOG_VERB) && \
00262 eq::base::Log::instance( SUBDIR, __FILE__, __LINE__ )
00263
00265 #define EQLOG(topic) (eq::base::Log::topics & (topic)) && \
00266 eq::base::Log::instance( SUBDIR, __FILE__, __LINE__ )
00267
00268 #endif //EQBASE_LOG_H