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