![]() |
|
|
Generated: 18 Jul 2008 |
00001 // $Header: /local/reps/Gaudi/GaudiKernel/src/Lib/Message.cpp,v 1.9 2008/02/20 19:16:23 hmd Exp $ 00002 #include <string> 00003 #include <iostream> 00004 #include <iomanip> 00005 #include <cstdlib> 00006 #include <cctype> 00007 #include "GaudiKernel/IMessageSvc.h" 00008 #include "GaudiKernel/Message.h" 00009 #include "GaudiKernel/Timing.h" 00010 00011 #include "GaudiKernel/time_r.h" 00012 00013 using namespace MSG; 00014 00015 // Formatting string characters. 00016 const char Message::FORMAT_PREFIX = '%'; 00017 const char Message::JUSTIFY_LEFT = 'L'; 00018 const char Message::JUSTIFY_RIGHT = 'R'; 00019 const char Message::MESSAGE = 'M'; 00020 const char Message::TYPE = 'T'; 00021 const char Message::TIME = 't'; 00022 const char Message::UTIME = 'u'; 00023 const char Message::SOURCE = 'S'; 00024 const char Message::FILL = 'F'; 00025 const char Message::WIDTH = 'W'; 00026 //const char* Message::DEFAULT_FORMAT = "% F%67W%L#############################################################################\n-----------------------------------------------------------------------------\nMessage follows...\nSource : %S\nType : %T\nMessage : %M\nEnd of message.\n-----------------------------------------------------------------------------\n"; 00027 const char* Message::DEFAULT_FORMAT = "% F%18W%S%7W%R%T %0W%M"; 00028 // Time format accepts anything that strftime does plus %f for milliseconds 00029 const char* Message::DEFAULT_TIME_FORMAT = "%Y-%m-%d %H:%M:%S,%f"; 00030 00031 namespace { 00032 00033 std::string formattedTime ( std::string fmt, bool universal = false ); 00034 00035 } 00036 00037 //############################################################################# 00038 // --------------------------------------------------------------------------- 00039 // Routine: Constructor. 00040 // Purpose: 00041 // --------------------------------------------------------------------------- 00042 // 00043 Message::Message() : 00044 m_message( "" ), m_source( "UNKNOWN" ), m_format( DEFAULT_FORMAT ), 00045 m_time_format(DEFAULT_TIME_FORMAT), m_type( MSG::NIL ), 00046 m_fill( ' ' ), m_width( 0 ), m_left( true ) 00047 { 00048 } 00049 00050 //############################################################################# 00051 // --------------------------------------------------------------------------- 00052 // Routine: Constructor. 00053 // Purpose: 00054 // --------------------------------------------------------------------------- 00055 // 00056 Message::Message ( const char* src, int type, const char* msg ) : 00057 m_message( msg ), m_source( src ), m_format( DEFAULT_FORMAT ), 00058 m_time_format(DEFAULT_TIME_FORMAT), m_type( type ), 00059 m_fill( ' ' ), m_width( 0 ), m_left( true ) 00060 { 00061 } 00062 00063 //############################################################################# 00064 // --------------------------------------------------------------------------- 00065 // Routine: Constructor. 00066 // Purpose: 00067 // --------------------------------------------------------------------------- 00068 // 00069 Message::Message ( const std::string& src, int type, const std::string& msg ) : 00070 m_message( msg ), m_source( src ), m_format( DEFAULT_FORMAT ), 00071 m_time_format(DEFAULT_TIME_FORMAT), m_type( type ), 00072 m_fill( ' ' ), m_width( 0 ), m_left( true ) 00073 { 00074 } 00075 00076 //############################################################################# 00077 // --------------------------------------------------------------------------- 00078 // Routine: getMessage 00079 // Purpose: Get the message string. 00080 // --------------------------------------------------------------------------- 00081 // 00082 const std::string& Message::getMessage() const 00083 { 00084 return m_message; 00085 } 00086 00087 //############################################################################# 00088 // --------------------------------------------------------------------------- 00089 // Routine: setMessage 00090 // Purpose: Set the message string. 00091 // --------------------------------------------------------------------------- 00092 // 00093 void Message::setMessage( const std::string& msg ) 00094 { 00095 m_message = msg; 00096 } 00097 00098 //############################################################################# 00099 // --------------------------------------------------------------------------- 00100 // Routine: getType 00101 // Purpose: Get the message type. 00102 // --------------------------------------------------------------------------- 00103 // 00104 int Message::getType() const 00105 { 00106 return m_type; 00107 } 00108 00109 //############################################################################# 00110 // --------------------------------------------------------------------------- 00111 // Routine: setType 00112 // Purpose: Set the message type. 00113 // --------------------------------------------------------------------------- 00114 // 00115 void Message::setType( int msg_type ) 00116 { 00117 m_type = msg_type; 00118 } 00119 00120 //############################################################################# 00121 // --------------------------------------------------------------------------- 00122 // Routine: getSource 00123 // Purpose: Get the message source. 00124 // --------------------------------------------------------------------------- 00125 // 00126 const std::string& Message::getSource() const 00127 { 00128 return m_source; 00129 } 00130 00131 //############################################################################# 00132 // --------------------------------------------------------------------------- 00133 // Routine: setSource 00134 // Purpose: Set the message source. 00135 // --------------------------------------------------------------------------- 00136 // 00137 void Message::setSource( const std::string& src ) 00138 { 00139 m_source = src; 00140 } 00141 00142 //############################################################################# 00143 // --------------------------------------------------------------------------- 00144 // Routine: operator << 00145 // Purpose:Insert the message into a stream. 00146 // --------------------------------------------------------------------------- 00147 // 00148 std::ostream& operator << ( std::ostream& stream, const Message& msg ) 00149 { 00150 msg.makeFormattedMsg( msg.m_format ); 00151 stream << msg.m_formatted_msg; 00152 return stream; 00153 } 00154 00155 //############################################################################# 00156 // --------------------------------------------------------------------------- 00157 // Routine: operator < 00158 // Purpose: comparison operator needed for maps 00159 // --------------------------------------------------------------------------- 00160 // 00161 bool Message::operator < ( const Message& b ) 00162 { 00163 return m_type < b.m_type || 00164 m_source < b.m_source || 00165 m_message < b.m_message; 00166 } 00167 00168 //############################################################################# 00169 // --------------------------------------------------------------------------- 00170 // Routine: operator == 00171 // Purpose: comparison op. 00172 // --------------------------------------------------------------------------- 00173 // 00174 bool operator == ( const Message& a, const Message& b ) 00175 { 00176 return a.m_source == b.m_source && 00177 a.m_type == b.m_type && 00178 a.m_message == b.m_message; 00179 } 00180 00181 //############################################################################# 00182 // --------------------------------------------------------------------------- 00183 // Routine: 00184 // Purpose: Get the format string. 00185 // --------------------------------------------------------------------------- 00186 // 00187 const std::string& Message::getFormat() const 00188 { 00189 return m_format; 00190 } 00191 00192 //############################################################################# 00193 // --------------------------------------------------------------------------- 00194 // Routine: 00195 // Purpose: Get the default format string. 00196 // --------------------------------------------------------------------------- 00197 // 00198 const std::string Message::getDefaultFormat() 00199 { 00200 return DEFAULT_FORMAT; 00201 } 00202 00203 00204 //############################################################################# 00205 // --------------------------------------------------------------------------- 00206 // Routine: 00207 // Purpose: Set the format string - 00208 // use isFormatted() to check for valid format. 00209 // --------------------------------------------------------------------------- 00210 // 00211 void Message::setFormat( const std::string& format ) const 00212 { 00213 if ( format.empty() ) 00214 m_format = DEFAULT_FORMAT; 00215 else 00216 m_format = format; 00217 } 00218 00219 //############################################################################# 00220 // --------------------------------------------------------------------------- 00221 // Routine: 00222 // Purpose: Get the time format string. 00223 // --------------------------------------------------------------------------- 00224 // 00225 const std::string& Message::getTimeFormat() const 00226 { 00227 return m_time_format; 00228 } 00229 00230 //############################################################################# 00231 // --------------------------------------------------------------------------- 00232 // Routine: 00233 // Purpose: Get the default time format string. 00234 // --------------------------------------------------------------------------- 00235 // 00236 const std::string Message::getDefaultTimeFormat() 00237 { 00238 return DEFAULT_TIME_FORMAT ; 00239 } 00240 00241 00242 //############################################################################# 00243 // --------------------------------------------------------------------------- 00244 // Routine: 00245 // Purpose: Set the time format string - 00246 // use isFormatted() to check for valid format. 00247 // --------------------------------------------------------------------------- 00248 // 00249 void Message::setTimeFormat( const std::string& timeFormat ) const 00250 { 00251 if ( timeFormat.empty() ) 00252 m_time_format = DEFAULT_TIME_FORMAT; 00253 else 00254 m_time_format = timeFormat; 00255 } 00256 00257 //############################################################################# 00258 // --------------------------------------------------------------------------- 00259 // Routine: makeFormattedMsg 00260 // Purpose: This formats the message according to the format string. 00261 // --------------------------------------------------------------------------- 00262 // 00263 void Message::makeFormattedMsg( const std::string& format ) const 00264 { 00265 m_formatted_msg = ""; 00266 std::string::const_iterator i = format.begin(); 00267 while( i != format.end() ) { 00268 00269 // Output format string until format statement found. 00270 while( i != format.end() && *i != FORMAT_PREFIX ) 00271 m_formatted_msg += *i++; 00272 00273 // Test for end of format string. 00274 if ( i == format.end() ) break; 00275 i++; 00276 00277 // Find type of formatting. 00278 std::string this_format = ""; 00279 while( i != format.end() && *i != FORMAT_PREFIX && 00280 *i != MESSAGE && *i != TYPE && *i != SOURCE && 00281 *i != FILL && *i != WIDTH && *i != TIME && *i != UTIME && 00282 *i != JUSTIFY_LEFT && *i != JUSTIFY_RIGHT ) { 00283 this_format += *i++; 00284 } 00285 00286 // Reached end of string with improper format. 00287 if ( i == format.end() ) { 00288 invalidFormat(); 00289 break; 00290 } 00291 00292 this_format += *i++; 00293 decodeFormat( this_format ); 00294 } 00295 } 00296 00297 //############################################################################# 00298 // --------------------------------------------------------------------------- 00299 // Routine: decodeFormat 00300 // Purpose: This the work horse that check for a valid format string. 00301 // --------------------------------------------------------------------------- 00302 // 00303 void Message::decodeFormat( const std::string& format ) const 00304 { 00305 if ( ! format.empty() ) { 00306 const char FORMAT_TYPE = format[ format.length() - 1 ]; 00307 const std::string FORMAT_PARAM = format.substr( 0, format.length() - 1 ); 00308 00309 // Now test the format. 00310 std::string level; 00311 switch( FORMAT_TYPE ) { 00312 case FILL: 00313 if ( FORMAT_PARAM.length() == 1 ) { 00314 m_fill = FORMAT_PARAM[0]; 00315 } 00316 else 00317 invalidFormat(); 00318 break; 00319 00320 case TIME: 00321 { 00322 const std::string& timeStr = formattedTime ( m_time_format ) ; 00323 sizeField( timeStr ); 00324 } 00325 break; 00326 00327 case UTIME: 00328 { 00329 const std::string& timeStr = formattedTime ( m_time_format, true ) ; 00330 sizeField( timeStr ); 00331 } 00332 break; 00333 00334 case MESSAGE: 00335 sizeField( m_message ); 00336 break; 00337 00338 case SOURCE: 00339 sizeField( m_source ); 00340 break; 00341 00342 case TYPE: 00343 switch ( m_type ) { 00344 using namespace MSG; 00345 #define SET(x) case x: level=#x; break 00346 SET( NIL ); 00347 SET( VERBOSE ); 00348 SET( DEBUG ); 00349 SET( INFO ); 00350 SET( WARNING ); 00351 SET( ERROR ); 00352 SET( FATAL ); 00353 case ALWAYS: level="SUCCESS"; break; 00354 default: 00355 level = "UNKNOWN"; 00356 break; 00357 #undef SET 00358 } 00359 sizeField( level ); 00360 break; 00361 00362 case FORMAT_PREFIX: m_formatted_msg += FORMAT_PREFIX; break; 00363 case JUSTIFY_RIGHT: m_left = false; break; 00364 case JUSTIFY_LEFT: m_left = true; break; 00365 case WIDTH: setWidth( FORMAT_PARAM ); break; 00366 default: invalidFormat(); break; 00367 } 00368 } 00369 else 00370 invalidFormat(); 00371 } 00372 00373 //############################################################################# 00374 // --------------------------------------------------------------------------- 00375 // Routine: invalidFormat. 00376 // Purpose: called when invalid format found. 00377 // --------------------------------------------------------------------------- 00378 // 00379 00380 void Message::invalidFormat() const 00381 { 00382 makeFormattedMsg( DEFAULT_FORMAT ); 00383 } 00384 00385 //############################################################################# 00386 // --------------------------------------------------------------------------- 00387 // Routine: setWidth 00388 // Purpose: Sets the minimum width of a stream field. 00389 // --------------------------------------------------------------------------- 00390 // 00391 00392 void Message::setWidth( const std::string& formatArg ) const 00393 { 00394 // Check that the parameters are only digits. 00395 bool only_digits = true; 00396 for( std::string::const_iterator i = formatArg.begin(); 00397 i != formatArg.end(); i++ ) { 00398 00399 if ( ! isdigit( *i ) ) { 00400 only_digits = false; 00401 invalidFormat(); 00402 break; 00403 } 00404 } 00405 00406 // Convert string to int. 00407 if ( only_digits ) { 00408 #ifdef __GNUG__ 00409 m_width = atoi( formatArg.c_str() ); 00410 #else 00411 m_width = atoi( formatArg.data() ); 00412 #endif 00413 } 00414 } 00415 00416 //############################################################################# 00417 // --------------------------------------------------------------------------- 00418 // Routine: sizeField 00419 // Purpose: Truncates or pads the text to m_width as necessary 00420 // --------------------------------------------------------------------------- 00421 // 00422 00423 void Message::sizeField( const std::string& text ) const 00424 { 00425 std::string newText; 00426 if ( m_width == 0 || m_width == static_cast<int>( text.length() ) ) { 00427 newText = text; 00428 } 00429 else { 00430 00431 // Truncate the text if it is too long. 00432 if ( m_width < static_cast<int>( text.length() ) ) { 00433 newText = text.substr( 0, m_width ); 00434 for ( int i = 0, j = newText.length()-1; i < 3 && j >= 0; i++, j-- ) 00435 newText[ j ] = '.'; 00436 } 00437 00438 // Pad the text. 00439 else { 00440 newText = std::string( m_width, m_fill ); 00441 if ( m_left ) 00442 newText.replace( newText.begin(), newText.begin() + text.length(), 00443 text.begin(), text.end() ); 00444 else 00445 newText.replace( newText.end() - text.length(), newText.end(), 00446 text.begin(), text.end() ); 00447 } 00448 } 00449 00450 m_formatted_msg += newText; 00451 } 00452 00453 namespace { 00454 00455 // get the current time from the system and format it according to the format 00456 std::string formattedTime ( std::string fmt, bool universal ) 00457 { 00458 // get current time in milliseconds 00459 longlong t = System::currentTime( System::milliSec ); 00460 int msec = static_cast<int>(t % 1000); 00461 time_t sec = static_cast<time_t>(t / 1000); 00462 00463 // convert to break-down time 00464 struct tm tms ; 00465 if (universal) { 00466 gmtime_r( &sec, &tms ); 00467 } else { 00468 localtime_r( &sec, &tms ); 00469 } 00470 00471 // replace %f in the format string with miliseconds 00472 std::string::size_type n = fmt.find("%f") ; 00473 if ( n != std::string::npos ) { 00474 char subs[4] ; 00475 sprintf ( subs, "%03d", msec ) ; 00476 while ( n != std::string::npos ) { 00477 fmt.replace ( n, 2, subs ) ; 00478 n = fmt.find("%f") ; 00479 } 00480 } 00481 00482 char buf[128] ; 00483 strftime(buf, 128, fmt.c_str(), &tms ); 00484 return std::string( buf ); 00485 } 00486 00487 } 00488