Panda3D
|
00001 // Filename: pnotify.h 00002 // Created by: drose (28Feb00) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #ifndef NOTIFY_H 00016 #define NOTIFY_H 00017 00018 #include "dtoolbase.h" 00019 #include "notifySeverity.h" 00020 #include <map> 00021 00022 class NotifyCategory; 00023 00024 //////////////////////////////////////////////////////////////////// 00025 // Class : Notify 00026 // Description : An object that handles general error reporting to the 00027 // user. It contains a pointer to an ostream, initially 00028 // cerr, which can be reset at will to point to 00029 // different output devices, according to the needs of 00030 // the application. All output generated within Panda 00031 // should vector through the Notify ostream. 00032 // 00033 // This also includes a collection of Categories and 00034 // Severities, which may be independently enabled or 00035 // disabled, so that error messages may be squelched or 00036 // respected according to the wishes of the user. 00037 //////////////////////////////////////////////////////////////////// 00038 class EXPCL_DTOOLCONFIG Notify { 00039 PUBLISHED: 00040 Notify(); 00041 ~Notify(); 00042 00043 void set_ostream_ptr(ostream *ostream_ptr, bool delete_later); 00044 ostream *get_ostream_ptr() const; 00045 00046 typedef bool AssertHandler(const char *expression, int line, 00047 const char *source_file); 00048 00049 void set_assert_handler(AssertHandler *assert_handler); 00050 void clear_assert_handler(); 00051 bool has_assert_handler() const; 00052 AssertHandler *get_assert_handler() const; 00053 00054 bool has_assert_failed() const; 00055 const string &get_assert_error_message() const; 00056 void clear_assert_failed(); 00057 00058 NotifyCategory *get_top_category(); 00059 NotifyCategory *get_category(const string &basename, 00060 NotifyCategory *parent_category); 00061 NotifyCategory *get_category(const string &basename, 00062 const string &parent_fullname); 00063 NotifyCategory *get_category(const string &fullname); 00064 00065 static ostream &out(); 00066 static ostream &null(); 00067 static void write_string(const string &str); 00068 static Notify *ptr(); 00069 00070 public: 00071 static ios_fmtflags get_literal_flag(); 00072 00073 bool assert_failure(const string &expression, int line, 00074 const char *source_file); 00075 bool assert_failure(const char *expression, int line, 00076 const char *source_file); 00077 00078 static NotifySeverity string_severity(const string &string); 00079 00080 void config_initialized(); 00081 00082 private: 00083 ostream *_ostream_ptr; 00084 bool _owns_ostream_ptr; 00085 ostream *_null_ostream_ptr; 00086 00087 AssertHandler *_assert_handler; 00088 bool _assert_failed; 00089 string _assert_error_message; 00090 00091 // This shouldn't be a pmap, since it might be invoked before we 00092 // initialize the global malloc pointers. 00093 typedef map<string, NotifyCategory *> Categories; 00094 Categories _categories; 00095 00096 static Notify *_global_ptr; 00097 }; 00098 00099 00100 // This defines the symbol nout in the same way that cerr and cout are 00101 // defined, for compactness of C++ code that uses Notify in its 00102 // simplest form. Maybe it's a good idea to define this symbol and 00103 // maybe it's not, but it does seem that "nout" isn't likely to 00104 // collide with any other name. 00105 00106 #define nout (Notify::out()) 00107 00108 // Here are a couple of assert-type functions. These are designed to 00109 // avoid simply dumping core, since that's quite troublesome when the 00110 // programmer is working in a higher-level environment that is calling 00111 // into the C++ layer. 00112 00113 // nassertr() is intended to be used in functions that have return 00114 // values; it returns the indicated value if the assertion fails. 00115 00116 // nassertv() is intended to be used in functions that do not have 00117 // return values; it simply returns if the assertion fails. 00118 00119 // nassertd() does not return from the function, but instead executes 00120 // the following block of code (like an if statement) if the assertion 00121 // fails. 00122 00123 // nassertr_always() and nassertv_always() are like nassertr() and 00124 // nassertv(), except that they will not get completely compiled out 00125 // if NDEBUG is set. Instead, they will quietly return from the 00126 // function. These macros are appropriate, for instance, for sanity 00127 // checking user input parameters, where optimal performance is not 00128 // paramount. 00129 00130 #ifdef NDEBUG 00131 00132 #define nassertr(condition, return_value) 00133 #define nassertv(condition) 00134 #define nassertd(condition) if (false) 00135 // We trust the compiler to optimize the above out. 00136 00137 #define nassertr_always(condition, return_value) \ 00138 { \ 00139 if (!(condition)) { \ 00140 return return_value; \ 00141 } \ 00142 } 00143 00144 #define nassertv_always(condition) \ 00145 { \ 00146 if (!(condition)) { \ 00147 return; \ 00148 } \ 00149 } 00150 00151 #define nassert_raise(message) Notify::write_string(message) 00152 00153 #define enter_debugger_if(condition) ((void)0) 00154 00155 #else // NDEBUG 00156 00157 #define nassertr(condition, return_value) \ 00158 { \ 00159 if (!(condition)) { \ 00160 if (Notify::ptr()->assert_failure(#condition, __LINE__, __FILE__)) { \ 00161 return return_value; \ 00162 } \ 00163 } \ 00164 } 00165 00166 #define nassertv(condition) \ 00167 { \ 00168 if (!(condition)) { \ 00169 if (Notify::ptr()->assert_failure(#condition, __LINE__, __FILE__)) { \ 00170 return; \ 00171 } \ 00172 } \ 00173 } 00174 00175 #define nassertd(condition) \ 00176 if (!(condition) && \ 00177 Notify::ptr()->assert_failure(#condition, __LINE__, __FILE__)) 00178 00179 #define nassertr_always(condition, return_value) nassertr(condition, return_value) 00180 #define nassertv_always(condition) nassertv(condition) 00181 00182 #define nassert_raise(message) Notify::ptr()->assert_failure(message, __LINE__, __FILE__) 00183 00184 #define enter_debugger_if(condition) \ 00185 if (condition) { \ 00186 Notify::ptr()->assert_failure(#condition, __LINE__, __FILE__); \ 00187 __asm { int 3 } \ 00188 } 00189 00190 00191 #endif // NDEBUG 00192 00193 00194 #include "pnotify.I" 00195 00196 #endif