]> Creatis software - crea.git/blob - src/creaMessageManager.h
*** empty log message ***
[crea.git] / src / creaMessageManager.h
1
2
3 /*! \file
4
5  
6
7   \brief Class creaMessageManager and Macros for outputing messages in crea
8
9
10
11   There are 4 kinds of messages :
12
13   - Messages (normal messages)
14
15   - Debug messages (not compiled in release)
16
17   - Warnings 
18
19   - Errors
20
21   There are also "types" of messages which are strings which identify the nature of the message 
22
23   (for example : "Kernel" messages are generated by the core classes of the library, there can be a type of 
24
25   message for each type of Node, and so on...)
26
27   A type of message must be declared by registering it into the MessageManager. This is done by a line like :
28
29   crea::MessageManager::RegisterMessageType("Kernel","Messages generated by the core classes of the library",5);
30
31   where : 
32
33   -The first string is the type of the message (the category which will be used to generate a message of this type)
34
35   -The second string is help string
36
37   -The integer is the initial level for the messages of this type (see below).
38
39   
40
41   To generate a message of a known type then use one of the macros :
42
43   creaMessage, creaDebugMessage, creaWarning, creaError or their variants.
44
45
46
47   example :
48
49
50
51   creaMessage("Kernel",4,"problem with "<<GetName()<<creaendl);
52
53
54
55   will push the 3rd argument in std::cout if the message level of "Kernel" messages is greater or equal to 4.
56
57   which means that it generates a message of level 4 (0 : very important/always displayed ... 9 : deep debug message).
58
59
60
61   At run time, one is able to change the level of the messages displayed by using a command like :
62
63   
64
65   crea::MessageManager::SetMessageLevel("Kernel",5); 
66
67   
68
69   which tells the manager to display all Kernel messages of level up to 5.
70
71
72
73   Variants :
74
75
76
77   crea*Cont : continues a previous creaMessage on the same line (without rewriting the type and level)
78
79   crea*Inc / Dec : displays the message and then increments/decrement the messages tabulation 
80
81
82
83 */
84
85   //===========================================================
86
87   /**
88
89      \class crea::MessageManager
90
91      \brief Manages the messages displayed by crea
92
93   */
94
95
96
97
98
99 #ifndef __creaMessageManager_h__
100
101 #define __creaMessageManager_h__
102
103
104
105 // The do { } while(0) statement in macros is made to "swallow the semicolon" 
106
107 // see http://gcc.gnu.org/onlinedocs/cpp/Swallowing-the-Semicolon.html#Swallowing-the-Semicolon
108
109
110
111 #include "creaSystem.h"
112
113 #include "creaRTTI.h" // for CREA_GET_CURRENT_OBJECT_NAME
114
115 // Signal/slot mechanism for message events
116
117 #include <boost/signal.hpp>
118
119 #include <boost/bind.hpp>
120
121
122
123 #include <string>
124
125 #include <map>
126
127 #include <iostream>
128
129 #include <sstream>
130
131
132
133 // Comment out these symbols to prevent compilation 
134
135 //#define CREA_COMPILE_MESSAGES
136
137 //#define CREA_COMPILE_DEBUG_MESSAGES
138
139 //#define CREA_COMPILE_WARNING_MESSAGES
140
141 //#define CREA_COMPILE_ERROR_MESSAGES
142
143
144
145
146
147 #define creaOnMessageLevel(key,value)                   \
148   int __creaOnMessageLevelVariable =                    \
149     crea::MessageManager::GetMessageLevel(key);         \
150   if ( __creaOnMessageLevelVariable<0)                  \
151     {                                                   \
152       creaWarning("message type '"<<key<<"' unknown");  \
153     }                                                   \
154   else if (value<= __creaOnMessageLevelVariable) 
155
156
157
158 #ifdef CREA_PREPEND_MESSAGE_WITH_CODE
159 #define creaMessageCode                         \
160   key[0] << key[1] << key[2] << value << " "
161 #else 
162 #define creaMessageCode ""
163 #endif 
164
165
166
167 #ifdef CREA_PREPEND_MESSAGE_WITH_TAB
168 #define creaMessageTab                          \
169   crea::MessageManager::GetTab()
170 #else 
171 #define creaMessageTab ""
172 #endif
173
174
175
176 //#define CREA_PREPEND_MESSAGE_WITH_SPACE
177 #ifdef CREA_PREPEND_MESSAGE_WITH_SPACE
178 #define creaMessageSpace(value)                 \
179   crea::MessageManager::GetSpace(value)
180 #else 
181 #define creaMessageSpace(value) ""
182 #endif
183
184  
185
186
187
188 //===========================================================
189
190 #ifdef CREA_COMPILE_MESSAGES
191
192 // Macro for messages
193 #define creaMessage(key,value,MESSAGE)                  \
194   do {                                                  \
195     creaOnMessageLevel(key,value)                       \
196       {                                                 \
197         std::ostringstream s;                           \
198         s << creaMessageCode                            \
199           << creaMessageTab                             \
200           << creaMessageSpace(value)                    \
201           << MESSAGE;                                   \
202         crea::MessageManager::SendMessage(key,s.str()); \
203       }                                                 \
204   }                                                     \
205   while (0)
206
207
208
209 // Macro for continuing a message (when one wants to split the macro
210 // call into multiple lines)
211 #define creaMessageCont(key,value,MESSAGE)              \
212   do                                                    \
213     {                                                   \
214       creaOnMessageLevel(key,value)                     \
215         {                                               \
216         std::ostringstream s;                           \
217         s << MESSAGE;                                   \
218         crea::MessageManager::SendMessage(key,s.str()); \
219         }                                               \
220     }                                                   \
221   while (0)
222
223
224 #define creaMessageInc(key,value,MESSAGE)               \
225   do                                                    \
226     {                                                   \
227         std::ostringstream s;                           \
228         s << creaMessageCode                            \
229           << creaMessageTab                             \
230           << creaMessageSpace(value)                    \
231           << MESSAGE;                                   \
232         crea::MessageManager::SendMessage(key,s.str()); \
233         crea::MessageManager::IncTab();                 \
234         }                                               \
235     }                                                   \
236   while (0)
237
238
239 #define creaMessageDec(key,value,MESSAGE)                       \
240   do                                                            \
241     {                                                           \
242       creaOnMessageLevel(key,value)                             \
243         {                                                       \
244           crea::MessageManager::DecTab();                       \
245           std::ostringstream s;                                 \
246           s << creaMessageCode                                  \
247             << creaMessageTab                                   \
248             << creaMessageSpace(value)                          \
249             << MESSAGE;                                         \
250           crea::MessageManager::SendMessage(key,s.str());       \
251         }                                                       \
252     }                                                           \
253   while (0)
254
255
256 #define creaDecTab(key,value)                   \
257   do                                            \
258     {                                           \
259       creaOnMessageLevel(key,value)             \
260         {                                       \
261           crea::MessageManager::DecTab();       \
262         }                                       \
263     }                                           \
264   while (0)
265
266
267 #define creaIncTab(key,value)                   \
268   do                                            \
269     {                                           \
270       creaOnMessageLevel(key,value)             \
271         {                                       \
272           crea::MessageManager::IncTab();       \
273         }                                       \
274     }                                           \
275   while (0)
276
277
278 #define creaResetTab()                          \
279   do                                            \
280     {                                           \
281       crea::MessageManager::ResetTab();         \
282     }                                           \
283   while (0)
284
285 #else
286 #define creaMessage(key,value,MESSAGE)
287 #define creaMessageInc(key,value,MESSAGE)
288 #define creaMessageDec(key,value,MESSAGE)
289 #define creaMessageCont(key,value,MESSAGE)
290 #define creaDecTab(key,value)
291 #define creaIncTab(key,value)
292 #define creaResetTab()
293 #endif
294
295 //===========================================================
296
297
298
299
300
301
302
303 //===========================================================
304
305 // Macros for debug messages
306
307 #ifdef CREA_COMPILE_DEBUG_MESSAGES
308
309 #define creaDebugMessage(key,value,MESSAGE) creaMessage(key,value,MESSAGE)
310
311 #define creaDebugMessageCont(key,value,MESSAGE) creaMessageCont(key,value,MESSAGE)
312
313 #define creaDebugMessageInc(key,value,MESSAGE) creaMessageInc(key,value,MESSAGE)  
314
315 #define creaDebugMessageDec(key,value,MESSAGE) creaMessageDec(key,value,MESSAGE)
316
317 #define creaDebugDecTab(key,value) creaDecTab(key,value)
318
319 #define creaDebugIncTab(key,value) creaIncTab(key,value)
320
321 #define creaDebugResetTab() creaResetTab()
322
323 #else
324
325 #define creaDebugMessage(key,value,MESSAGE) 
326
327 #define creaDebugMessageCont(key,value,MESSAGE) 
328
329 #define creaDebugMessageInc(key,value,MESSAGE)
330
331 #define creaDebugMessageDec(key,value,MESSAGE) 
332
333 #define creaDebugDecTab(key,value)
334
335 #define creaDebugIncTab(key,value)
336
337 #endif
338
339 //===========================================================
340
341
342
343 //===========================================================
344
345 #ifdef CREA_COMPILE_WARNING_MESSAGES
346 #define creaWarning(MESSAGE)                                            \
347   do                                                                    \
348     {                                                                   \
349       int lev = crea::MessageManager::GetMessageLevel("warning");       \
350       if (lev >0)                                                       \
351         {                                                               \
352           std::cerr << "!! WARNING !! " << MESSAGE << std::endl;        \
353           if (lev >1)                                                   \
354             {                                                           \
355               std::cerr << "!! WARNING !! In file '"<<__FILE__          \
356                         <<"' ; Line "<<__LINE__<<std::endl;             \
357             }                                                           \
358         }                                                               \
359     }                                                                   \
360   while (0) 
361
362 #else
363 #define creaWarning(MESSAGE) 
364 #endif
365
366 //===========================================================
367
368
369
370
371
372 //===========================================================
373
374 #ifdef CREA_COMPILE_ERROR_MESSAGES
375 //#include "creaWx.h"
376 #define creaError(MESSAGE)                              \
377   do                                                    \
378     {                                                   \
379       std::ostringstream s;                             \
380       s << MESSAGE;                                     \
381       std::ostringstream f;                             \
382       f << __FILE__ << " (l."<<__LINE__<<")";           \
383       crea::Exception e( CREA_GET_CURRENT_OBJECT_NAME,  \
384                         f.str(),                        \
385                         s.str());                       \
386       throw e;                                          \
387     }                                                   \
388   while (0) 
389
390
391
392 #define creaGlobalError(MESSAGE)                                \
393   do                                                    \
394     {                                                   \
395       std::ostringstream s;                             \
396       s << MESSAGE;                                     \
397       std::ostringstream f;                             \
398       f << __FILE__ << " (l."<<__LINE__<<")";           \
399       crea::Exception e( "global scope",                \
400                         f.str(),                        \
401                         s.str());                       \
402       throw e;                                          \
403     }                                                   \
404   while (0) 
405
406
407
408 #define CREA_INTERNAL_ERROR_MESSAGE \
409   "\n\n***********************************************\n**** THIS IS AN INTERNAL ERROR TO crea     ****\n**** Please send a full bug report to :    ****\n****  creatools@creatis.insa-lyon.fr ****\n***********************************************\n\n"
410
411 #define creaInternalError(MESSAGE)                      \
412   do                                                    \
413     {                                                   \
414       std::ostringstream s;                             \
415       s << MESSAGE << CREA_INTERNAL_ERROR_MESSAGE;      \
416       std::ostringstream f;                             \
417       f << __FILE__ << " (l."<<__LINE__<<")";           \
418       crea::Exception e( CREA_GET_CURRENT_OBJECT_NAME,  \
419                          f.str(),                       \
420                          s.str());                      \
421       throw e;                                          \
422     }                                                   \
423   while (0) 
424
425
426
427 #else
428 #define creaError(MESSAGE)
429 #define creaGlobalError(MESSAGE)
430 #define creaInternalError(MESSAGE)
431 #endif
432
433 //===========================================================
434
435
436
437 //===========================================================
438
439 #define creaendl std::endl
440
441 //===========================================================
442
443
444
445
446
447 namespace crea 
448
449 {
450
451   
452
453   class CREA_EXPORT MessageManager
454
455   {
456
457   public:
458
459     //=============================================
460
461     typedef boost::signal<void (const std::string&)>  MessageSignalType;
462
463     typedef MessageSignalType::slot_function_type MessageCallbackType;
464
465     //=============================================
466
467     ///
468
469     MessageManager();
470
471     ///
472
473     ~MessageManager();
474
475     ///
476
477     static MessageManager* GetInstance();
478
479     ///
480
481     static void RegisterMessageType(const std::string& key, 
482
483                                     const std::string& help,
484
485                                     unsigned char default_level = 9);
486
487     ///
488
489     static void SetMessageLevel(const std::string& key, unsigned char level);
490
491     ///
492
493     static int GetMessageLevel(const std::string& key);
494
495     ///  
496
497     static void SendMessage(const std::string& key, const std::string& mess);
498
499     ///
500
501     static void AddMessageObserver(const std::string& key, MessageCallbackType callback );
502
503     ///
504
505     static void SendMessagesToCout(bool v = true);
506
507     ///
508
509     static std::string& GetTab() { static std::string s; return s; }
510
511     ///
512
513     static std::string GetSpace(int n) { 
514
515       std::string s; s.insert(0,"                ",n); return s; }
516
517     ///
518
519     static void IncTab() { GetTab() += std::string(" "); }
520
521     ///
522
523     static void DecTab() { GetTab() = GetTab().substr(0,GetTab().length()-1); }
524
525     ///
526
527     static void ResetTab() { GetTab() = std::string(""); }
528
529     ///
530
531     static void PrintInfo();
532
533     /// 
534
535     
536
537   private:
538
539     struct MessageType
540
541     {
542
543       MessageType(int l, const std::string& h) : Level(l), Help(h) {}
544
545       int Level;
546
547       std::string Help;
548
549       MessageSignalType Signal;
550
551     };
552
553     typedef std::map<std::string,MessageType*> MessageMapType;
554
555     MessageMapType mMessageMap;
556
557     unsigned int mMaxMessageLength;
558
559     bool mSendToCout;
560
561   };
562
563   //===========================================================
564
565   
566
567 }
568
569
570
571 #include "creaException.h"
572
573
574
575 #endif
576