The Gaudi Framework  v30r0 (c919700c)
Message.cpp
Go to the documentation of this file.
1 #include "GaudiKernel/Message.h"
4 #include "GaudiKernel/Time.h"
5 #include "GaudiKernel/Timing.h"
6 #include <algorithm>
7 #include <cctype>
8 #include <cstdio>
9 #include <cstdlib>
10 #include <iomanip>
11 #include <iostream>
12 #include <string>
13 
14 using namespace MSG;
15 
16 namespace
17 {
18  // get the current time from the system and format it according to the format
19  inline std::string formattedTime( const std::string& fmt, bool universal = false )
20  {
21  return Gaudi::Time::current().format( !universal, fmt );
22  }
23 }
24 
25 //#############################################################################
26 // ---------------------------------------------------------------------------
27 // Routine: Constructor.
28 // Purpose:
29 // ---------------------------------------------------------------------------
30 //
32 {
33  m_ecSlot = Gaudi::Hive::currentContextId();
35  m_ecThrd = pthread_self();
36 }
37 
38 //#############################################################################
39 // ---------------------------------------------------------------------------
40 // Routine: Constructor.
41 // Purpose:
42 // ---------------------------------------------------------------------------
43 //
44 Message::Message( const char* src, int type, const char* msg ) : m_message( msg ), m_source( src ), m_type( type )
45 {
48  m_ecThrd = pthread_self();
49 }
50 
51 //#############################################################################
52 // ---------------------------------------------------------------------------
53 // Routine: Constructor.
54 // Purpose:
55 // ---------------------------------------------------------------------------
56 //
58  : m_message( std::move( msg ) ), m_source( std::move( src ) ), m_type( type )
59 {
62  m_ecThrd = pthread_self();
63 }
64 
65 //#############################################################################
66 // ---------------------------------------------------------------------------
67 // Routine: getMessage
68 // Purpose: Get the message string.
69 // ---------------------------------------------------------------------------
70 //
71 const std::string& Message::getMessage() const { return m_message; }
72 
73 //#############################################################################
74 // ---------------------------------------------------------------------------
75 // Routine: setMessage
76 // Purpose: Set the message string.
77 // ---------------------------------------------------------------------------
78 //
80 
81 //#############################################################################
82 // ---------------------------------------------------------------------------
83 // Routine: getType
84 // Purpose: Get the message type.
85 // ---------------------------------------------------------------------------
86 //
87 int Message::getType() const { return m_type; }
88 
89 //#############################################################################
90 // ---------------------------------------------------------------------------
91 // Routine: setType
92 // Purpose: Set the message type.
93 // ---------------------------------------------------------------------------
94 //
95 void Message::setType( int msg_type ) { m_type = msg_type; }
96 
97 //#############################################################################
98 // ---------------------------------------------------------------------------
99 // Routine: getSource
100 // Purpose: Get the message source.
101 // ---------------------------------------------------------------------------
102 //
103 const std::string& Message::getSource() const { return m_source; }
104 
105 //#############################################################################
106 // ---------------------------------------------------------------------------
107 // Routine: setSource
108 // Purpose: Set the message source.
109 // ---------------------------------------------------------------------------
110 //
112 
113 //#############################################################################
114 // ---------------------------------------------------------------------------
115 // Routine: operator <<
116 // Purpose:Insert the message into a stream.
117 // ---------------------------------------------------------------------------
118 //
120 {
121  msg.makeFormattedMsg( msg.m_format );
122  stream << msg.m_formatted_msg;
123  return stream;
124 }
125 
126 //#############################################################################
127 // ---------------------------------------------------------------------------
128 // Routine: operator <
129 // Purpose: comparison operator needed for maps
130 // ---------------------------------------------------------------------------
131 //
132 bool Message::operator<( const Message& b )
133 {
134  return m_type < b.m_type || m_source < b.m_source || m_message < b.m_message;
135 }
136 
137 //#############################################################################
138 // ---------------------------------------------------------------------------
139 // Routine: operator ==
140 // Purpose: comparison op.
141 // ---------------------------------------------------------------------------
142 //
143 bool operator==( const Message& a, const Message& b )
144 {
145  return a.m_source == b.m_source && a.m_type == b.m_type && a.m_message == b.m_message;
146 }
147 
148 //#############################################################################
149 // ---------------------------------------------------------------------------
150 // Routine:
151 // Purpose: Get the format string.
152 // ---------------------------------------------------------------------------
153 //
154 const std::string& Message::getFormat() const { return m_format; }
155 
156 //#############################################################################
157 // ---------------------------------------------------------------------------
158 // Routine:
159 // Purpose: Get the default format string.
160 // ---------------------------------------------------------------------------
161 //
163 
164 //#############################################################################
165 // ---------------------------------------------------------------------------
166 // Routine:
167 // Purpose: Set the format string -
168 // use isFormatted() to check for valid format.
169 // ---------------------------------------------------------------------------
170 //
172 {
173  if ( LIKELY( !format.empty() ) ) {
174  m_format = std::move( format );
175  } else {
177  }
178 }
179 
180 //#############################################################################
181 // ---------------------------------------------------------------------------
182 // Routine:
183 // Purpose: Get the time format string.
184 // ---------------------------------------------------------------------------
185 //
187 
188 //#############################################################################
189 // ---------------------------------------------------------------------------
190 // Routine:
191 // Purpose: Get the default time format string.
192 // ---------------------------------------------------------------------------
193 //
195 
196 //#############################################################################
197 // ---------------------------------------------------------------------------
198 // Routine:
199 // Purpose: Set the time format string -
200 // use isFormatted() to check for valid format.
201 // ---------------------------------------------------------------------------
202 //
203 void Message::setTimeFormat( std::string timeFormat ) const
204 {
205  m_time_format = ( timeFormat.empty() ? DEFAULT_TIME_FORMAT : std::move( timeFormat ) );
206 }
207 
208 //#############################################################################
209 // ---------------------------------------------------------------------------
210 // Routine: makeFormattedMsg
211 // Purpose: This formats the message according to the format string.
212 // ---------------------------------------------------------------------------
213 //
215 {
217  auto i = format.begin();
218  while ( i != format.end() ) {
219 
220  // Output format string until format statement found.
221  while ( i != format.end() && *i != FORMAT_PREFIX ) m_formatted_msg += *i++;
222 
223  // Test for end of format string.
224  if ( i == format.end() ) break;
225  i++;
226 
227  // Find type of formatting.
228  std::string this_format;
229  while ( i != format.end() && *i != FORMAT_PREFIX && *i != MESSAGE && *i != TYPE && *i != SOURCE && *i != FILL &&
230  *i != WIDTH && *i != TIME && *i != UTIME && *i != SLOT && *i != EVTNUM && *i != THREAD &&
231  *i != JUSTIFY_LEFT && *i != JUSTIFY_RIGHT ) {
232  this_format += *i++;
233  }
234 
235  // Reached end of string with improper format.
236  if ( i == format.end() ) {
237  invalidFormat();
238  break;
239  }
240 
241  this_format += *i++;
242  decodeFormat( this_format );
243  }
244 }
245 
246 //#############################################################################
247 // ---------------------------------------------------------------------------
248 // Routine: decodeFormat
249 // Purpose: This the work horse that checks for a valid format string.
250 // ---------------------------------------------------------------------------
251 //
253 {
254  if ( !format.empty() ) {
255  const char FORMAT_TYPE = format[format.length() - 1];
256  const std::string FORMAT_PARAM = format.substr( 0, format.length() - 1 );
257 
258  // Now test the format.
260  switch ( FORMAT_TYPE ) {
261  case FILL:
262  if ( FORMAT_PARAM.length() == 1 ) {
263  m_fill = FORMAT_PARAM[0];
264  } else
265  invalidFormat();
266  break;
267 
268  case TIME: {
269  sizeField( formattedTime( m_time_format ) );
270  } break;
271 
272  case UTIME: {
273  sizeField( formattedTime( m_time_format, true ) );
274  } break;
275 
276  case THREAD: {
277  std::ostringstream ost;
278  // ost << "0x" << std::hex << pthread_self();
279  ost << "0x" << std::hex << m_ecThrd;
280  const std::string& thrStr( ost.str() );
281  sizeField( thrStr );
282  } break;
283 
284  case SLOT: {
285  if ( m_ecEvt >= 0 ) {
286  std::ostringstream ost;
287  ost << m_ecSlot;
288  const std::string& slotStr( ost.str() );
289  sizeField( slotStr );
290  } else {
291  const std::string& slotStr( "" );
292  sizeField( slotStr );
293  }
294  } break;
295 
296  case EVTNUM: {
297  if ( m_ecEvt >= 0 ) {
298  std::ostringstream ost;
299  ost << m_ecEvt;
300  const std::string& slotStr( ost.str() );
301  sizeField( slotStr );
302  } else {
303  const std::string& slotStr( "" );
304  sizeField( slotStr );
305  }
306  } break;
307 
308  case MESSAGE:
309  sizeField( m_message );
310  break;
311 
312  case SOURCE:
313  sizeField( m_source );
314  break;
315 
316  case TYPE:
317  switch ( m_type ) {
318 #define SET( x ) \
319  case x: \
320  level = #x; \
321  break
322  SET( NIL );
323  SET( VERBOSE );
324  SET( DEBUG );
325  SET( INFO );
326  SET( WARNING );
327  SET( ERROR );
328  SET( FATAL );
329  case ALWAYS:
330  level = "SUCCESS";
331  break;
332  default:
333  level = "UNKNOWN";
334  break;
335 #undef SET
336  }
337  sizeField( level );
338  break;
339 
340  case FORMAT_PREFIX:
342  break;
343  case JUSTIFY_RIGHT:
344  m_left = false;
345  break;
346  case JUSTIFY_LEFT:
347  m_left = true;
348  break;
349  case WIDTH:
350  setWidth( FORMAT_PARAM );
351  break;
352  default:
353  invalidFormat();
354  break;
355  }
356  } else
357  invalidFormat();
358 }
359 
360 //#############################################################################
361 // ---------------------------------------------------------------------------
362 // Routine: invalidFormat.
363 // Purpose: called when invalid format found.
364 // ---------------------------------------------------------------------------
365 //
366 
368 
369 //#############################################################################
370 // ---------------------------------------------------------------------------
371 // Routine: setWidth
372 // Purpose: Sets the minimum width of a stream field.
373 // ---------------------------------------------------------------------------
374 //
375 namespace
376 {
377  // Check that a container only contains digits.
378  constexpr struct all_digit_t {
379  template <typename C>
380  bool operator()( const C& c ) const
381  {
382  return std::all_of( std::begin( c ), std::end( c ),
383  []( typename C::const_reference i ) { return isdigit( i ); } );
384  }
385  } all_digits{};
386 }
387 
388 void Message::setWidth( const std::string& formatArg ) const
389 {
390  // Convert string to int, if string contains digits only...
391  if ( all_digits( formatArg ) )
392  m_width = std::stoi( formatArg );
393  else
394  invalidFormat();
395 }
396 
397 //#############################################################################
398 // ---------------------------------------------------------------------------
399 // Routine: sizeField
400 // Purpose: Truncates or pads the text to m_width as necessary
401 // ---------------------------------------------------------------------------
402 //
403 
404 void Message::sizeField( const std::string& text ) const
405 {
406  std::string newText;
407  if ( m_width == 0 || m_width == static_cast<int>( text.length() ) ) {
408  newText = text;
409  } else {
410 
411  // Truncate the text if it is too long.
412  if ( m_width < static_cast<int>( text.length() ) ) {
413  newText = text.substr( 0, m_width );
414  for ( int i = 0, j = newText.length() - 1; i < 3 && j >= 0; ++i, --j ) newText[j] = '.';
415  }
416 
417  // Pad the text.
418  else {
419  newText = std::string( m_width, m_fill );
420  if ( m_left )
421  newText.replace( newText.begin(), newText.begin() + text.length(), text.begin(), text.end() );
422  else
423  newText.replace( newText.end() - text.length(), newText.end(), text.begin(), text.end() );
424  }
425  }
426 
427  m_formatted_msg += newText;
428 }
size_t m_ecSlot
Definition: Message.h:171
long int m_ecEvt
Definition: Message.h:172
static const char TYPE
The character used to indicate that the message type should be printed.
Definition: Message.h:133
bool m_left
Justification.
Definition: Message.h:116
static const char MESSAGE
The character used to indicate that the message should be printed.
Definition: Message.h:130
const std::string & getFormat() const
Get the format string.
Definition: Message.cpp:154
char m_fill
The current fill character.
Definition: Message.h:110
static const char JUSTIFY_LEFT
The character used to indicate start of left text justification.
Definition: Message.h:124
GAUDI_API ContextIdType currentContextId()
Return the current context id.
T empty(T...args)
GAUDI_API std::string format(const char *,...)
MsgStream format utility "a la sprintf(...)".
Definition: MsgStream.cpp:120
std::string m_formatted_msg
Formatted message.
Definition: Message.h:107
static const char THREAD
Definition: Message.h:169
std::string m_time_format
Time format string.
Definition: Message.h:101
void decodeFormat(const std::string &format) const
Decode format.
Definition: Message.cpp:252
void setWidth(const std::string &formatArg) const
Set the width of a stream.
Definition: Message.cpp:388
bool operator<(const Message &test)
Needed to build maps.
Definition: Message.cpp:132
static Time current()
Returns the current time.
Definition: Time.cpp:112
std::string m_message
The message.
Definition: Message.h:92
void setMessage(std::string msg)
Set the message string.
Definition: Message.cpp:79
STL namespace.
void setType(int msg_type)
Set the message type.
Definition: Message.cpp:95
T end(T...args)
int getType() const
Get the message type.
Definition: Message.cpp:87
Message()
Default constructor.
Definition: Message.cpp:31
friend std::ostream & operator<<(std::ostream &stream, const Message &msg)
Insert the message into a stream.
Definition: Message.cpp:119
void setSource(std::string src)
Set the message source.
Definition: Message.cpp:111
void invalidFormat() const
Called when an invalid format string is encountered.
Definition: Message.cpp:367
STL class.
T replace(T...args)
static const std::string getDefaultTimeFormat()
Get the default time format string.
Definition: Message.cpp:194
static const std::string getDefaultFormat()
Get the default format string.
Definition: Message.cpp:162
static const char EVTNUM
Definition: Message.h:168
T clear(T...args)
friend bool operator==(const Message &a, const Message &b)
Insert the message into a stream.
Definition: Message.cpp:143
T move(T...args)
#define LIKELY(x)
Definition: Kernel.h:127
int m_width
The current field width.
Definition: Message.h:113
static const char TIME
The character used to indicate that the message timestamp should be printed.
Definition: Message.h:136
std::string m_format
The format string.
Definition: Message.h:98
GAUDI_API ContextIdType currentContextEvt()
T length(T...args)
void setFormat(std::string msg) const
Set the format string.
Definition: Message.cpp:171
static const char JUSTIFY_RIGHT
The character used to indicate start of right text justification.
Definition: Message.h:127
static const char UTIME
The character used to indicate that the message timestamp should be printed in UTC time...
Definition: Message.h:140
virtual Out operator()(const vector_of_const_< In > &inputs) const =0
The Message class.
Definition: Message.h:15
static const char SLOT
For slot and event number from EventContext.
Definition: Message.h:167
T begin(T...args)
pthread_t m_ecThrd
Definition: Message.h:173
T all_of(T...args)
static const char FILL
The character used to indicate that the previous character is to be used for padding out fields if th...
Definition: Message.h:148
void makeFormattedMsg(const std::string &format) const
Format the message.
Definition: Message.cpp:214
Print levels enumeration.
Definition: IMessageSvc.h:14
#define SET(x)
void setTimeFormat(std::string timeFormat) const
Set the time format string.
Definition: Message.cpp:203
T hex(T...args)
T substr(T...args)
void sizeField(const std::string &text) const
Truncate or pad the output string to the field width as necessary.
Definition: Message.cpp:404
const std::string & getSource() const
Get the message source.
Definition: Message.cpp:103
const std::string & getTimeFormat() const
Get the time format string.
Definition: Message.cpp:186
static constexpr const char * DEFAULT_FORMAT
The default message format.
Definition: Message.h:160
static const char FORMAT_PREFIX
Formatting string characters.
Definition: Message.h:121
std::string m_source
The source.
Definition: Message.h:95
STL class.
static const char WIDTH
The character used to indicate that the previous decimal characters should be taken as the field widt...
Definition: Message.h:153
T stoi(T...args)
static const char SOURCE
The character used to indicate that the message source should be printed.
Definition: Message.h:143
static constexpr const char * DEFAULT_TIME_FORMAT
The default time format.
Definition: Message.h:164
std::string format(bool local, std::string spec="%c") const
Format the time using strftime.
Definition: Time.cpp:260
const std::string & getMessage() const
Get the message string.
Definition: Message.cpp:71
int m_type
The type.
Definition: Message.h:104