Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Debug.hh
1 /*
2 This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4 Copyright (C) 2003-2009 (see file CONTACT for details)
5  Multimediale Systeme der Informationsverarbeitung
6  Institut fuer Informatik
7  Christian-Albrechts-Universitaet Kiel
8 
9 
10 BIAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14 
15 BIAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with BIAS; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24 
25 
26 #ifndef __BIASDEBUG_HH__
27 #define __BIASDEBUG_HH__
28 
29 #include <bias_config.h>
30 
31 #if defined WIN32 && defined(_DLL)
32 //# include <Base/Common/BIASpragmaStart.hh> // for DLL build
33 #pragma warning(push)
34 #pragma warning(disable: 4251) // disable only STL DLL linking warning noise
35 #endif
36 
37 #include <iostream>
38 #include <iomanip>
39 #include <string>
40 #include <cstdio>
41 #include <cstdlib>
42 #include <map>
43 #include <limits>
44 #include <typeinfo>
45 #ifdef __APPLE__
46 # include <math.h>
47 #endif // __APPLE__
48 
49 /** \ingroup g_utils
50  \file Debug.hh
51  \brief some macros, classes and varaibles for debugging purposes:
52 
53  The class variables _liDebugLevel and _zDebugStream
54  must exist for the macros to operate. Usually they are inherited
55  from the Debug class defined below
56 
57  _liDebuglevel is a bitfield. It is set to 0 in the constr. of Debug
58  The bits should be addressed via a #define macros from the header file
59  of the acording class.
60 
61  _zDebugStream is a ostream. It is set to cerr in the constructor of
62  Debug
63 
64  BIASDOUT(flag, stream)
65  prints stream to cerr if flag is set in _liDebuglevel
66 
67  BIASDOUT_THREAD is the aequivalent to BIASDOUT for the use within a thread
68 
69  BIASGDOUT(level, stream)
70  prints out debug information if BIASGlobalDebugLevel is greater than
71  level. It can only be used together with the global debug level.
72 
73  The global debuglevel variable 'BIASGlobalDebugLevel' is defined in
74  MainDebug.hh. It should be included only in the application.
75 
76  The global debug level 'BIASGlobalDebugLevel' should be defined in every
77  executable via the include of <Debug/MainDebug.hh>.
78 
79  A function ResetDebugLevelFromGlobal() can be implemented in classes that
80  need it. See Examples...
81 
82  An exhaustive example exists.
83 
84  \author Felix Woelk
85 **/
86 
87 
88 
89 #ifdef BIAS_DEBUG
90 
91 
92 #define BIASDOUT(flag, arg)\
93  { if ((this->_liDebugLevel & flag)!=0){\
94  std::ostream _cods_(std::cout.rdbuf()); \
95  this->GetDebugStream(_cods_); _cods_ << #flag << ", " << __FILE__ \
96  << ", " << __LINE__ << " : " << arg << std::endl; } }
97 
98 #define BIASFLUSHDOUT \
99  { std::ostream _cods_(std::cout.rdbuf()); \
100  this->GetDebugStream(_cods_); _cods_.flush(); }
101 
102 #define BIASDOUT_THREAD(debuglevel, debugstream, flag, arg)\
103  if ((debuglevel & flag)!=0)\
104  debugstream << #flag << ", " << __FILE__ << ", " << __LINE__ << " : "\
105  << arg << std::endl;
106 
107 #define BIASGDOUT(level, arg)\
108  if (Debug::GlobalDebugLevel >= level)\
109  std::cerr << arg << std::endl;
110 
111 #define BIASDOUT_CLEAN(flag, arg)\
112  { if ((this->_liDebugLevel & flag)!=0){\
113  std::ostream _cods_(std::cout.rdbuf()); \
114  this->GetDebugStream(_cods_); _cods_ << arg << std::endl; } }
115 
116 #define BIASCDOUT(flag, arg)\
117  { if ((this->_liDebugLevel & flag)!=0){\
118  std::ostream _cods_(std::cout.rdbuf()); \
119  this->GetDebugStream(_cods_); _cods_ << arg; } }
120 
121 #define BCDOUT(name, arg)\
122  { if ( (this->_liDebugLevel & Debug::Name2DebugLevel(#name) ) !=0 ){\
123  std::ostream _cods_(std::cout.rdbuf()); \
124  this->GetDebugStream(_cods_); _cods_ << arg; } }
125 # ifdef __APPLE__
126 # define INFNANCHECK(a) { if (BIAS_ISNAN(a) || BIAS_ISINF(a)){\
127  std::cout << __FILE__<<":"<<__LINE__ << " "<<#a<<" = "<<a<<std::endl; \
128  assert(!BIAS_ISNAN(a) && !BIAS_ISINF(a));\
129  } }
130 # else // __APPLE__
131 # define INFNANCHECK(a) { if (BIAS_ISNAN(a) || BIAS_ISINF(a)){\
132  std::cout << __FILE__<<":"<<__LINE__ << " "<<#a<<" = "<<a<<std::endl; \
133  assert(!BIAS_ISNAN(a) && !BIAS_ISINF(a));\
134  } }
135 # endif // __APPLE__
136 
137 #else
138 
139 #define BIASDOUT_CLEAN(flag, arg) {}
140 #define BIASDOUT(flag, arg) {}
141 #define BIASFLUSHDOUT {}
142 #define BIASDOUT_THREAD(debuglevel, debugstream, flag, arg) {}
143 #define BIASGDOUT(level, arg) {}
144 #define BIASCDOUT(flag, arg) {}
145 #define BCDOUT(name, arg) {}
146 #define INFNANCHECK(a) {}
147 
148 #endif // BIAS_DEBUG
149 
150 
151 // TODO: Please use BIASABORT instead!
152 #ifdef WIN32
153 #define ABORT std::cout << "Please hit enter to terminate program!" << std::endl << std::flush; \
154  getchar(); \
155  exit(-1);
156 #else
157 #define ABORT abort();
158 #endif
159 
160 
161 /// this returns the type as a string, e.g. PRINTTYPE(int) -> "int"
162 /// useful when debugging templates
163 /// on WIN32 this can be done more pretty with typeid( *ptr ).name() (jw)
164 #define PRINTTYPE(thetype) (\
165  (typeid(thetype)==typeid(char))? "char": \
166  (typeid(thetype)==typeid(signed char))?"signed char":\
167  (typeid(thetype)==typeid(unsigned char))?"unsigned char":\
168  (typeid(thetype)==typeid(short))? "short": \
169  (typeid(thetype)==typeid(signed short))? "signed short": \
170  (typeid(thetype)==typeid(unsigned short))?"unsigned short":\
171  (typeid(thetype)==typeid(int))? "int":\
172  (typeid(thetype)==typeid(unsigned int))?"unsigned int":\
173  (typeid(thetype)==typeid(signed int))?"signed int":\
174  (typeid(thetype)==typeid(double))?"double":\
175  (typeid(thetype)==typeid(float))?"float":\
176  (typeid(thetype)==typeid(long))?"long":\
177  "UnknownStorageType")
178 
179 
180 namespace BIAS{
181 
182  /* this variable os the global debuglevel and should be defined in
183  every executable via include of <Debug/MainDebug.hh> */
184  //extern long int GlobalDebugLevel;
185 
186 
187  /** \class Debug
188  \ingroup g_utils
189  \file Debug.hh
190  \brief some macros, classes and varaibles for debugging purposes
191  if a class is derived from Debug, then use BIASDOUT() instead of
192  cerr/cout for debugging purposes
193 
194  father of many classed to includes flags based debug information
195 
196  The class variables _liDebugLevel and _zDebugStream
197  must exist for the macros to operate. Usually they are inherited
198  from the Debug class defined below
199 
200  _liDebuglevel is a bitfield. It is set to 0 in the constr. of Debug
201  The bits should be addressed via a #define macros from the header file
202  of the acording class.
203 
204  _zDebugStream is a ostream. It is set to cerr in the constructor of
205  Debug
206 
207  - BIASDOUT(flag, stream)
208  prints stream to cerr if flag is set in _liDebuglevel
209 
210  - BIASDOUT_THREAD is the aequivalent to BIASDOUT for the use within a thread
211  - BIASGDOUT(level, stream)
212  prints out debug information if BIASGlobalDebugLevel is greater than
213  level. It can only be used together with the global debug level.
214 
215  - BIASDOUT_CLEAN(flag, stream)
216  is similar to BIASDOUT except that no flag,file and line is printed
217 
218 
219  The global debuglevel variable 'BIASGlobalDebugLevel' is defined in
220  Debug.cpp.
221 
222  A function ResetDebugLevelFromGlobal() can be implemented in classes that
223  need it. See Examples...
224 
225  An exhaustive example exists.
226 
227  New debuglevel concept avoids the proble of multiple debuglevel
228  definitions:
229 
230  Pros:
231  - each class keeps tracks of available debuglevels itself
232  - class inherits knowledge about debuglevel from parents
233  - class can print all available debuglevels
234  - inhibits double definition of debuglevels in inheritance hirarchy
235  Cons:
236  - slower (map lookup)
237  - when using a unknown debuglevel, no compile time error is produced
238  (only a runtime error)
239 
240  Usage Summary:
241  - call NewDebugLevel("name") for creation of debuglevel in class
242  constructor
243  (replaces old #define name 0x00001)
244  - use macro BCDOUT(name, "my error message"<<endl) in class
245  (replaces old BIASCDOUT(name, ""))
246  - for enabling debug output call AddDebugLevel("name") or
247  SetDebugLevel("name")
248  (replaces old SetDebugLevel(name) and AddDebugLevel(name) )
249 
250  Problem Example:
251 
252  // file father.hh
253  #define DL_FATHER 0x1
254  class father{
255  foo(){ BIASCDOUT(DL_FATHER, "bla");}
256  };
257  // file child.hh
258  #include "father.hh"
259  #define DL_CHILD 0x1
260  class child : public father
261  {
262  foo2(){ foo(); BIASCDOUT(DL_CHILD, "fasel"); }
263  };
264 
265  calling
266  child.SetDebugLevel(DL_CHILD);
267  child.foo2();
268 
269  results in the unexpected additional debug output "bla".
270 
271 
272 
273  To avoid this use new debugconcept:
274 
275  // file father.hh
276  class father{
277  father() { NewDebugLevel("DL_FATHER"); }
278  foo(){ BIASCDOUT(DL_FATHER, "bla");}
279  };
280 
281  // file child.hh
282  #include "father.hh"
283  class child : public father
284  {
285  child() : father() { NewDebugLevel("DL_CHILD"); }
286  foo2(){ foo(); BIASCDOUT(DL_CHILD, "fasel"); }
287  };
288 
289  calling
290  child.SetDebugLevel("DL_CHILD");
291  child.foo2();
292 
293  results in the only in the debug output "fasel".
294 
295  \author Felix Woelk
296  **/
297 
298  class BIASDebug_EXPORT Debug {
299 
300  public:
301  inline Debug()
302  {
303 #ifdef BIAS_DEBUG
304  _liDebugLevel = 0;
305  _liNextDebugLevel = 1;
306 #endif
307  };
308 
309  inline Debug(const Debug& deb)
310  {
311 #ifdef BIAS_DEBUG
312  *this = deb;
313 #endif
314  }
315 
316  inline ~Debug() {};
317 
318  inline void SetDebugLevel(const long int lv)
319  {
320 #ifdef BIAS_DEBUG
321  _liDebugLevel = lv;
322 #endif
323  };
324 
325  inline void SetDebugLevel(const std::string &name)
326  {
327 #ifdef BIAS_DEBUG
328  SetDebugLevel(Name2DebugLevel(name));
329 #endif
330  };
331 
332  inline int GetDebugLevel() const
333  {
334 #ifdef BIAS_DEBUG
335  return _liDebugLevel;
336 #else
337  return 0;
338 #endif
339  };
340 
341  inline bool DebugLevelIsSet(const long int lv) const
342  {
343 #ifdef BIAS_DEBUG
344  return ((_liDebugLevel & lv)!=0);
345 #else
346  return false;
347 #endif
348  };
349 
350  inline bool DebugLevelIsSet(const std::string& name) const
351  {
352  return DebugLevelIsSet(Name2DebugLevel(name));
353  };
354 
355  inline void AddDebugLevel(const long int lv)
356  {
357 #ifdef BIAS_DEBUG
358  _liDebugLevel = _liDebugLevel | lv;
359 #endif
360  };
361 
362  inline void AddDebugLevel(const std::string& name)
363  {
364 #ifdef BIAS_DEBUG
365  AddDebugLevel(Name2DebugLevel(name));
366 #endif
367  };
368 
369  inline void RemoveDebugLevel(const long int lv)
370  {
371 #ifdef BIAS_DEBUG
372  _liDebugLevel = _liDebugLevel & (~lv);
373 #endif
374  };
375 
376  inline void RemoveDebugLevel(const std::string& name)
377  {
378 #ifdef BIAS_DEBUG
379  RemoveDebugLevel(Name2DebugLevel(name));
380 #endif
381  };
382 
383  inline void PrintDebugLevel(std::ostream& os=std::cout) const
384  {
385 #ifdef BIAS_DEBUG
386 #define WS sizeof(long int)*8
387  os << "0x" << std::hex << std::setw(sizeof(long int)<<1)
388  << std::setfill('0') << GetDebugLevel() << std::dec << " = ";
389  for (unsigned i=1; i<=WS; i++){
390  os << !!((1<<(WS-i))&GetDebugLevel());
391  if ((i%4)==0) os << " ";
392  if ((i%8)==0) os << " ";
393  }
394  os << std::endl;
395 #endif
396  }
397 
398  inline void SetDebugStream(const std::ostream& os)
399  {
400 #ifdef BIAS_DEBUG
401  _zDebugStream.rdbuf(os.rdbuf());
402 #endif
403  }
404 
405  inline std::ostream& GetDebugStream() const
406  {
407 #ifdef BIAS_DEBUG
408  return _zDebugStream;
409 #else
410  return std::cout;
411 #endif
412  }
413 
414  inline void GetDebugStream(std::ostream& os) const
415  {
416 #ifdef BIAS_DEBUG
417 
418  os.rdbuf(_zDebugStream.rdbuf());
419 #else
420  os.rdbuf(std::cout.rdbuf());
421 #endif
422  }
423 
424  inline static void SetGlobalDebugLevel(long int lev)
425  {
426 #ifdef BIAS_DEBUG
427  GlobalDebugLevel = lev;
428 #endif
429  }
430 
431  inline static long int GetGlobalDebugLevel()
432  {
433 #ifdef BIAS_DEBUG
434  return GlobalDebugLevel;
435 #else
436  return 0;
437 #endif
438  }
439 
440  inline Debug& operator=(const Debug& deb)
441  {
442 #ifdef BIAS_DEBUG
443  _liDebugLevel = deb._liDebugLevel;
444  _zDebugStream.rdbuf(deb._zDebugStream.rdbuf());
445  _liNextDebugLevel = deb._liNextDebugLevel;
446  _String2Debuglevel = deb._String2Debuglevel;
447 #endif
448  return *this;
449  }
450 
451  /** looks up a debuglevel in the internal map,
452  returns 0 if not found
453  @author woelk 09/2006 */
454  inline long int Name2DebugLevel(const std::string& name) const
455  {
456 #ifdef BIAS_DEBUG
457  std::map<std::string, long int>::const_iterator it =
458  _String2Debuglevel.find(name);
459  if (it == _String2Debuglevel.end()){
460  std::cerr << "Debuglevel \""<<name<<"\" is unknown. Please use one "
461  <<"of the following: \n";
462  ShowDebugLevel(std::cerr);
463  std::cerr << "\n\n\n";
464  return 0;
465  }
466  return it->second;
467 #else
468  return 0;
469 #endif
470  }
471 
472  /** creates a new debuglevel
473  @author woelk 09/2006 */
474  inline long int NewDebugLevel(const std::string& name)
475  {
476 #ifdef BIAS_DEBUG
477  long int res = ConsumeNextFreeDebuglevel_();
478  std::map<std::string, long int>::iterator it
479  = _String2Debuglevel.find(name);
480  if (it != _String2Debuglevel.end()){
481  std::cerr << "debuglevel with name \""<<name<<"\" does already exist, "
482  <<"please choose a different name!\n\n\n";
483  ABORT;
484  } else {
485  _String2Debuglevel.insert(make_pair(name, res));
486  /* ShowDebugLevel(std::cerr); */
487  }
488  return res;
489 #else
490  return 0;
491 #endif
492  }
493 
494  /** @brief prints all internally known debuglevels
495  @author woelk 09/2006 */
496  inline void ShowDebugLevel(std::ostream& os = std::cout) const
497  {
498 #ifdef BIAS_DEBUG
499  std::map<std::string, long int>::const_iterator it;
500  for (it = _String2Debuglevel.begin();
501  it != _String2Debuglevel.end(); it++){
502  os << " 0x"<<std::hex<<it->second<<" : "
503  <<it->first<<std::dec<<std::endl;
504  }
505 #endif
506  }
507 
508  protected:
509 #ifdef BIAS_DEBUG
510  long int _liDebugLevel;
511  static std::ostream _zDebugStream;
512 
513  static long int GlobalDebugLevel;
514 
515  /// new concept, debuglevel are managed here in the debug class
517  std::map<std::string, long int> _String2Debuglevel;
518 
519  /** @brief returns the next available debuglevel
520  @author woelk 09/2006 */
522  long dl = _liNextDebugLevel;
523  //if ((long)_liNextDebugLevel == (long)(std::numeric_limits<long>::max())) // FIXME, max redef.
524  if ((long)_liNextDebugLevel > (long)(1<<30)) // workaround
525  {
526  std::cerr << "maximum number of debuglevels reached\n";
527  ABORT;
528  }
529  _liNextDebugLevel = _liNextDebugLevel<<1;
530  return dl;
531  }
532 #endif
533 
534 #ifdef WIN32
535  static int dummy_; //< export something to avoid conditional Win32 Release exports
536 #endif
537  };
538 } // namespace
539 
540 
541 #if defined WIN32 && defined(_DLL)
542 //# include <Base/Common/BIASpragmaEnd.hh> // for DLL build
543 #pragma warning(pop)
544 #endif
545 
546 
547 #endif // __BIASDEBUG_HH__
static long int GetGlobalDebugLevel()
Definition: Debug.hh:431
void SetDebugLevel(const std::string &name)
Definition: Debug.hh:325
void AddDebugLevel(const long int lv)
Definition: Debug.hh:355
void AddDebugLevel(const std::string &name)
Definition: Debug.hh:362
Debug(const Debug &deb)
Definition: Debug.hh:309
long ConsumeNextFreeDebuglevel_()
returns the next available debuglevel
Definition: Debug.hh:521
int GetDebugLevel() const
Definition: Debug.hh:332
Debug & operator=(const Debug &deb)
Definition: Debug.hh:440
void PrintDebugLevel(std::ostream &os=std::cout) const
Definition: Debug.hh:383
bool DebugLevelIsSet(const long int lv) const
Definition: Debug.hh:341
long int _liNextDebugLevel
new concept, debuglevel are managed here in the debug class
Definition: Debug.hh:516
bool DebugLevelIsSet(const std::string &name) const
Definition: Debug.hh:350
long int Name2DebugLevel(const std::string &name) const
looks up a debuglevel in the internal map, returns 0 if not found
Definition: Debug.hh:454
void RemoveDebugLevel(const std::string &name)
Definition: Debug.hh:376
void SetDebugLevel(const long int lv)
Definition: Debug.hh:318
long int NewDebugLevel(const std::string &name)
creates a new debuglevel
Definition: Debug.hh:474
long int _liDebugLevel
Definition: Debug.hh:510
std::map< std::string, long int > _String2Debuglevel
Definition: Debug.hh:517
static long int GlobalDebugLevel
Definition: Debug.hh:513
void ShowDebugLevel(std::ostream &os=std::cout) const
prints all internally known debuglevels
Definition: Debug.hh:496
void GetDebugStream(std::ostream &os) const
Definition: Debug.hh:414
std::ostream & GetDebugStream() const
Definition: Debug.hh:405
static std::ostream _zDebugStream
Definition: Debug.hh:511
void RemoveDebugLevel(const long int lv)
Definition: Debug.hh:369
static void SetGlobalDebugLevel(long int lev)
Definition: Debug.hh:424
void SetDebugStream(const std::ostream &os)
Definition: Debug.hh:398