Panda3D
 All Classes Functions Variables Enumerations
pnotify.h
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
 All Classes Functions Variables Enumerations