| The Gaudi Framework v32r1 (f65d50dc)

Message.cpp
Go to the documentation of this file.
1 #include "GaudiKernel/Message.h"
2 #include "GaudiKernel/IMessageSvc.h"
3 #include "GaudiKernel/ThreadLocalContext.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 //
37 Message::Message( std::string src, int type, std::string msg )
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 //
54 void Message::setMessage( std::string msg ) { m_message = std::move( msg ); }
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 //
86 void Message::setSource( std::string src ) { m_source = std::move( src ); }
87
88 //#############################################################################
89 // ---------------------------------------------------------------------------
90 // Routine: operator <<
91 // Purpose:Insert the message into a stream.
92 // ---------------------------------------------------------------------------
93 //
94 std::ostream& operator<<( std::ostream& stream, const Message& msg ) {
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 //
134 const std::string Message::getDefaultFormat() { return DEFAULT_FORMAT; }
135
136 //#############################################################################
137 // ---------------------------------------------------------------------------
138 // Routine:
139 // Purpose: Set the format string -
140 // use isFormatted() to check for valid format.
141 // ---------------------------------------------------------------------------
142 //
143 void Message::setFormat( std::string format ) const {
144 if ( LIKELY( !format.empty() ) ) {
145 m_format = std::move( format );
146 } else {
147 m_format = DEFAULT_FORMAT;
148 }
149 }
150
151 //#############################################################################
152 // ---------------------------------------------------------------------------
153 // Routine:
154 // Purpose: Get the time format string.
155 // ---------------------------------------------------------------------------
156 //
157 const std::string& Message::getTimeFormat() const { return m_time_format; }
158
159 //#############################################################################
160 // ---------------------------------------------------------------------------
161 // Routine:
162 // Purpose: Get the default time format string.
163 // ---------------------------------------------------------------------------
164 //
165 const std::string Message::getDefaultTimeFormat() { return DEFAULT_TIME_FORMAT; }
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 //
184 void Message::makeFormattedMsg( const std::string& format ) const {
185 m_formatted_msg.clear();
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 //
221 void Message::decodeFormat( const std::string& format ) const {
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.
227 std::string level;
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;
254 if ( m_ecSlot != EventContext::INVALID_CONTEXT_ID ) { ost << m_ecSlot; }
255 sizeField( ost.str() );
256 } break;
257
258 case EVTNUM: {
259 std::ostringstream ost;
260 if ( m_ecEvt != EventContext::INVALID_CONTEXT_EVT ) { ost << m_ecEvt; }
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:
303 m_formatted_msg += 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
329 void Message::invalidFormat() const { makeFormattedMsg( DEFAULT_FORMAT ); }
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 }
Message::TYPE
static const char TYPE
The character used to indicate that the message type should be printed.
Definition: Message.h:125
Message::m_left
bool m_left
The message alignment.
Definition: Message.h:100
Message::MESSAGE
static const char MESSAGE
The character used to indicate that the message should be printed.
Definition: Message.h:122
Message::m_fill
char m_fill
Current fill character.
Definition: Message.h:98
Message::JUSTIFY_LEFT
static const char JUSTIFY_LEFT
The character used to indicate start of left text justification.
Definition: Message.h:116
std::string::empty
T empty(T... args)
Message::sizeField
void sizeField(const std::string &text) const
Truncate or pad the output string to the field width as necessary.
Definition: Message.cpp:363
Message::decodeFormat
void decodeFormat(const std::string &format) const
Decode format.
Definition: Message.cpp:221
format
GAUDI_API std::string format(const char *,...)
MsgStream format utility "a la sprintf(...)".
Definition: MsgStream.cpp:109
Message::m_formatted_msg
std::string m_formatted_msg
Formatted message.
Definition: Message.h:97
gaudirun.c
c
Definition: gaudirun.py:487
Message::THREAD
static const char THREAD
The character used to indicate that the thread ID should be printed.
Definition: Message.h:143
Message::m_time_format
std::string m_time_format
Time format string.
Definition: Message.h:96
Message::getType
int getType() const
Get the message type.
Definition: Message.cpp:62
Message::Message
Message()=default
Default constructor.
Message::operator<
bool operator<(const Message &test)
Needed to build maps.
Definition: Message.cpp:106
operator==
bool operator==(const Message &a, const Message &b)
Insert the message into a stream.
Definition: Message.cpp:116
ThreadLocalContext.h
Message::m_ecEvt
EventContext::ContextEvt_t m_ecEvt
Event number.
Definition: Message.h:105
MSG::DEBUG
Definition: IMessageSvc.h:15
Gaudi::Time::current
static Time current()
Returns the current time.
Definition: Time.cpp:109
Message::m_message
std::string m_message
The message text.
Definition: Message.h:92
Message::setMessage
void setMessage(std::string msg)
Set the message string.
Definition: Message.cpp:54
std
STL namespace.
Message::setType
void setType(int msg_type)
Set the message type.
Definition: Message.cpp:70
Message::setWidth
void setWidth(const std::string &formatArg) const
Set the width of a stream.
Definition: Message.cpp:348
std::string::end
T end(T... args)
SET
#define SET(x)
Message::m_ecEvtId
EventIDBase m_ecEvtId
Full event ID.
Definition: Message.h:106
MSG::VERBOSE
Definition: IMessageSvc.h:15
Message::EVENTID
static const char EVENTID
The character used to indicate that the full event ID should be printed.
Definition: Message.h:146
Message::setSource
void setSource(std::string src)
Set the message source.
Definition: Message.cpp:86
Message::getSource
const std::string & getSource() const
Get the message source.
Definition: Message.cpp:78
Message::setFormat
void setFormat(std::string msg) const
Set the format string.
Definition: Message.cpp:143
std::string
STL class.
MSG::FATAL
Definition: IMessageSvc.h:15
EventContext::INVALID_CONTEXT_EVT
static constexpr ContextEvt_t INVALID_CONTEXT_EVT
Definition: EventContext.h:30
std::string::replace
T replace(T... args)
Message::getDefaultTimeFormat
static const std::string getDefaultTimeFormat()
Get the default time format string.
Definition: Message.cpp:165
Message::invalidFormat
void invalidFormat() const
Called when an invalid format string is encountered.
Definition: Message.cpp:329
std::ostringstream
STL class.
gaudirun.type
type
Definition: gaudirun.py:142
operator<<
std::ostream & operator<<(std::ostream &stream, const Message &msg)
Insert the message into a stream.
Definition: Message.cpp:94
Message::getDefaultFormat
static const std::string getDefaultFormat()
Get the default format string.
Definition: Message.cpp:134
MSG::NIL
Definition: IMessageSvc.h:15
EventContext::INVALID_CONTEXT_ID
static constexpr ContextID_t INVALID_CONTEXT_ID
Definition: EventContext.h:29
std::ostringstream::str
T str(T... args)
IMessageSvc.h
Message::EVTNUM
static const char EVTNUM
The character used to indicate that the event number should be printed.
Definition: Message.h:140
Time.h
std::string::clear
T clear(T... args)
std::move
T move(T... args)
Message::m_ecSlot
EventContext::ContextID_t m_ecSlot
Event slot.
Definition: Message.h:104
LIKELY
#define LIKELY(x)
Definition: Kernel.h:95
EventIDBase::isValid
bool isValid() const
Definition: EventIDBase.h:147
Timing.h
Message::getFormat
const std::string & getFormat() const
Get the format string.
Definition: Message.cpp:126
Message::makeFormattedMsg
void makeFormattedMsg(const std::string &format) const
Format the message.
Definition: Message.cpp:184
Message::m_width
int m_width
Current field width.
Definition: Message.h:99
Message::TIME
static const char TIME
The character used to indicate that the message timestamp should be printed.
Definition: Message.h:128
Message::m_format
std::string m_format
The format string.
Definition: Message.h:95
std::string::length
T length(T... args)
Gaudi::Time::format
std::string format(bool local, std::string spec="%c") const
Format the time using strftime.
Definition: Time.cpp:252
Message::JUSTIFY_RIGHT
static const char JUSTIFY_RIGHT
The character used to indicate start of right text justification.
Definition: Message.h:119
Message::setTimeFormat
void setTimeFormat(std::string timeFormat) const
Set the time format string.
Definition: Message.cpp:174
Message::UTIME
static const char UTIME
The character used to indicate that the message timestamp should be printed in UTC time.
Definition: Message.h:131
Message
The Message class.
Definition: Message.h:17
Message::SLOT
static const char SLOT
The character used to indicate that the slot number should be printed.
Definition: Message.h:137
std::string::begin
T begin(T... args)
Message::getMessage
const std::string & getMessage() const
Get the message string.
Definition: Message.cpp:46
Message::m_ecThrd
pthread_t m_ecThrd
Thread ID.
Definition: Message.h:107
std::all_of
T all_of(T... args)
Message::FILL
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
MSG
Print levels enumeration.
Definition: IMessageSvc.h:14
GaudiMP.FdsRegistry.msg
msg
Definition: FdsRegistry.py:8
std::hex
T hex(T... args)
MSG::ERROR
Definition: IMessageSvc.h:15
std::string::substr
T substr(T... args)
gaudirun.level
level
Definition: gaudirun.py:334
MSG::WARNING
Definition: IMessageSvc.h:15
Message::DEFAULT_FORMAT
static constexpr const char * DEFAULT_FORMAT
The default message format.
Definition: Message.h:156
MSG::INFO
Definition: IMessageSvc.h:15
Message::FORMAT_PREFIX
static const char FORMAT_PREFIX
The character used to prefix formatting commands.
Definition: Message.h:113
Message::m_source
std::string m_source
The message source.
Definition: Message.h:93
std::ostream
STL class.
Message::WIDTH
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
std::stoi
T stoi(T... args)
Message::SOURCE
static const char SOURCE
The character used to indicate that the message source should be printed.
Definition: Message.h:134
MSG::ALWAYS
Definition: IMessageSvc.h:15
Message::DEFAULT_TIME_FORMAT
static constexpr const char * DEFAULT_TIME_FORMAT
The default time format (accepts strftime formatters plus %f for milliseconds).
Definition: Message.h:159
Message::getTimeFormat
const std::string & getTimeFormat() const
Get the time format string.
Definition: Message.cpp:157
Message::m_type
int m_type
The message type/level.
Definition: Message.h:94
Message.h