00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef DBG_DBG_H
00020 #define DBG_DBG_H
00021
00022 #include <iosfwd>
00023 #include <exception>
00024
00025 #ifndef _MSC_VER
00026 #include <ctime>
00027 #else
00028
00029
00030 #include <time.h>
00031 #endif
00032
00033 #if defined(DBG_ENABLED) && defined(NDEBUG)
00034
00035 #endif
00036
00292 namespace dbg
00293 {
00300 const int version = 110;
00301
00302
00303
00304
00305
00325 enum level
00326 {
00327 info,
00328 warning,
00329 error,
00330 fatal,
00331 tracing,
00332 debug,
00333 none,
00334 all
00335 };
00336
00353 enum assertion_behaviour
00354 {
00355 assertions_abort,
00356 assertions_throw,
00357 assertions_continue
00358 };
00359
00379 typedef const char * dbg_source;
00380
00381
00382
00383
00384
00392 typedef const unsigned int line_no_t;
00393
00402 typedef const char * func_name_t;
00403
00411 typedef const char * file_name_t;
00412
00431 struct source_pos
00432 {
00433 line_no_t line;
00434 func_name_t func;
00435 file_name_t file;
00436 dbg_source src;
00437
00442 source_pos(line_no_t ln, func_name_t fn, file_name_t fl, dbg_source s)
00443 : line(ln), func(fn), file(fl), src(s) {}
00444
00448 source_pos()
00449 : line(0), func(0), file(0), src(0) {}
00450 };
00451
00452 #ifndef _MSC_VER
00453
00466 typedef std::clock_t dbgclock_t;
00467 #else
00468
00472 typedef clock_t dbgclock_t;
00473 #endif
00474
00475
00476
00477
00478
00487 struct dbg_exception : public std::exception
00488 {
00489 dbg_exception(const source_pos &p) : pos(p) {}
00490 const source_pos pos;
00491 };
00492
00498 struct assertion_exception : public dbg_exception
00499 {
00500 assertion_exception(const source_pos &p) : dbg_exception(p) {}
00501 };
00502
00508 struct sentinel_exception : public dbg_exception
00509 {
00510 sentinel_exception(const source_pos &p) : dbg_exception(p) {}
00511 };
00512
00518 struct unimplemented_exception : public dbg_exception
00519 {
00520 unimplemented_exception(const source_pos &p) : dbg_exception(p) {}
00521 };
00522
00528 struct check_ptr_exception : public dbg_exception
00529 {
00530 check_ptr_exception(const source_pos &p) : dbg_exception(p) {}
00531 };
00532
00533 #ifdef DBG_ENABLED
00534
00535
00536
00537
00538
00554 extern dbg_source default_source;
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566 #if defined(__GNUC__)
00567 #define DBG_FUNCTION __FUNCTION__
00568 #else
00569 #define DBG_FUNCTION 0
00570 #endif
00571
00572 #if !defined(DBG_SOURCE)
00573 #define DBG_SOURCE 0
00574 #endif
00575
00576
00577
00578
00579
00580
00581
00582 #define DBG_HERE \
00583 (::dbg::source_pos(__LINE__, DBG_FUNCTION, __FILE__, DBG_SOURCE))
00584
00585
00586
00587
00588
00616 void enable(level lvl, bool enabled);
00617
00638 void enable(level lvl, dbg_source src, bool enabled);
00639
00651 void enable_all(level lvl, bool enabled);
00652
00653
00654
00655
00656
00678 std::ostream &out(level lvl, dbg_source src);
00679
00703 inline std::ostream &out(level lvl)
00704 {
00705 return out(lvl, 0);
00706 }
00707
00729 void attach_ostream(level lvl, std::ostream &o);
00730
00742 void attach_ostream(level lvl, dbg_source src, std::ostream &o);
00743
00757 void detach_ostream(level lvl, std::ostream &o);
00758
00770 void detach_ostream(level lvl, dbg_source src, std::ostream &o);
00771
00780 void detach_all_ostreams(level lvl);
00781
00791 void detach_all_ostreams(level lvl, dbg_source src);
00792
00799 inline std::ostream &info_out()
00800 {
00801 return out(dbg::info);
00802 }
00803
00810 inline std::ostream &warning_out()
00811 {
00812 return out(dbg::warning);
00813 }
00814
00821 inline std::ostream &error_out()
00822 {
00823 return out(dbg::error);
00824 }
00825
00832 inline std::ostream &fatal_out()
00833 {
00834 return out(dbg::fatal);
00835 }
00836
00843 inline std::ostream &trace_out()
00844 {
00845 return out(dbg::tracing);
00846 }
00847
00848
00849
00850
00851
00861 void set_prefix(const char *prefix);
00862
00874 void enable_level_prefix(bool enabled);
00875
00891 void enable_time_prefix(bool enabled);
00892
00917 struct prefix
00918 {
00923 prefix() : l(none) {}
00924
00928 prefix(level lvl) : l(lvl) {}
00929
00930 level l;
00931 };
00932
00939 std::ostream &operator<<(std::ostream &s, const prefix &p);
00940
00960 struct indent
00961 {
00966 indent() : l(none) {}
00967
00971 indent(level lvl) : l(lvl) {}
00972
00973 level l;
00974 };
00975
00982 std::ostream &operator<<(std::ostream &s, const indent &i);
00983
01004 std::ostream &operator<<(std::ostream &s, const source_pos &pos);
01005
01006
01007
01008
01009
01030 void set_assertion_behaviour(level lvl, assertion_behaviour behaviour);
01031
01080 void set_assertion_period(dbgclock_t period);
01081
01082
01083
01084
01085
01095 struct assert_info : public source_pos
01096 {
01097 bool asserted;
01098 const char *text;
01099
01105 assert_info(bool a, const char *t,
01106 line_no_t line, func_name_t func,
01107 file_name_t file, dbg_source spos)
01108 : source_pos(line, func, file, spos), asserted(a), text(t) {}
01109
01115 assert_info(bool a, const char *b, const source_pos &sp)
01116 : source_pos(sp), asserted(a), text(b) {}
01117 };
01118
01119
01120
01121
01122
01123 #define DBG_STRING(a) #a
01124
01125
01126
01127
01128
01129
01130
01131 #define DBG_ASSERTION(a) \
01132 ::dbg::assert_info(a, DBG_STRING(a), DBG_HERE)
01133
01164 void assertion(level lvl, dbg_source src, const assert_info &ai);
01165
01173 inline void assertion(level lvl, const assert_info &ai)
01174 {
01175 assertion(lvl, 0, ai);
01176 }
01177
01185 inline void assertion(dbg_source src, const assert_info &ai)
01186 {
01187 assertion(warning, src, ai);
01188 }
01189
01196 inline void assertion(const assert_info &ai)
01197 {
01198 assertion(warning, 0, ai);
01199 }
01200
01201
01202
01203
01204
01224 void sentinel(level lvl, dbg_source src, const source_pos &here);
01225
01233 inline void sentinel(level lvl, const source_pos &here)
01234 {
01235 sentinel(lvl, 0, here);
01236 }
01237
01245 inline void sentinel(dbg_source src, const source_pos &here)
01246 {
01247 sentinel(warning, src, here);
01248 }
01249
01256 inline void sentinel(const source_pos &here)
01257 {
01258 sentinel(warning, 0, here);
01259 }
01260
01261
01262
01263
01264
01291 void unimplemented(level lvl, dbg_source src, const source_pos &here);
01292
01300 inline void unimplemented(level lvl, const source_pos &here)
01301 {
01302 unimplemented(lvl, 0, here);
01303 }
01304
01312 inline void unimplemented(dbg_source src, const source_pos &here)
01313 {
01314 unimplemented(warning, src, here);
01315 }
01316
01323 inline void unimplemented(const source_pos &here)
01324 {
01325 unimplemented(warning, 0, here);
01326 }
01327
01328
01329
01330
01331
01349 void check_ptr(level lvl, dbg_source src, const void *p, const source_pos &here);
01350
01359 inline void check_ptr(level lvl, const void *p, const source_pos &here)
01360 {
01361 check_ptr(lvl, 0, p, here);
01362 }
01363
01372 inline void check_ptr(dbg_source src, const void *p, const source_pos &here)
01373 {
01374 check_ptr(warning, src, p, here);
01375 }
01376
01384 inline void check_ptr(const void *p, const source_pos &here)
01385 {
01386 check_ptr(warning, 0, p, here);
01387 }
01388
01389
01390
01391
01392
01404 template <class T>
01405 inline unsigned int array_size(T &array)
01406 {
01407 return sizeof(array)/sizeof(array[0]);
01408 }
01409
01424 void check_bounds(level lvl, dbg_source src,
01425 int index, int bound, const source_pos &here);
01442 inline void check_bounds(level lvl, dbg_source src,
01443 int index, int minbound, int maxbound,
01444 const source_pos &here)
01445 {
01446 check_bounds(lvl, src, index-minbound, maxbound, here);
01447 }
01448
01467 template <class T>
01468 void check_bounds(level lvl, dbg_source src,
01469 int index, T &array, const source_pos &here)
01470 {
01471 check_bounds(lvl, src, index, array_size(array), here);
01472 }
01473
01483 template <class T>
01484 void check_bounds(level lvl, int index, T &array, const source_pos &here)
01485 {
01486 check_bounds(lvl, 0, index, array_size(array), here);
01487 }
01488
01498 template <class T>
01499 void check_bounds(dbg_source src, int index, T &array,
01500 const source_pos &here)
01501 {
01502 check_bounds(warning, src, index, array_size(array), here);
01503 }
01504
01513 template <class T>
01514 void check_bounds(int index, T &array, const source_pos &here)
01515 {
01516 check_bounds(warning, 0, index, array_size(array), here);
01517 }
01518
01519
01520
01521
01522
01581 class trace
01582 {
01583 public:
01584
01593 trace(func_name_t name);
01594
01599 trace(dbg_source src, func_name_t name);
01600
01607 trace(const source_pos &here);
01608
01613 trace(dbg_source src, const source_pos &here);
01614
01615 ~trace();
01616
01617 private:
01618
01619 trace(const trace &);
01620 trace &operator=(const trace &);
01621
01622 void trace_begin();
01623 void trace_end();
01624
01625 dbg_source m_src;
01626 const char *m_name;
01627 const source_pos m_pos;
01628 bool m_triggered;
01629 };
01630
01631
01632
01633
01634
01690 template <class obj_t>
01691 class post_mem_fun
01692 {
01693 public:
01694
01699 typedef bool (obj_t::*fn_t)();
01700
01707 post_mem_fun(level lvl, obj_t *obj, fn_t fn, const source_pos &pos)
01708 : m_lvl(lvl), m_src(0), m_obj(obj), m_fn(fn), m_pos(pos) {}
01709
01717 post_mem_fun(level lvl, dbg_source src,
01718 obj_t *obj, fn_t fn, const source_pos &pos)
01719 : m_lvl(lvl), m_src(src), m_obj(obj), m_fn(fn), m_pos(pos) {}
01720
01729 post_mem_fun(obj_t *obj, fn_t fn, const source_pos &pos)
01730 : m_lvl(dbg::warning), m_src(0),
01731 m_obj(obj), m_fn(fn), m_pos(pos) {}
01732
01742 post_mem_fun(dbg_source src, obj_t *obj, fn_t fn,
01743 const source_pos &pos)
01744 : m_lvl(dbg::warning), m_src(src),
01745 m_obj(obj), m_fn(fn), m_pos(pos) {}
01746
01750 ~post_mem_fun()
01751 {
01752 assertion(m_lvl, m_src,
01753 assert_info((m_obj->*m_fn)(), "post condition",
01754 m_pos.line, m_pos.func, m_pos.file, m_pos.src));
01755 }
01756
01757 private:
01758
01759 const level m_lvl;
01760 const dbg_source m_src;
01761 obj_t *m_obj;
01762 fn_t m_fn;
01763 const source_pos m_pos;
01764 };
01765
01777 class post
01778 {
01779 public:
01780
01785 typedef bool (*fn_t)();
01786
01792 post(level lvl, fn_t fn, const source_pos &pos)
01793 : m_lvl(lvl), m_src(0), m_fn(fn), m_pos(pos) {}
01794
01801 post(level lvl, dbg_source src, fn_t fn, const source_pos &pos)
01802 : m_lvl(lvl), m_src(src), m_fn(fn), m_pos(pos) {}
01803
01811 post(fn_t fn, const source_pos &pos)
01812 : m_lvl(dbg::warning), m_src(0), m_fn(fn), m_pos(pos) {}
01813
01822 post(dbg_source src, fn_t fn, const source_pos &pos)
01823 : m_lvl(dbg::warning), m_src(src), m_fn(fn), m_pos(pos) {}
01824
01828 ~post()
01829 {
01830 assertion(m_lvl, m_src,
01831 assert_info(m_fn(), "post condition",
01832 m_pos.line, m_pos.func, m_pos.file, m_pos.src));
01833 }
01834
01835 private:
01836
01837 level m_lvl;
01838 const dbg_source m_src;
01839 fn_t m_fn;
01840 const source_pos m_pos;
01841 };
01842
01843
01844
01845
01846
01866 template <bool expression>
01867 class compile_assertion;
01868 template <>
01869 class compile_assertion<true> {};
01870
01871 #else
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885 #define DBG_HERE ((void*)0)
01886 #define DBG_ASSERTION(a) ((void*)0)
01887
01888
01889 const dbg_source default_source = 0;
01890
01897 class null_stream
01898 {
01899 public:
01900 #ifdef _MSC_VER
01901 null_stream &operator<<(void *) { return *this; }
01902 null_stream &operator<<(const void *) { return *this; }
01903 null_stream &operator<<(long) { return *this; }
01904 #else
01905 template <class otype>
01906 null_stream &operator<<(const otype &) { return *this; }
01907 #endif
01908
01909 template <class otype>
01910 null_stream &operator<<(otype &) { return *this; }
01911 null_stream &operator<<(std::ostream& (*)(std::ostream&))
01912 {
01913 return *this;
01914 }
01915 };
01916
01917 struct prefix { prefix() {} prefix(level) {} };
01918 struct indent { indent() {} indent(level) {} };
01919
01920 inline void enable(level, bool) {}
01921 inline void enable(level, dbg_source, bool) {}
01922 inline void enable_all(level, bool) {}
01923 inline null_stream out(level, dbg_source) {return null_stream();}
01924 inline null_stream out(level) {return null_stream();}
01925 inline void attach_ostream(level, std::ostream &) {}
01926 inline void attach_ostream(level, dbg_source, std::ostream &) {}
01927 inline void detach_ostream(level, std::ostream &) {}
01928 inline void detach_ostream(level, dbg_source, std::ostream &) {}
01929 inline void detach_all_ostreams(level) {}
01930 inline void detach_all_ostreams(level, dbg_source) {}
01931 inline null_stream info_out() {return null_stream();}
01932 inline null_stream warning_out() {return null_stream();}
01933 inline null_stream error_out() {return null_stream();}
01934 inline null_stream fatal_out() {return null_stream();}
01935 inline null_stream trace_out() {return null_stream();}
01936 inline void set_prefix(const char *) {}
01937 inline void enable_level_prefix(bool) {}
01938 inline void enable_time_prefix(bool) {}
01939
01940 inline void set_assertion_behaviour(level, assertion_behaviour) {}
01941 inline void set_assertion_period(dbgclock_t) {}
01942 inline void assertion(level, dbg_source, void *) {}
01943 inline void assertion(level, void *) {}
01944 inline void assertion(dbg_source, void *) {}
01945 inline void assertion(void *) {}
01946 inline void sentinel(level, dbg_source, void *) {}
01947 inline void sentinel(level, void *) {}
01948 inline void sentinel(dbg_source, void *) {}
01949 inline void sentinel(void *) {}
01950 inline void unimplemented(level, dbg_source, void *) {}
01951 inline void unimplemented(level, void *) {}
01952 inline void unimplemented(dbg_source, void *) {}
01953 inline void unimplemented(void *) {}
01954 inline void check_ptr(level, dbg_source, const void *, void *) {}
01955 inline void check_ptr(level, const void *, void *) {}
01956 inline void check_ptr(dbg_source, const void *, void *) {}
01957 inline void check_ptr(const void *, void *) {}
01958 inline void check_bounds(level, void *, int, int, void *) {}
01959 inline void check_bounds(level, dbg_source, int, void*, void*) {}
01960 inline void check_bounds(level, dbg_source, int, int,
01961 void *, void *) {}
01962 inline void check_bounds(level, int, void *, void*) {}
01963 inline void check_bounds(void *, int, void *, void *) {}
01964 inline void check_bounds(int, void *, void *) {}
01965
01966 class trace
01967 {
01968 public:
01969 trace(const char *fn_name) {}
01970 trace(dbg_source, const char *fn_name) {}
01971 trace(void *here) {}
01972 trace(dbg_source, void *here) {}
01973 ~trace() {}
01974 };
01975
01976 template <class obj_t>
01977 class post_mem_fun
01978 {
01979 public:
01980 typedef bool (obj_t::*fn_t)();
01981 post_mem_fun(level, void *, fn_t, void *) {}
01982 post_mem_fun(level, dbg_source, void *, fn_t, void *) {}
01983 post_mem_fun(void *, fn_t, void *) {}
01984 post_mem_fun(dbg_source, void *, fn_t, void *) {}
01985 ~post_mem_fun() {}
01986 };
01987 class post
01988 {
01989 public:
01990 typedef bool(*fn_t)();
01991 post(level, fn_t, void *) {}
01992 post(level, dbg_source, fn_t, void *) {}
01993 post(fn_t, void *) {}
01994 post(dbg_source, fn_t, void *) {}
01995 ~post() {}
01996 };
01997
01998 template <bool expression>
01999 class compile_assertion {};
02000
02001 #endif
02002 }
02003
02004 #endif