Panda3D
pnotify.h
1 // Filename: pnotify.h
2 // Created by: drose (28Feb00)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #ifndef NOTIFY_H
16 #define NOTIFY_H
17 
18 #include "dtoolbase.h"
19 #include "notifySeverity.h"
20 #include <map>
21 
22 class NotifyCategory;
23 
24 ////////////////////////////////////////////////////////////////////
25 // Class : Notify
26 // Description : An object that handles general error reporting to the
27 // user. It contains a pointer to an ostream, initially
28 // cerr, which can be reset at will to point to
29 // different output devices, according to the needs of
30 // the application. All output generated within Panda
31 // should vector through the Notify ostream.
32 //
33 // This also includes a collection of Categories and
34 // Severities, which may be independently enabled or
35 // disabled, so that error messages may be squelched or
36 // respected according to the wishes of the user.
37 ////////////////////////////////////////////////////////////////////
38 class EXPCL_DTOOLCONFIG Notify {
39 PUBLISHED:
40  Notify();
41  ~Notify();
42 
43  void set_ostream_ptr(ostream *ostream_ptr, bool delete_later);
44  ostream *get_ostream_ptr() const;
45 
46  typedef bool AssertHandler(const char *expression, int line,
47  const char *source_file);
48 
49  void set_assert_handler(AssertHandler *assert_handler);
50  void clear_assert_handler();
51  bool has_assert_handler() const;
52  AssertHandler *get_assert_handler() const;
53 
54  INLINE bool has_assert_failed() const;
55  INLINE const string &get_assert_error_message() const;
56  INLINE void clear_assert_failed();
57 
58  NotifyCategory *get_top_category();
59  NotifyCategory *get_category(const string &basename,
60  NotifyCategory *parent_category);
61  NotifyCategory *get_category(const string &basename,
62  const string &parent_fullname);
63  NotifyCategory *get_category(const string &fullname);
64 
65  static ostream &out();
66  static ostream &null();
67  static void write_string(const string &str);
68  static Notify *ptr();
69 
70 public:
71  static ios_fmtflags get_literal_flag();
72 
73  bool assert_failure(const string &expression, int line,
74  const char *source_file);
75  bool assert_failure(const char *expression, int line,
76  const char *source_file);
77 
78  static NotifySeverity string_severity(const string &string);
79 
80  void config_initialized();
81 
82 private:
83  ostream *_ostream_ptr;
84  bool _owns_ostream_ptr;
85  ostream *_null_ostream_ptr;
86 
87  AssertHandler *_assert_handler;
88  bool _assert_failed;
89  string _assert_error_message;
90 
91  // This shouldn't be a pmap, since it might be invoked before we
92  // initialize the global malloc pointers.
93  typedef map<string, NotifyCategory *> Categories;
94  Categories _categories;
95 
96  static Notify *_global_ptr;
97 };
98 
99 
100 // This defines the symbol nout in the same way that cerr and cout are
101 // defined, for compactness of C++ code that uses Notify in its
102 // simplest form. Maybe it's a good idea to define this symbol and
103 // maybe it's not, but it does seem that "nout" isn't likely to
104 // collide with any other name.
105 
106 #define nout (Notify::out())
107 
108 // Here are a couple of assert-type functions. These are designed to
109 // avoid simply dumping core, since that's quite troublesome when the
110 // programmer is working in a higher-level environment that is calling
111 // into the C++ layer.
112 
113 // nassertr() is intended to be used in functions that have return
114 // values; it returns the indicated value if the assertion fails.
115 
116 // nassertv() is intended to be used in functions that do not have
117 // return values; it simply returns if the assertion fails.
118 
119 // nassertd() does not return from the function, but instead executes
120 // the following block of code (like an if statement) if the assertion
121 // fails.
122 
123 // nassertr_always() and nassertv_always() are like nassertr() and
124 // nassertv(), except that they will not get completely compiled out
125 // if NDEBUG is set. Instead, they will quietly return from the
126 // function. These macros are appropriate, for instance, for sanity
127 // checking user input parameters, where optimal performance is not
128 // paramount.
129 
130 // nassert_static() is a compile-time assertion. It should only be
131 // used with constant expressions and compilation will fail if the
132 // assertion is not true.
133 
134 #ifdef NDEBUG
135 
136 #define nassertr(condition, return_value)
137 #define nassertv(condition)
138 #define nassertd(condition) if (false)
139 // We trust the compiler to optimize the above out.
140 
141 #define nassertr_always(condition, return_value) \
142  { \
143  if (!(condition)) { \
144  return return_value; \
145  } \
146  }
147 
148 #define nassertv_always(condition) \
149  { \
150  if (!(condition)) { \
151  return; \
152  } \
153  }
154 
155 #define nassert_raise(message) Notify::write_string(message)
156 
157 #define enter_debugger_if(condition) ((void)0)
158 
159 #else // NDEBUG
160 
161 #define nassertr(condition, return_value) \
162  { \
163  if (!(condition)) { \
164  if (Notify::ptr()->assert_failure(#condition, __LINE__, __FILE__)) { \
165  return return_value; \
166  } \
167  } \
168  }
169 
170 #define nassertv(condition) \
171  { \
172  if (!(condition)) { \
173  if (Notify::ptr()->assert_failure(#condition, __LINE__, __FILE__)) { \
174  return; \
175  } \
176  } \
177  }
178 
179 #define nassertd(condition) \
180  if (!(condition) && \
181  Notify::ptr()->assert_failure(#condition, __LINE__, __FILE__))
182 
183 #define nassertr_always(condition, return_value) nassertr(condition, return_value)
184 #define nassertv_always(condition) nassertv(condition)
185 
186 #define nassert_raise(message) Notify::ptr()->assert_failure(message, __LINE__, __FILE__)
187 
188 #define enter_debugger_if(condition) \
189  if (condition) { \
190  Notify::ptr()->assert_failure(#condition, __LINE__, __FILE__); \
191  __asm { int 3 } \
192  }
193 
194 
195 #endif // NDEBUG
196 
197 #if __cplusplus >= 201103
198 #define __nassert_static(condition, line, file) static_assert((condition), #condition " at line " #line " of " file)
199 #define _nassert_static(condition, line, file) __nassert_static(condition, line, file)
200 #define nassert_static(condition) _nassert_static(condition, __LINE__, __FILE__)
201 #else
202 #define __nassert_static(condition, suffix) typedef char nassert_static_ ## suffix [(condition) ? 1 : -1];
203 #define _nassert_static(condition, suffix) __nassert_static(condition, suffix)
204 #define nassert_static(condition) _nassert_static(condition, __COUNTER__)
205 #endif
206 
207 #include "pnotify.I"
208 
209 #endif
A particular category of error messages.
An object that handles general error reporting to the user.
Definition: pnotify.h:38