24 /// \brief Extended assertion handling |
24 /// \brief Extended assertion handling |
25 |
25 |
26 #include <lemon/error.h> |
26 #include <lemon/error.h> |
27 |
27 |
28 namespace lemon { |
28 namespace lemon { |
29 |
|
30 /// @{ |
|
31 |
|
32 ///\e |
|
33 class AssertionFailedError : public LogicError { |
|
34 protected: |
|
35 const char *_assertion; |
|
36 const char *_file; |
|
37 int _line; |
|
38 const char *_function; |
|
39 const char *_message; |
|
40 |
|
41 mutable ExceptionMember<std::string> _message_holder; |
|
42 public: |
|
43 ///\e |
|
44 AssertionFailedError(const char *file, int line, const char *function, |
|
45 const char *msg, const char *assertion = 0) : |
|
46 _assertion(assertion), _file(file), _line(line), |
|
47 _function(function), _message(msg) {} |
|
48 |
|
49 ///\e |
|
50 const char* assertion() const { return _assertion; } |
|
51 ///\e |
|
52 const char* message() const { return _message; } |
|
53 ///\e |
|
54 const char* file() const { return _file; } |
|
55 ///\e |
|
56 const char* function() const { return _function; } |
|
57 ///\e |
|
58 int line() const { return _line; } |
|
59 |
|
60 |
|
61 virtual const char* what() const throw() { |
|
62 try { |
|
63 std::ostringstream ostr; |
|
64 ostr << _file << ":" << _line << ": "; |
|
65 if (_function) |
|
66 ostr << _function << ": "; |
|
67 ostr << _message; |
|
68 if (_assertion) |
|
69 ostr << " (assertion '" << _assertion << "' failed)"; |
|
70 _message_holder.set(ostr.str()); |
|
71 return ostr.str().c_str(); |
|
72 } |
|
73 catch(...) {} |
|
74 if( _message_holder.valid() ) return _message_holder.get().c_str(); |
|
75 return "lemon::AssertionFailedError"; |
|
76 } |
|
77 virtual ~AssertionFailedError() throw() {} |
|
78 }; |
|
79 |
|
80 |
|
81 inline void assert_fail_log(const char *file, int line, |
|
82 const char *function, |
|
83 const std::exception& exception, |
|
84 const char *assertion) |
|
85 { |
|
86 std::cerr << file << ":" << line << ": "; |
|
87 if (function) |
|
88 std::cerr << function << ": "; |
|
89 std::cerr << exception.what(); |
|
90 if (assertion) |
|
91 std::cerr << " (assertion '" << assertion << "' failed)"; |
|
92 std::cerr << std::endl; |
|
93 } |
|
94 |
29 |
95 inline void assert_fail_log(const char *file, int line, const char *function, |
30 inline void assert_fail_log(const char *file, int line, const char *function, |
96 const char *message, const char *assertion) |
31 const char *message, const char *assertion) |
97 { |
32 { |
98 std::cerr << file << ":" << line << ": "; |
33 std::cerr << file << ":" << line << ": "; |
102 if (assertion) |
37 if (assertion) |
103 std::cerr << " (assertion '" << assertion << "' failed)"; |
38 std::cerr << " (assertion '" << assertion << "' failed)"; |
104 std::cerr << std::endl; |
39 std::cerr << std::endl; |
105 } |
40 } |
106 |
41 |
107 inline void assert_fail_log(const char *file, int line, const char *function, |
|
108 const std::string& message, const char *assertion) |
|
109 { |
|
110 assert_fail_log(file, line, function, message.c_str(), assertion); |
|
111 } |
|
112 |
|
113 inline void assert_fail_abort(const char *file, int line, |
|
114 const char *function, |
|
115 const std::exception& exception, |
|
116 const char *assertion) |
|
117 { |
|
118 assert_fail_log(file, line, function, exception, assertion); |
|
119 std::abort(); |
|
120 } |
|
121 |
|
122 inline void assert_fail_abort(const char *file, int line, |
42 inline void assert_fail_abort(const char *file, int line, |
123 const char *function, const char* message, |
43 const char *function, const char* message, |
124 const char *assertion) |
44 const char *assertion) |
125 { |
45 { |
126 assert_fail_log(file, line, function, message, assertion); |
46 assert_fail_log(file, line, function, message, assertion); |
127 std::abort(); |
47 std::abort(); |
128 } |
48 } |
129 |
49 |
130 inline void assert_fail_abort(const char *file, int line, |
50 namespace _assert_bits { |
131 const char *function, |
51 |
132 const std::string& message, |
52 |
133 const char *assertion) |
53 inline const char* cstringify(const std::string& str) { |
134 { |
54 return str.c_str(); |
135 assert_fail_log(file, line, function, message.c_str(), assertion); |
55 } |
136 std::abort(); |
56 |
|
57 inline const char* cstringify(const char* str) { |
|
58 return str; |
|
59 } |
137 } |
60 } |
138 |
|
139 inline void assert_fail_error(const char *file, int line, |
|
140 const char *function, |
|
141 const std::exception& exception, |
|
142 const char *assertion) |
|
143 { |
|
144 throw AssertionFailedError(file, line, function, |
|
145 exception.what(), assertion); |
|
146 } |
|
147 |
|
148 inline void assert_fail_error(const char *file, int line, |
|
149 const char *function, const char *message, |
|
150 const char *assertion) |
|
151 { |
|
152 throw AssertionFailedError(file, line, function, message, assertion); |
|
153 } |
|
154 |
|
155 inline void assert_fail_error(const char *file, int line, |
|
156 const char *function, |
|
157 const std::string& message, |
|
158 const char *assertion) |
|
159 { |
|
160 throw AssertionFailedError(file, line, function, message.c_str(), assertion); |
|
161 } |
|
162 |
|
163 template <typename Exception> |
|
164 inline void assert_fail_exception(const char *, int, const char *, |
|
165 const Exception& exception, |
|
166 const char *, const std::exception* = |
|
167 static_cast<const Exception*>(0)) |
|
168 { |
|
169 throw exception; |
|
170 } |
|
171 |
|
172 inline void assert_fail_exception(const char *file, int line, |
|
173 const char *function, const char *message, |
|
174 const char *assertion) |
|
175 { |
|
176 throw AssertionFailedError(file, line, function, message, assertion); |
|
177 } |
|
178 |
|
179 inline void assert_fail_exception(const char *file, int line, |
|
180 const char *function, |
|
181 const std::string& message, |
|
182 const char *assertion) |
|
183 { |
|
184 throw AssertionFailedError(file, line, function, message.c_str(), assertion); |
|
185 } |
|
186 |
|
187 /// @} |
|
188 |
|
189 } |
61 } |
|
62 |
190 #endif // LEMON_ASSERT_H |
63 #endif // LEMON_ASSERT_H |
191 |
64 |
192 #undef LEMON_ASSERT |
65 #undef LEMON_ASSERT |
193 #undef LEMON_FIXME |
66 #undef LEMON_FIXME |
|
67 #undef LEMON_DEBUG |
194 |
68 |
195 #if (defined(LEMON_ASSERT_LOG) ? 1 : 0) + \ |
69 #if (defined(LEMON_ASSERT_LOG) ? 1 : 0) + \ |
196 (defined(LEMON_ASSERT_ABORT) ? 1 : 0) + \ |
70 (defined(LEMON_ASSERT_ABORT) ? 1 : 0) + \ |
197 (defined(LEMON_ASSERT_ERROR) ? 1 : 0) + \ |
|
198 (defined(LEMON_ASSERT_EXCEPTION) ? 1 : 0) + \ |
|
199 (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) > 1 |
71 (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) > 1 |
200 #error "LEMON assertion system is not set properly" |
72 #error "LEMON assertion system is not set properly" |
201 #endif |
73 #endif |
202 |
74 |
203 #if ((defined(LEMON_ASSERT_LOG) ? 1 : 0) + \ |
75 #if ((defined(LEMON_ASSERT_LOG) ? 1 : 0) + \ |
204 (defined(LEMON_ASSERT_ABORT) ? 1 : 0) + \ |
76 (defined(LEMON_ASSERT_ABORT) ? 1 : 0) + \ |
205 (defined(LEMON_ASSERT_ERROR) ? 1 : 0) + \ |
|
206 (defined(LEMON_ASSERT_EXCEPTION) ? 1 : 0) + \ |
|
207 (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) == 1 || \ |
77 (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) == 1 || \ |
208 defined(LEMON_ENABLE_ASSERTS)) && \ |
78 defined(LEMON_ENABLE_ASSERTS)) && \ |
209 defined(LEMON_DISABLE_ASSERTS) |
79 (defined(LEMON_DISABLE_ASSERTS) || \ |
|
80 defined(NDEBUG)) |
210 #error "LEMON assertion system is not set properly" |
81 #error "LEMON assertion system is not set properly" |
211 #endif |
82 #endif |
212 |
83 |
213 |
84 |
214 #if defined LEMON_ASSERT_LOG |
85 #if defined LEMON_ASSERT_LOG |
215 # undef LEMON_ASSERT_HANDLER |
86 # undef LEMON_ASSERT_HANDLER |
216 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_log |
87 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_log |
217 #elif defined LEMON_ASSERT_ABORT |
88 #elif defined LEMON_ASSERT_ABORT |
218 # undef LEMON_ASSERT_HANDLER |
89 # undef LEMON_ASSERT_HANDLER |
219 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort |
90 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort |
220 #elif defined LEMON_ASSERT_ERROR |
|
221 # undef LEMON_ASSERT_HANDLER |
|
222 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_error |
|
223 #elif defined LEMON_ASSERT_EXCEPTION |
|
224 # undef LEMON_ASSERT_HANDLER |
|
225 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_exception |
|
226 #elif defined LEMON_ASSERT_CUSTOM |
91 #elif defined LEMON_ASSERT_CUSTOM |
227 # undef LEMON_ASSERT_HANDLER |
92 # undef LEMON_ASSERT_HANDLER |
228 # ifndef LEMON_CUSTOM_ASSERT_HANDLER |
93 # ifndef LEMON_CUSTOM_ASSERT_HANDLER |
229 # error "LEMON_CUSTOM_ASSERT_HANDLER is not set" |
94 # error "LEMON_CUSTOM_ASSERT_HANDLER is not set" |
230 # endif |
95 # endif |
231 # define LEMON_ASSERT_HANDLER LEMON_CUSTOM_ASSERT_HANDLER |
96 # define LEMON_ASSERT_HANDLER LEMON_CUSTOM_ASSERT_HANDLER |
232 #elif defined LEMON_ENABLE_ASSERTS |
97 #elif defined LEMON_DISABLE_ASSERTS |
233 # undef LEMON_ASSERT_HANDLER |
98 # undef LEMON_ASSERT_HANDLER |
|
99 #elif defined NDEBUG |
|
100 # undef LEMON_ASSERT_HANDLER |
|
101 #else |
234 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort |
102 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort |
235 #else |
103 #endif |
236 # undef LEMON_ASSERT_HANDLER |
|
237 #endif |
|
238 |
|
239 |
104 |
240 #ifndef LEMON_FUNCTION_NAME |
105 #ifndef LEMON_FUNCTION_NAME |
241 # define LEMON_FUNCTION_NAME (__PRETTY_FUNCTION__) |
106 # define LEMON_FUNCTION_NAME (__PRETTY_FUNCTION__) |
242 #endif |
107 #endif |
243 |
108 |
245 |
110 |
246 /// \ingroup exceptions |
111 /// \ingroup exceptions |
247 /// |
112 /// |
248 /// \brief Macro for assertion with customizable message |
113 /// \brief Macro for assertion with customizable message |
249 /// |
114 /// |
250 /// Macro for assertion with customizable message. |
115 /// Macro for assertion with customizable message. \param exp An |
251 /// \param exp An expression that must be convertible to \c bool. |
116 /// expression that must be convertible to \c bool. If it is \c |
252 /// If it is \c false, then an assertion is raised. The concrete |
117 /// false, then an assertion is raised. The concrete behaviour depends |
253 /// behaviour depends on the settings of the assertion system. |
118 /// on the settings of the assertion system. \param msg A <tt>const |
254 /// \param msg A <tt>const char*</tt>, a <tt>const std::string&</tt> or |
119 /// char*</tt> parameter, which can be used to provide information |
255 /// a <tt>const std::exception&</tt> parameter, which can be used to |
120 /// about the circumstances of the failed assertion. |
256 /// provide information about the circumstances of the failed assertion. |
121 /// |
257 /// |
122 /// The assertions are enabled in the default behaviour. |
258 /// The assertions are disabled in the default behaviour. |
123 /// You can disable them with the following code: |
259 /// You can enable them with the following code: |
124 /// \code |
260 /// \code |
125 /// #define LEMON_DISABLE_ASSERTS |
261 /// #define LEMON_ENABLE_ASSERTS |
|
262 /// \endcode |
126 /// \endcode |
263 /// or with compilation parameters: |
127 /// or with compilation parameters: |
264 /// \code |
128 /// \code |
265 /// g++ -DLEMON_ENABLE_ASSERTS |
129 /// g++ -DLEMON_DISABLE_ASSERTS |
266 /// make CXXFLAGS='-DLEMON_ENABLE_ASSERTS' |
130 /// make CXXFLAGS='-DLEMON_DISABLE_ASSERTS' |
267 /// \endcode |
131 /// \endcode |
|
132 /// The checking is also disabled when the standard macro \c NDEBUG is defined. |
268 /// |
133 /// |
269 /// The LEMON assertion system has a wide range of customization |
134 /// The LEMON assertion system has a wide range of customization |
270 /// properties. As a default behaviour the failed assertion prints a |
135 /// properties. As a default behaviour the failed assertion prints a |
271 /// short log message to the standard error and aborts the execution. |
136 /// short log message to the standard error and aborts the execution. |
272 /// |
137 /// |
273 /// The following modes can be used in the assertion system: |
138 /// The following modes can be used in the assertion system: |
274 /// |
139 /// |
275 /// - \c LEMON_ASSERT_LOG The failed assertion prints a short log |
140 /// - \c LEMON_ASSERT_LOG The failed assertion prints a short log |
276 /// message to the standard error and continues the execution. |
141 /// message to the standard error and continues the execution. |
277 /// - \c LEMON_ASSERT_ABORT This mode is similar to the |
142 /// - \c LEMON_ASSERT_ABORT This mode is similar to the \c |
278 /// \c LEMON_ASSERT_LOG, but it aborts the program. It is the default |
143 /// LEMON_ASSERT_LOG, but it aborts the program. It is the default |
279 /// behaviour mode when the assertions are enabled with |
144 /// behaviour. |
280 /// \c LEMON_ENABLE_ASSERTS. |
|
281 /// - \c LEMON_ASSERT_ERROR The assertion throws an |
|
282 /// \ref lemon::AssertionFailedError "AssertionFailedError". |
|
283 /// If the \c msg parameter is an exception, then the result of the |
|
284 /// \ref lemon::Exception::what() "what()" member function is passed |
|
285 /// as error message. |
|
286 /// - \c LEMON_ASSERT_EXCEPTION If the specified \c msg is an |
|
287 /// exception, then it raised directly (solving that the exception |
|
288 /// can not be thrown polymorphically), otherwise an \ref |
|
289 /// lemon::AssertionFailedError "AssertionFailedError" is thrown with |
|
290 /// the given parameters. |
|
291 /// - \c LEMON_ASSERT_CUSTOM The user can define own assertion handler |
145 /// - \c LEMON_ASSERT_CUSTOM The user can define own assertion handler |
292 /// functions. Three overloaded functions should be defined with the |
146 /// function. |
293 /// following parameter lists: |
|
294 /// \code |
147 /// \code |
295 /// void custom_assert_handler(const char* file, int line, const char* function, |
148 /// void custom_assert_handler(const char* file, int line, const char* function, |
296 /// const char* message, const char* assertion); |
149 /// const char* message, const char* assertion); |
297 /// void custom_assert_handler(const char* file, int line, const char* function, |
|
298 /// const std::string& message, const char* assertion); |
|
299 /// void custom_assert_handler(const char* file, int line, const char* function, |
|
300 /// const std::exception& message, const char* assertion); |
|
301 /// \endcode |
150 /// \endcode |
302 /// The name of the functions should be defined as the \c |
151 /// The name of the function should be defined as the \c |
303 /// LEMON_CUSTOM_ASSERT_HANDLER macro name. |
152 /// LEMON_CUSTOM_ASSERT_HANDLER macro name. |
304 /// \code |
153 /// \code |
305 /// #define LEMON_CUSTOM_ASSERT_HANDLER custom_assert_handler |
154 /// #define LEMON_CUSTOM_ASSERT_HANDLER custom_assert_handler |
306 /// \endcode |
155 /// \endcode |
307 /// Whenever an assertion is occured, one of the custom assertion |
156 /// Whenever an assertion is occured, the custom assertion |
308 /// handlers is called with appropiate parameters. |
157 /// handler is called with appropiate parameters. |
309 /// |
158 /// |
310 /// The assertion mode can also be changed within one compilation unit. |
159 /// The assertion mode can also be changed within one compilation unit. |
311 /// If the macros are redefined with other settings and the |
160 /// If the macros are redefined with other settings and the |
312 /// \ref lemon/assert.h "assert.h" file is reincluded, then the |
161 /// \ref lemon/assert.h "assert.h" file is reincluded, then the |
313 /// behaviour is changed appropiately to the new settings. |
162 /// behaviour is changed appropiately to the new settings. |
314 # define LEMON_ASSERT(exp, msg) \ |
163 # define LEMON_ASSERT(exp, msg) \ |
315 (static_cast<void> (!!(exp) ? 0 : ( \ |
164 (static_cast<void> (!!(exp) ? 0 : ( \ |
316 LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \ |
165 LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \ |
317 LEMON_FUNCTION_NAME, \ |
166 LEMON_FUNCTION_NAME, \ |
318 msg, #exp), 0))) |
167 ::lemon::_assert_bits::cstringify(msg), #exp), 0))) |
319 |
|
320 |
168 |
321 /// \ingroup exceptions |
169 /// \ingroup exceptions |
322 /// |
170 /// |
323 /// \brief Macro for mark not yet implemented features. |
171 /// \brief Macro for mark not yet implemented features. |
324 /// |
172 /// |
325 /// Macro for mark not yet implemented features and outstanding bugs. |
173 /// Macro for mark not yet implemented features and outstanding bugs. |
326 /// It is close to be the shortcut of the following code: |
174 /// It is close to be the shortcut of the following code: |
327 /// \code |
175 /// \code |
328 /// LEMON_ASSERT(false, msg); |
176 /// LEMON_ASSERT(false, msg); |
329 /// \endcode |
177 /// \endcode |
|
178 /// |
|
179 /// \see LEMON_ASSERT |
330 # define LEMON_FIXME(msg) \ |
180 # define LEMON_FIXME(msg) \ |
331 (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME, \ |
181 (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME, \ |
332 "FIXME: " msg, static_cast<const char*>(0))) |
182 ::lemon::_assert_bits::cstringify(msg), \ |
|
183 static_cast<const char*>(0))) |
|
184 |
|
185 /// \ingroup exceptions |
|
186 /// |
|
187 /// \brief Macro for internal assertions |
|
188 /// |
|
189 /// Macro for internal assertions, it is used in the library to check |
|
190 /// the consistency of results of algorithms, several pre- and |
|
191 /// postconditions and invariants. The checking is disabled by |
|
192 /// default, but it can be turned on with the macro \c |
|
193 /// LEMON_ENABLE_DEBUG. |
|
194 /// \code |
|
195 /// #define LEMON_ENABLE_DEBUG |
|
196 /// \endcode |
|
197 /// or with compilation parameters: |
|
198 /// \code |
|
199 /// g++ -DLEMON_ENABLE_DEBUG |
|
200 /// make CXXFLAGS='-DLEMON_ENABLE_DEBUG' |
|
201 /// \endcode |
|
202 /// |
|
203 /// This macro works like the \c LEMON_ASSERT macro, therefore the |
|
204 /// current behaviour depends on the settings of \c LEMON_ASSERT |
|
205 /// macro. |
|
206 /// |
|
207 /// \see LEMON_ASSERT |
|
208 # define LEMON_DEBUG(exp, msg) \ |
|
209 (static_cast<void> (!!(exp) ? 0 : ( \ |
|
210 LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \ |
|
211 LEMON_FUNCTION_NAME, \ |
|
212 ::lemon::_assert_bits::cstringify(msg), #exp), 0))) |
333 |
213 |
334 #else |
214 #else |
335 |
215 |
336 # ifndef LEMON_ASSERT_HANDLER |
216 # ifndef LEMON_ASSERT_HANDLER |
337 # define LEMON_ASSERT(exp, msg) (static_cast<void>(0)) |
217 # define LEMON_ASSERT(exp, msg) (static_cast<void>(0)) |
338 # define LEMON_FIXME(msg) (static_cast<void>(0)) |
218 # define LEMON_FIXME(msg) (static_cast<void>(0)) |
|
219 # define LEMON_DEBUG(exp, msg) (static_cast<void>(0)) |
339 # else |
220 # else |
340 # define LEMON_ASSERT(exp, msg) \ |
221 # define LEMON_ASSERT(exp, msg) \ |
341 (static_cast<void> (!!(exp) ? 0 : ( \ |
222 (static_cast<void> (!!(exp) ? 0 : ( \ |
342 LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \ |
223 LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \ |
343 LEMON_FUNCTION_NAME, \ |
224 LEMON_FUNCTION_NAME, \ |
344 msg, #exp), 0))) |
225 ::lemon::_assert_bits::cstringify(msg), \ |
345 # define LEMON_FIXME(msg) \ |
226 #exp), 0))) |
|
227 # define LEMON_FIXME(msg) \ |
346 (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME, \ |
228 (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME, \ |
347 "FIXME: " msg, static_cast<const char*>(0))) |
229 ::lemon::_assert_bits::cstringify(msg), \ |
|
230 static_cast<const char*>(0))) |
|
231 |
|
232 # if LEMON_ENABLE_DEBUG |
|
233 # define LEMON_DEBUG(exp, msg) |
|
234 (static_cast<void> (!!(exp) ? 0 : ( \ |
|
235 LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \ |
|
236 LEMON_FUNCTION_NAME, \ |
|
237 ::lemon::_assert_bits::cstringify(msg), \ |
|
238 #exp), 0))) |
|
239 # else |
|
240 # define LEMON_DEBUG(exp, msg) (static_cast<void>(0)) |
|
241 # endif |
348 # endif |
242 # endif |
349 |
243 |
350 #endif |
244 #endif |
351 |
245 |
352 |
246 #ifdef DOXYGEN |
|
247 |
|
248 |
|
249 #else |
|
250 |
|
251 |
|
252 #endif |
|
253 |
|
254 |