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