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