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