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.
An object that handles general error reporting to the user.
Definition: pnotify.h:33
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.