00001
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
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
00027 const char* Message::DEFAULT_FORMAT = "% F%18W%S%7W%R%T %0W%M";
00028
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
00040
00041
00042
00043 Message::Message() :
00044 m_message( "" ), m_source( "UNKNOWN" ), m_format( DEFAULT_FORMAT ),
00045 m_time_format(DEFAULT_TIME_FORMAT), m_type( NIL ),
00046 m_fill( ' ' ), m_width( 0 ), m_left( true )
00047 {
00048 }
00049
00050
00051
00052
00053
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
00066
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
00079
00080
00081
00082 const std::string& Message::getMessage() const
00083 {
00084 return m_message;
00085 }
00086
00087
00088
00089
00090
00091
00092
00093 void Message::setMessage( const std::string& msg )
00094 {
00095 m_message = msg;
00096 }
00097
00098
00099
00100
00101
00102
00103
00104 int Message::getType() const
00105 {
00106 return m_type;
00107 }
00108
00109
00110
00111
00112
00113
00114
00115 void Message::setType( int msg_type )
00116 {
00117 m_type = msg_type;
00118 }
00119
00120
00121
00122
00123
00124
00125
00126 const std::string& Message::getSource() const
00127 {
00128 return m_source;
00129 }
00130
00131
00132
00133
00134
00135
00136
00137 void Message::setSource( const std::string& src )
00138 {
00139 m_source = src;
00140 }
00141
00142
00143
00144
00145
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
00158
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
00171
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
00184
00185
00186
00187 const std::string& Message::getFormat() const
00188 {
00189 return m_format;
00190 }
00191
00192
00193
00194
00195
00196
00197
00198 const std::string Message::getDefaultFormat()
00199 {
00200 return DEFAULT_FORMAT;
00201 }
00202
00203
00204
00205
00206
00207
00208
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
00222
00223
00224
00225 const std::string& Message::getTimeFormat() const
00226 {
00227 return m_time_format;
00228 }
00229
00230
00231
00232
00233
00234
00235
00236 const std::string Message::getDefaultTimeFormat()
00237 {
00238 return DEFAULT_TIME_FORMAT ;
00239 }
00240
00241
00242
00243
00244
00245
00246
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
00260
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
00270 while( i != format.end() && *i != FORMAT_PREFIX )
00271 m_formatted_msg += *i++;
00272
00273
00274 if ( i == format.end() ) break;
00275 i++;
00276
00277
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
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
00300
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
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 #define SET(x) case x: level=#x; break
00345 SET( NIL );
00346 SET( VERBOSE );
00347 SET( DEBUG );
00348 SET( INFO );
00349 SET( WARNING );
00350 SET( ERROR );
00351 SET( FATAL );
00352 case ALWAYS: level="SUCCESS"; break;
00353 default:
00354 level = "UNKNOWN";
00355 break;
00356 #undef SET
00357 }
00358 sizeField( level );
00359 break;
00360
00361 case FORMAT_PREFIX: m_formatted_msg += FORMAT_PREFIX; break;
00362 case JUSTIFY_RIGHT: m_left = false; break;
00363 case JUSTIFY_LEFT: m_left = true; break;
00364 case WIDTH: setWidth( FORMAT_PARAM ); break;
00365 default: invalidFormat(); break;
00366 }
00367 }
00368 else
00369 invalidFormat();
00370 }
00371
00372
00373
00374
00375
00376
00377
00378
00379 void Message::invalidFormat() const
00380 {
00381 makeFormattedMsg( DEFAULT_FORMAT );
00382 }
00383
00384
00385
00386
00387
00388
00389
00390
00391 void Message::setWidth( const std::string& formatArg ) const
00392 {
00393
00394 bool only_digits = true;
00395 for( std::string::const_iterator i = formatArg.begin();
00396 i != formatArg.end(); i++ ) {
00397
00398 if ( ! isdigit( *i ) ) {
00399 only_digits = false;
00400 invalidFormat();
00401 break;
00402 }
00403 }
00404
00405
00406 if ( only_digits ) {
00407 #ifdef __GNUG__
00408 m_width = atoi( formatArg.c_str() );
00409 #else
00410 m_width = atoi( formatArg.data() );
00411 #endif
00412 }
00413 }
00414
00415
00416
00417
00418
00419
00420
00421
00422 void Message::sizeField( const std::string& text ) const
00423 {
00424 std::string newText;
00425 if ( m_width == 0 || m_width == static_cast<int>( text.length() ) ) {
00426 newText = text;
00427 }
00428 else {
00429
00430
00431 if ( m_width < static_cast<int>( text.length() ) ) {
00432 newText = text.substr( 0, m_width );
00433 for ( int i = 0, j = newText.length()-1; i < 3 && j >= 0; i++, j-- )
00434 newText[ j ] = '.';
00435 }
00436
00437
00438 else {
00439 newText = std::string( m_width, m_fill );
00440 if ( m_left )
00441 newText.replace( newText.begin(), newText.begin() + text.length(),
00442 text.begin(), text.end() );
00443 else
00444 newText.replace( newText.end() - text.length(), newText.end(),
00445 text.begin(), text.end() );
00446 }
00447 }
00448
00449 m_formatted_msg += newText;
00450 }
00451
00452 namespace {
00453
00454
00455 std::string formattedTime ( std::string fmt, bool universal )
00456 {
00457
00458 longlong t = System::currentTime( System::milliSec );
00459 int msec = static_cast<int>(t % 1000);
00460 time_t sec = static_cast<time_t>(t / 1000);
00461
00462
00463 struct tm tms ;
00464 if (universal) {
00465 gmtime_r( &sec, &tms );
00466 } else {
00467 localtime_r( &sec, &tms );
00468 }
00469
00470
00471 std::string::size_type n = fmt.find("%f") ;
00472 if ( n != std::string::npos ) {
00473 char subs[4] ;
00474 sprintf ( subs, "%03d", msec ) ;
00475 while ( n != std::string::npos ) {
00476 fmt.replace ( n, 2, subs ) ;
00477 n = fmt.find("%f") ;
00478 }
00479 }
00480
00481 char buf[128] ;
00482 strftime(buf, 128, fmt.c_str(), &tms );
00483 return std::string( buf );
00484 }
00485
00486 }
00487