COIN-OR::LEMON - Graph Library

source: lemon/lemon/assert.h @ 108:889d0c289d19

Last change on this file since 108:889d0c289d19 was 108:889d0c289d19, checked in by Balazs Dezso <deba@…>, 16 years ago

Reworking assertions and moving to distinict file

File size: 11.6 KB
Line 
1/* -*- C++ -*-
2 *
3 * This file is a part of LEMON, a generic C++ optimization library
4 *
5 * Copyright (C) 2003-2008
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 *
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
12 *
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
15 * purpose.
16 *
17 */
18
19#ifndef LEMON_ASSERT_H
20#define LEMON_ASSERT_H
21
22/// \ingroup exceptions
23/// \file
24/// \brief Extended assertion handling
25
26#include <lemon/error.h>
27
28namespace 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
95  inline void assert_fail_log(const char *file, int line, const char *function,
96                              const char *message, const char *assertion)
97  {
98    std::cerr << file << ":" << line << ": ";
99    if (function)
100      std::cerr << function << ": ";
101    std::cerr << message;
102    if (assertion)
103      std::cerr << " (assertion '" << assertion << "' failed)";
104    std::cerr << std::endl;
105  }
106
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    std::cerr << file << ":" << line << ": ";
119    if (function)
120      std::cerr << function << ": ";
121    std::cerr << exception.what();
122    if (assertion)
123      std::cerr << " (assertion '" << assertion << "' failed)";
124    std::cerr << std::endl;
125    std::abort();
126  }
127
128  inline void assert_fail_abort(const char *file, int line,
129                                const char *function, const char* message,
130                                const char *assertion)
131  {
132    std::cerr << file << ":" << line << ": ";
133    if (function)
134      std::cerr << function << ": ";
135    std::cerr << message;
136    if (assertion)
137      std::cerr << " (assertion '" << assertion << "' failed)";
138    std::cerr << std::endl;
139    std::abort();
140  }
141
142  inline void assert_fail_abort(const char *file, int line,
143                                const char *function,
144                                const std::string& message,
145                                const char *assertion)
146  {
147    assert_fail_abort(file, line, function, message.c_str(), assertion);
148  }
149
150  inline void assert_fail_error(const char *file, int line,
151                                  const char *function,
152                                  const std::exception& exception,
153                                  const char *assertion)
154  {
155    throw AssertionFailedError(file, line, function,
156                               exception.what(), assertion);
157  }
158
159  inline void assert_fail_error(const char *file, int line,
160                                  const char *function, const char *message,
161                                  const char *assertion)
162  {
163    throw AssertionFailedError(file, line, function, message, assertion);
164  }
165
166  inline void assert_fail_error(const char *file, int line,
167                                  const char *function,
168                                  const std::string& message,
169                                  const char *assertion)
170  {
171    assert_fail_error(file, line, function, message.c_str(), assertion);
172  }
173
174  template <typename Exception>
175  inline void assert_fail_exception(const char *, int, const char *,
176                                    const Exception& exception,
177                                    const char *, const std::exception* =
178                                    static_cast<const Exception*>(0))
179  {
180    throw exception;
181  }
182
183  inline void assert_fail_exception(const char *file, int line,
184                                    const char *function, const char *message,
185                                    const char *assertion)
186  {
187    throw AssertionFailedError(file, line, function, message, assertion);
188  }
189
190  inline void assert_fail_exception(const char *file, int line,
191                                    const char *function,
192                                    const std::string& message,
193                                    const char *assertion)
194  {
195    assert_fail_exception(file, line, function, message.c_str(), assertion);
196  }
197
198/// @}
199
200}
201#endif // LEMON_ASSERT_H
202
203#undef LEMON_ASSERT
204#undef LEMON_FIXME
205
206#if (defined(LEMON_ASSERT_LOG) ? 1 : 0) +               \
207  (defined(LEMON_ASSERT_ABORT) ? 1 : 0) +               \
208  (defined(LEMON_ASSERT_ERROR) ? 1 : 0) +               \
209  (defined(LEMON_ASSERT_EXCEPTION) ? 1 : 0) +           \
210  (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) > 1
211#error "Lemon assertion system is not set properly"
212#endif
213
214#if ((defined(LEMON_ASSERT_LOG) ? 1 : 0) +              \
215     (defined(LEMON_ASSERT_ABORT) ? 1 : 0) +            \
216     (defined(LEMON_ASSERT_ERROR) ? 1 : 0) +            \
217     (defined(LEMON_ASSERT_EXCEPTION) ? 1 : 0) +        \
218     (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) == 1 ||     \
219     defined(LEMON_ENABLE_ASSERT)) &&                   \
220  defined(LEMON_DISABLE_ASSERTS)
221#error "Lemon assertion system is not set properly"
222#endif
223
224
225#if defined LEMON_ASSERT_LOG
226#  undef LEMON_ASSERT_HANDLER
227#  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_log
228#elif defined LEMON_ASSERT_ABORT
229#  undef LEMON_ASSERT_HANDLER
230#  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort
231#elif defined LEMON_ASSERT_ERROR
232#  undef LEMON_ASSERT_HANDLER
233#  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_error
234#elif defined LEMON_ASSERT_EXCEPTION
235#  undef LEMON_ASSERT_HANDLER
236#  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_exception
237#elif defined LEMON_ASSERT_CUSTOM
238#  undef LEMON_ASSERT_HANDLER
239#  ifndef LEMON_CUSTOM_ASSERT_HANDLER
240#    error "LEMON_CUSTOM_ASSERT_HANDLER is not set"
241#  endif
242#  define LEMON_ASSERT_HANDLER LEMON_CUSTOM_ASSERT_HANDLER
243#elif defined LEMON_ENABLE_ASSERTS
244#  undef LEMON_ASSERT_HANDLER
245#  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort
246#else
247#  undef LEMON_ASSERT_HANDLER
248#endif
249
250
251#ifndef LEMON_FUNCTION_NAME
252#  define LEMON_FUNCTION_NAME (__PRETTY_FUNCTION__)
253#endif
254
255#ifdef DOXYGEN
256
257/// \ingroup exceptions
258///
259/// \brief Macro for assertions with customizable message
260///
261/// Macro for assertions with customizable message. 
262/// \param exp An expression convertible to bool. If the expression is
263/// false, then an assertion is raised. The concrete behaviour depends
264/// on the settings of the assertion system.
265/// \param msg A \e const \e char*, a \e const std::string& or a \e
266/// const \e std::exception& parameter. The variable can be used to
267/// provide information about the circumstances of failed assertion.
268///
269/// The assertions are disabled in the default behaviour. You can
270/// enable the assertions with the following code:
271/// \code
272/// #define LEMON_ENABLE_ASSERTS
273/// \endcode
274/// or with compilation parameters:
275/// \code
276/// g++ -DLEMON_ENABLE_ASSERTS
277/// make CXXFLAGS='-DLEMON_ENABLE_ASSERTS'
278/// \endcode
279///
280/// The %lemon assertion system has a wide range of customization
281/// properties. As default behaviour the failed assertion prints a
282/// short log message to the standard ouput and aborts the execution.
283///
284/// The following modes can be used in the assertion system:
285///
286/// - \e LEMON_ASSERT_LOG The failed assert print a short convenient
287///   error message to the standard error and continues the
288///   execution.
289/// - \e LEMON_ASSERT_ABORT This mode is similar to the \e
290///   LEMON_ASSERT_LOG, but it aborts the program. It is the default
291///   operation mode when the asserts are enabled with \e
292///   LEMON_ENABLE_ASSERTS.
293/// - \e LEMON_ASSERT_ERROR The assert throws an \ref
294///   lemon::AssertionFailedError "AssertionFailedError". If the \c
295///   msg parameter is an exception, then the result of the \ref
296///   lemon::Exception::what() "what()" member function is passed as
297///   error message.
298/// - \e LEMON_ASSERT_EXCEPTION If the specified \c msg is an
299///   exception then it raised directly (solving that the exception
300///   can not be thrown polymorphically), otherwise an \ref
301///   lemon::AssertionFailedError "AssertionFailedError" is thrown with
302///   the given parameter.
303/// - \e LEMON_ASSERT_CUSTOM The user can define an own assertion
304///   handler functions. Three overloaded functions should be defined
305///   with the following parameter lists:
306///   \code
307///     void custom_assert_handler(const char* file, int line,
308///                                const char* function, const char* message, const char* expression);
309///     void custom_assert_handler(const char* file, int line,
310///                                const char* function, const std::string& message, const char* expression);
311///     void custom_assert_handler(const char* file, int line,
312///                                const char* function, const std::exception& message, const char* expression);
313///   \endcode
314///   The name of the functions should be defined as the \c
315///   LEMON_CUSTOM_ASSERT_HANDLER macro name.
316///   \code
317///     #define LEMON_CUSTOM_ASSERT_HANDLER custom_assert_handler
318///   \endcode
319///   Whenever an assertion is occured, one of the custom assertion
320///   handler is called with appropiate parameters.
321///
322/// The assertion mode can be changed within one compilation unit, if
323/// the macros are redefined with other settings and the
324/// lemon/assert.h file is reincluded then the behaviour is changed
325/// appropiately to the new settings.
326#  define LEMON_ASSERT(exp, msg)                                        \
327  (static_cast<void> (!!(exp) ? 0 : (                                   \
328    LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                            \
329                         LEMON_FUNCTION_NAME,                           \
330                         msg, #exp), 0)))
331
332
333/// \ingroup exceptions
334///
335/// \brief Macro for mark not yet implemented features.
336///
337/// Macro for mark not yet implemented features and outstanding bugs.
338/// It is close to be the shortcut of the following code:
339/// \code
340///   LEMON_ASSERT(false, msg);
341/// \endcode
342#  define LEMON_FIXME(msg)                                              \
343       (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME,   \
344                             "FIXME: " msg, static_cast<const char*>(0)))
345
346#else
347
348#  ifndef LEMON_ASSERT_HANDLER
349#    define LEMON_ASSERT(exp, msg)  (static_cast<void> (0))
350#    define LEMON_FIXME(msg) (static_cast<void>(0))
351#  else
352#    define LEMON_ASSERT(exp, msg)                 \
353       (static_cast<void> (!!(exp) ? 0 : (         \
354         LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \
355                              LEMON_FUNCTION_NAME, \
356                              msg, #exp), 0)))
357#    define LEMON_FIXME(msg) \
358       (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME,   \
359                             "FIXME: " msg,  static_cast<const char*>(0)))
360#  endif
361
362#endif
363
364
Note: See TracBrowser for help on using the repository browser.