1 /*=========================================================================
4 Module: $RCSfile: gdcmDebug.h,v $
6 Date: $Date: 2008/04/10 12:15:36 $
7 Version: $Revision: 1.59 $
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.
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.
17 =========================================================================*/
22 #include "gdcmCommon.h"
23 #include "gdcmCommand.h"
29 #include <string.h> // strerror
32 namespace GDCM_NAME_SPACE
34 //-----------------------------------------------------------------------------
37 //-----------------------------------------------------------------------------
39 * \brief Debug is an object for warning/logging/tracing programs.
40 * It has the following modes :
41 * - error : for bad library use, seriously wrong DICOM
42 * - debug : for information/debug messages
43 * - warning : Warns the user when some oddity occured.
44 * - log : we display messages when anything is not Dicom Kosher
45 * - debug : we help developper to trace, at a glance, the execution
46 * - assert : design by contract implementation. A function should have
47 * proper input and proper output.
48 * (should not happen, not user controlled)
50 * A debugging message is only shown if the flag is on (DebugFlag)
51 * This is static var and can be set at beginning of code:
52 * GDCM_NAME_SPACE::Debug::SetDebugOn();
54 * Warning : Warns the user when some oddity occured, and we used an heuristics
55 * to bypass the trouble.
56 * e.g. : SamplesPerPixel missing, we assume it's a grey level image
57 * e.g : Pixel Representation missing : we assume 'unsigned'
58 * (we hope our assumption is OK, but user may disagree.)
59 * Log : we display messages when anything is not Dicom Kosher
60 * e.g. : non even length field
61 * e.g : file is declared as Explicit VR, but a DataElement
63 * e.g : a file holds an illegal group (0x0005, ...)
64 * Debug : We help developper to trace, at a glance, the execution.
65 * (before refining with a debugging tool)
67 * Setting ON Debug leads to set ON Warning (but not Log)
68 * Setting ON Log leads to set ON Warning (but not Debug)
71 class GDCM_EXPORT Debug
77 /// \brief This is a global flag that controls whether
78 /// both debug and warning messages are displayed.
79 /// (used to warn user when file contains some oddity)
80 static void SetDebugFlag (bool flag);
81 /// \brief Gets the debug flag value
82 static bool GetDebugFlag () {return DebugFlag; }
83 /// \brief Sets the Debug Flag to true
84 static void DebugOn () { SetDebugFlag(true); }
85 /// \brief Sets the Debug Flag to false
86 static void DebugOff () { SetDebugFlag(false); }
88 /// \brief This is a global flag that controls whether
89 /// log messages are displayed.
90 static void SetLogFlag (bool flag);
91 /// \brief Gets the Log flag value
92 static bool GetLogFlag () {return LogFlag; }
93 /// \brief Sets the Log Flag to true
94 static void LogOn () { SetLogFlag(true); }
95 /// \brief Sets the Log Flag to false
96 static void LogOff () { SetLogFlag(false); }
98 /// \brief This is a global flag that controls whether
99 /// warning messages are displayed.
100 static void SetWarningFlag (bool flag);
101 /// \brief Gets the warning flag value
102 static bool GetWarningFlag () {return WarningFlag; }
103 /// \brief Sets the Warning Flag to true
104 static void WarningOn () { SetWarningFlag(true); }
105 /// \brief Sets the Warning Flag to false
106 static void WarningOff () { SetWarningFlag(false); }
108 /// \brief This is a global flag that controls if debug are redirected
110 static void SetOutputToFile (bool flag);
111 static bool GetOutputToFile ();
112 /// \brief Next debug messages will be sent in the debug file
113 static void OutputToFileOn () { SetOutputToFile(true); }
114 /// \brief Next debug messages will be sent in the standard output
115 static void OutputToFileOff () { SetOutputToFile(false); }
117 static void SetOutputFileName (std::string const &filename);
119 static std::ostream &GetOutput ();
121 static void SendToOutput(unsigned int type,std::string const &msg,
122 const Base *object = NULL);
125 static bool WarningFlag;
127 static bool DebugFlag;
129 static bool OutputToFile;
131 static std::ofstream OutputFileStream;
132 static std::ostream &StandardStream;
134 static const int LINE_LENGTH;
137 } // end namespace gdcm
139 // Here we define function this is the only way to be able to pass
140 // stuff with indirection like:
141 // gdcmDebug( "my message:" << i << '\t' );
142 // You cannot use function unless you use vnsprintf ...
144 // __FUNCTION is not always defined by preprocessor
145 // In c++ we should use __PRETTY_FUNCTION__ instead...
146 #ifdef GDCM_COMPILER_HAS_FUNCTION
147 // Handle particular case for GNU C++ which also defines __PRETTY_FUNCTION__
148 // which is a lot nice in C++
150 # define __FUNCTION__ __FUNC__
153 # define GDCM_FUNCTION __PRETTY_FUNCTION__
155 # define GDCM_FUNCTION __FUNCTION__
158 # define GDCM_FUNCTION "<unknow>"
159 #endif //GDCM_COMPILER_HAS_FUNCTION
162 * \brief Debug : To be used to help bug tracking developer
165 * @param msg message part
168 #define gdcmMessageBodyMacro(type, obj, msg, adds) \
170 std::ostringstream osmacro; \
171 osmacro << "In " __FILE__ ", line " << __LINE__ \
172 << ", function " << GDCM_FUNCTION << "\n" \
173 << adds << msg << "\n\n"; \
174 GDCM_NAME_SPACE::Debug::SendToOutput(type,osmacro.str(),obj);\
177 // ------------------------------------------------------------------------
180 * \brief Debug : To be used to help bug tracking developer
181 * @param obj current instance or NULL
182 * @param msg message part
185 #define gdcmDebugBodyMacro(obj, msg) {}
186 #define gdcmDebugMacro(msg) {}
187 #define gdcmStaticDebugMacro(msg) {}
189 #define gdcmDebugBodyMacro(obj, msg) \
191 if( Debug::GetDebugFlag() ) \
193 std::string adds=""; \
196 adds = "Last system error was: "; \
197 adds += strerror(errno); \
200 gdcmMessageBodyMacro(GDCM_NAME_SPACE::CMD_DEBUG,obj,msg,adds);\
203 #define gdcmDebugMacro(msg) \
204 gdcmDebugBodyMacro(NULL,msg)
205 #define gdcmStaticDebugMacro(msg) \
206 gdcmDebugBodyMacro(NULL,msg)
209 // ------------------------------------------------------------------------
212 * \brief Log : we display messages when anything is not Dicom Kosher
213 * @param obj current instance or NULL
214 * @param msg message part
216 // No NDEBUG test to always have a return of warnings !!!
217 // -> Rien compris! JPRx
218 #define gdcmLogBodyMacro(obj, msg) \
220 if( Debug::GetLogFlag() ) \
221 gdcmMessageBodyMacro(GDCM_NAME_SPACE::CMD_LOG,obj,msg,"");\
223 #define gdcmLogMacro(msg) \
224 gdcmLogBodyMacro(this,msg)
225 #define gdcmStaticLogMacro(msg) \
226 gdcmLogBodyMacro(NULL,msg)
228 // ------------------------------------------------------------------------
231 * \brief Warning : To be used to warn the user when some oddity occurs
232 * @param obj current instance or NULL
233 * @param msg message part
235 // No NDEBUG test to always have a return of warnings !!!
236 // -> Rien compris! JPRx
237 #define gdcmWarningBodyMacro(obj, msg) \
239 if( Debug::GetWarningFlag() ) \
240 gdcmMessageBodyMacro(GDCM_NAME_SPACE::CMD_WARNING,obj,msg,"");\
242 #define gdcmWarningMacro(msg) \
243 gdcmWarningBodyMacro(this,msg)
244 #define gdcmStaticWarningMacro(msg) \
245 gdcmWarningBodyMacro(NULL,msg)
247 // ------------------------------------------------------------------------
250 * \brief Error : To be used when unecoverabale error occurs
251 * at a 'deep' level. (don't use it if file is not ACR/DICOM!)
252 * @param obj current instance or NULL
253 * @param msg second message part
255 // No NDEBUG test to always have a return of errors !!!
256 // -> Rien compris! JPRx
257 #define gdcmErrorBodyMacro(obj, msg) \
259 gdcmMessageBodyMacro(GDCM_NAME_SPACE::CMD_ERROR,obj,msg,"");\
261 #define gdcmErrorMacro(msg) \
262 gdcmErrorBodyMacro(this,msg)
263 #define gdcmStaticErrorMacro(msg) \
264 gdcmErrorBodyMacro(NULL,msg)
266 // ------------------------------------------------------------------------
269 * \brief Assert : To be used when an *absolutely* impossible error occurs
270 * No function should be allowed to stop the process instead of
271 * warning the caller!
272 * @param obj current instance or NULL
273 * @param arg argument to test
274 * An easy solution to pass also a message is to do:
275 * gdcmAssertMacro( "my message" && 2 < 3 )
277 // No NDEBUG test to always have a return of asserts !!!
278 // -> Rien compris! JPRx
279 #define gdcmAssertBodyMacro(obj, arg) \
283 gdcmMessageBodyMacro(GDCM_NAME_SPACE::CMD_ASSERT,obj,"","");\
287 #define gdcmAssertMacro(msg) \
288 gdcmAssertBodyMacro(NULL,msg)
289 #define gdcmStaticAssertMacro(msg) \
290 gdcmAssertBodyMacro(NULL,msg)
292 //-----------------------------------------------------------------------------