00001
00002 #include <string>
00003 #include <iostream>
00004 #include <iomanip>
00005 #include <cstdlib>
00006 #include <cstdio>
00007 #include <cctype>
00008 #include "GaudiKernel/IMessageSvc.h"
00009 #include "GaudiKernel/Message.h"
00010 #include "GaudiKernel/Timing.h"
00011
00012 #include "GaudiKernel/time_r.h"
00013
00014 using namespace MSG;
00015
00016
00017 const char Message::FORMAT_PREFIX = '%';
00018 const char Message::JUSTIFY_LEFT = 'L';
00019 const char Message::JUSTIFY_RIGHT = 'R';
00020 const char Message::MESSAGE = 'M';
00021 const char Message::TYPE = 'T';
00022 const char Message::TIME = 't';
00023 const char Message::UTIME = 'u';
00024 const char Message::SOURCE = 'S';
00025 const char Message::FILL = 'F';
00026 const char Message::WIDTH = 'W';
00027
00028 const char* Message::DEFAULT_FORMAT = "% F%18W%S%7W%R%T %0W%M";
00029
00030 const char* Message::DEFAULT_TIME_FORMAT = "%Y-%m-%d %H:%M:%S,%f";
00031
00032 namespace {
00033
00034 std::string formattedTime ( std::string fmt, bool universal = false );
00035
00036 }
00037
00038
00039
00040
00041
00042
00043
00044 Message::Message() :
00045 m_message( "" ), m_source( "UNKNOWN" ), m_format( DEFAULT_FORMAT ),
00046 m_time_format(DEFAULT_TIME_FORMAT), m_type( NIL ),
00047 m_fill( ' ' ), m_width( 0 ), m_left( true )
00048 {
00049 }
00050
00051
00052
00053
00054
00055
00056
00057 Message::Message ( const char* src, int type, const char* msg ) :
00058 m_message( msg ), m_source( src ), m_format( DEFAULT_FORMAT ),
00059 m_time_format(DEFAULT_TIME_FORMAT), m_type( type ),
00060 m_fill( ' ' ), m_width( 0 ), m_left( true )
00061 {
00062 }
00063
00064
00065
00066
00067
00068
00069
00070 Message::Message ( const std::string& src, int type, const std::string& msg ) :
00071 m_message( msg ), m_source( src ), m_format( DEFAULT_FORMAT ),
00072 m_time_format(DEFAULT_TIME_FORMAT), m_type( type ),
00073 m_fill( ' ' ), m_width( 0 ), m_left( true )
00074 {
00075 }
00076
00077
00078
00079
00080
00081
00082
00083 const std::string& Message::getMessage() const
00084 {
00085 return m_message;
00086 }
00087
00088
00089
00090
00091
00092
00093
00094 void Message::setMessage( const std::string& msg )
00095 {
00096 m_message = msg;
00097 }
00098
00099
00100
00101
00102
00103
00104
00105 int Message::getType() const
00106 {
00107 return m_type;
00108 }
00109
00110
00111
00112
00113
00114
00115
00116 void Message::setType( int msg_type )
00117 {
00118 m_type = msg_type;
00119 }
00120
00121
00122
00123
00124
00125
00126
00127 const std::string& Message::getSource() const
00128 {
00129 return m_source;
00130 }
00131
00132
00133
00134
00135
00136
00137
00138 void Message::setSource( const std::string& src )
00139 {
00140 m_source = src;
00141 }
00142
00143
00144
00145
00146
00147
00148
00149 std::ostream& operator << ( std::ostream& stream, const Message& msg )
00150 {
00151 msg.makeFormattedMsg( msg.m_format );
00152 stream << msg.m_formatted_msg;
00153 return stream;
00154 }
00155
00156
00157
00158
00159
00160
00161
00162 bool Message::operator < ( const Message& b )
00163 {
00164 return m_type < b.m_type ||
00165 m_source < b.m_source ||
00166 m_message < b.m_message;
00167 }
00168
00169
00170
00171
00172
00173
00174
00175 bool operator == ( const Message& a, const Message& b )
00176 {
00177 return a.m_source == b.m_source &&
00178 a.m_type == b.m_type &&
00179 a.m_message == b.m_message;
00180 }
00181
00182
00183
00184
00185
00186
00187
00188 const std::string& Message::getFormat() const
00189 {
00190 return m_format;
00191 }
00192
00193
00194
00195
00196
00197
00198
00199 const std::string Message::getDefaultFormat()
00200 {
00201 return DEFAULT_FORMAT;
00202 }
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 void Message::setFormat( const std::string& format ) const
00213 {
00214 if ( format.empty() )
00215 m_format = DEFAULT_FORMAT;
00216 else
00217 m_format = format;
00218 }
00219
00220
00221
00222
00223
00224
00225
00226 const std::string& Message::getTimeFormat() const
00227 {
00228 return m_time_format;
00229 }
00230
00231
00232
00233
00234
00235
00236
00237 const std::string Message::getDefaultTimeFormat()
00238 {
00239 return DEFAULT_TIME_FORMAT ;
00240 }
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250 void Message::setTimeFormat( const std::string& timeFormat ) const
00251 {
00252 if ( timeFormat.empty() )
00253 m_time_format = DEFAULT_TIME_FORMAT;
00254 else
00255 m_time_format = timeFormat;
00256 }
00257
00258
00259
00260
00261
00262
00263
00264 void Message::makeFormattedMsg( const std::string& format ) const
00265 {
00266 m_formatted_msg = "";
00267 std::string::const_iterator i = format.begin();
00268 while( i != format.end() ) {
00269
00270
00271 while( i != format.end() && *i != FORMAT_PREFIX )
00272 m_formatted_msg += *i++;
00273
00274
00275 if ( i == format.end() ) break;
00276 i++;
00277
00278
00279 std::string this_format = "";
00280 while( i != format.end() && *i != FORMAT_PREFIX &&
00281 *i != MESSAGE && *i != TYPE && *i != SOURCE &&
00282 *i != FILL && *i != WIDTH && *i != TIME && *i != UTIME &&
00283 *i != JUSTIFY_LEFT && *i != JUSTIFY_RIGHT ) {
00284 this_format += *i++;
00285 }
00286
00287
00288 if ( i == format.end() ) {
00289 invalidFormat();
00290 break;
00291 }
00292
00293 this_format += *i++;
00294 decodeFormat( this_format );
00295 }
00296 }
00297
00298
00299
00300
00301
00302
00303
00304 void Message::decodeFormat( const std::string& format ) const
00305 {
00306 if ( ! format.empty() ) {
00307 const char FORMAT_TYPE = format[ format.length() - 1 ];
00308 const std::string FORMAT_PARAM = format.substr( 0, format.length() - 1 );
00309
00310
00311 std::string level;
00312 switch( FORMAT_TYPE ) {
00313 case FILL:
00314 if ( FORMAT_PARAM.length() == 1 ) {
00315 m_fill = FORMAT_PARAM[0];
00316 }
00317 else
00318 invalidFormat();
00319 break;
00320
00321 case TIME:
00322 {
00323 const std::string& timeStr = formattedTime ( m_time_format ) ;
00324 sizeField( timeStr );
00325 }
00326 break;
00327
00328 case UTIME:
00329 {
00330 const std::string& timeStr = formattedTime ( m_time_format, true ) ;
00331 sizeField( timeStr );
00332 }
00333 break;
00334
00335 case MESSAGE:
00336 sizeField( m_message );
00337 break;
00338
00339 case SOURCE:
00340 sizeField( m_source );
00341 break;
00342
00343 case TYPE:
00344 switch ( m_type ) {
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
00376
00377
00378
00379
00380 void Message::invalidFormat() const
00381 {
00382 makeFormattedMsg( DEFAULT_FORMAT );
00383 }
00384
00385
00386
00387
00388
00389
00390
00391
00392 void Message::setWidth( const std::string& formatArg ) const
00393 {
00394
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
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
00419
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
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
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
00456 std::string formattedTime ( std::string fmt, bool universal )
00457 {
00458
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
00464 struct tm tms ;
00465 if (universal) {
00466 gmtime_r( &sec, &tms );
00467 } else {
00468 localtime_r( &sec, &tms );
00469 }
00470
00471
00472 std::string::size_type n = fmt.find("%f") ;
00473 if ( n != std::string::npos ) {
00474 char subs[4] ;
00475 std::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