]> Creatis software - gdcm.git/blob - src/gdcmDebug.h
To prepare use of progression bar in all types of Document
[gdcm.git] / src / gdcmDebug.h
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: gdcmDebug.h,v $
5   Language:  C++
6   Date:      $Date: 2005/11/29 17:21:34 $
7   Version:   $Revision: 1.52 $
8                                                                                 
9   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10   l'Image). All rights reserved. See Doc/License.txt or
11   http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
12                                                                                 
13      This software is distributed WITHOUT ANY WARRANTY; without even
14      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15      PURPOSE.  See the above copyright notices for more information.
16                                                                                 
17 =========================================================================*/
18
19 #ifndef GDCMDEBUG_H
20 #define GDCMDEBUG_H
21
22 #include "gdcmCommon.h"
23 #include "gdcmCommand.h"
24
25 #include <iostream>
26 #include <sstream>
27 #include <fstream>
28 #include <assert.h>
29 #include <errno.h>
30
31 namespace gdcm 
32 {
33 //-----------------------------------------------------------------------------
34 class CommandManager;
35
36 //-----------------------------------------------------------------------------
37 /**
38  * \brief Debug is an object for debugging in program.
39  * It has 2 debugging modes :
40  *  - error : for bad library use, seriously wrong DICOM
41  *  - debug : for information/debug messages
42  *  - warning : for warning about DICOM quality (kosher)
43  *  - assert : design by contract implementation. A function should have 
44  *             proper input and proper output. 
45  *             (should not happen, not user controlled)
46  * 
47  * A debugging message is only shown if the flag is on (DebugFlag)
48  * This is static var and can be set at beginning of code:
49  *         gdcm::Debug::SetDebugOn();
50  */
51 class GDCM_EXPORT Debug
52 {
53 public:
54    Debug();
55    ~Debug();
56
57    /// \brief This is a global flag that controls whether 
58    ///        both debug and warning messages are displayed. 
59    ///        (used to warn user when file contains some oddity)
60    static void SetDebugFlag (bool flag);
61    /// \brief   Gets the debug flag value
62    static bool GetDebugFlag () {return DebugFlag;}
63    /// \brief Sets the Debug Flag to true
64    static void DebugOn  () { SetDebugFlag(true);  }
65    /// \brief Sets the Debug Flag to false
66    static void DebugOff () { SetDebugFlag(false); }
67    
68    /// \brief This is a global flag that controls whether 
69    ///        warning messages are displayed.
70    static void SetWarningFlag (bool flag);
71    /// \brief   Gets the warning flag value
72    static bool GetWarningFlag () {return WarningFlag;}
73    /// \brief Sets the Warning Flag to true
74    static void WarningOn  () { SetWarningFlag(true);  }
75    /// \brief Sets the Warning Flag to false
76    static void WarningOff () { SetWarningFlag(false); }   
77
78    /// \brief This is a global flag that controls if debug are redirected
79    ///        to a file or not
80    static void SetOutputToFile (bool flag);
81    static bool GetOutputToFile ();
82    /// \brief Next debug messages will be sent in the debug file
83    static void OutputToFileOn  () { SetOutputToFile(true);  }
84    /// \brief Next debug messages will be sent in the standard output
85    static void OutputToFileOff () { SetOutputToFile(false); }
86
87    static void SetOutputFileName (std::string const &filename);
88
89    static std::ostream &GetOutput ();
90
91    static void SendToOutput(unsigned int type,std::string const &msg,
92                             const Base *object = NULL);
93
94 private:
95    static bool DebugFlag;
96    static bool WarningFlag;
97    static bool OutputToFile;
98
99    static std::ofstream OutputFileStream;
100    static std::ostream &StandardStream;
101
102    static const int LINE_LENGTH;
103 };
104
105 } // end namespace gdcm
106
107 // Here we define function this is the only way to be able to pass
108 // stuff with indirection like:
109 // gdcmDebug( "my message:" << i << '\t' ); 
110 // You cannot use function unless you use vnsprintf ...
111
112 // __FUNCTION is not always defined by preprocessor
113 // In c++ we should use __PRETTY_FUNCTION__ instead...
114 #ifdef GDCM_COMPILER_HAS_FUNCTION
115 // Handle particular case for GNU C++ which also defines __PRETTY_FUNCTION__
116 // which is a lot nice in C++
117 #ifdef __BORLANDC__
118 #  define __FUNCTION__ __FUNC__
119 #endif
120 #ifdef __GNUC__
121 #  define GDCM_FUNCTION __PRETTY_FUNCTION__
122 #else
123 #  define GDCM_FUNCTION __FUNCTION__ 
124 #endif //__GNUC__
125 #else
126 #  define GDCM_FUNCTION "<unknow>"
127 #endif //GDCM_COMPILER_HAS_FUNCTION
128
129 /**
130  * \brief   Debug : To be used to help bug tracking developer
131  * @param msg message part
132  */
133 #define gdcmMessageBodyMacro(type, obj, msg, adds)             \
134 {                                                              \
135    std::ostringstream osmacro;                                 \
136    osmacro << "In " __FILE__ ", line " << __LINE__             \
137            << ", function " << GDCM_FUNCTION << "\n"           \
138            << adds << msg << "\n\n";                           \
139    gdcm::Debug::SendToOutput(type,osmacro.str(),obj);          \
140 }
141
142 /**
143  * \brief Debug : To be used to help bug tracking developer
144  * @param msg message part
145  */
146 #ifdef NDEBUG
147 #define gdcmDebugBodyMacro(obj, msg) {}
148 #define gdcmDebugMacro(msg) {}
149 #define gdcmStaticDebugMacro(msg) {}
150 #else
151 #define gdcmDebugBodyMacro(obj, msg)                           \
152 {                                                              \
153    if( Debug::GetDebugFlag() )                                 \
154    {                                                           \
155       std::string adds="";                                     \
156       if( errno )                                              \
157       {                                                        \
158          adds = "Last system error was: ";                     \
159          adds += strerror(errno);                              \
160          adds += "\n";                                         \
161       }                                                        \
162       gdcmMessageBodyMacro(gdcm::CMD_DEBUG,obj,msg,adds);      \
163    }                                                           \
164 }
165 #define gdcmDebugMacro(msg)                                    \
166    gdcmDebugBodyMacro(NULL,msg)
167 #define gdcmStaticDebugMacro(msg)                              \
168    gdcmDebugBodyMacro(NULL,msg)
169 #endif //NDEBUG
170
171 /**
172  * \brief Warning : To be used to warn the user when some oddity occurs
173  * @param msg message part
174  */
175 // No NDEBUG test to always have a return of warnings !!!
176 // -> Rien compris! JPRx
177 #define gdcmWarningBodyMacro(obj, msg)                         \
178 {                                                              \
179    if( Debug::GetWarningFlag() )                               \
180       gdcmMessageBodyMacro(gdcm::CMD_WARNING,obj,msg,"");      \
181 }
182 #define gdcmWarningMacro(msg)                                  \
183    gdcmWarningBodyMacro(this,msg)
184 #define gdcmStaticWarningMacro(msg)                            \
185    gdcmWarningBodyMacro(NULL,msg)
186
187 /**
188  * \brief   Error : To be used when unecoverabale error occurs
189  *          at a 'deep' level. (don't use it if file is not ACR/DICOM!)
190  * @param msg second message part 
191  */
192 // No NDEBUG test to always have a return of errors !!!
193 // -> Rien compris! JPRx
194 #define gdcmErrorBodyMacro(obj, msg)                           \
195 {                                                              \
196    gdcmMessageBodyMacro(gdcm::CMD_ERROR,obj,msg,"");           \
197 }
198 #define gdcmErrorMacro(msg)                                    \
199    gdcmErrorBodyMacro(this,msg)
200 #define gdcmStaticErrorMacro(msg)                              \
201    gdcmErrorBodyMacro(NULL,msg)
202
203 /**
204  * \brief Assert : To be used when an *absolutely* impossible error occurs
205  *        No function should be allowed to stop the process instead of
206  *        warning the caller!
207  * @param arg argument to test
208  *        An easy solution to pass also a message is to do:
209  *        gdcmAssertMacro( "my message" && 2 < 3 )
210  */
211 // No NDEBUG test to always have a return of asserts !!!
212 // -> Rien compris! JPRx
213 #define gdcmAssertBodyMacro(obj, arg)                          \
214 {                                                              \
215    if( !(arg) )                                                \
216    {                                                           \
217       gdcmMessageBodyMacro(gdcm::CMD_ASSERT,obj,"","");        \
218       assert ( arg );                                          \
219    }                                                           \
220 }
221 #define gdcmAssertMacro(msg)                                   \
222    gdcmAssertBodyMacro(NULL,msg)
223 #define gdcmStaticAssertMacro(msg)                             \
224    gdcmAssertBodyMacro(NULL,msg)
225
226 //-----------------------------------------------------------------------------
227 #endif