Gaudi Framework, version v20r2

Generated: 18 Jul 2008

Message.cpp

Go to the documentation of this file.
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  

Generated at Fri Jul 18 11:59:22 2008 for Gaudi Framework, version v20r2 by Doxygen version 1.5.1 written by Dimitri van Heesch, © 1997-2004