COIN-OR::LEMON - Graph Library

source: lemon-main/lemon/assert.h @ 112:d2ee5e7f00ef

Last change on this file since 112:d2ee5e7f00ef was 112:d2ee5e7f00ef, checked in by Peter Kovacs <kpeter@…>, 16 years ago

Improvements in assert.h

File size: 11.3 KB
RevLine 
[66]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
[108]19#ifndef LEMON_ASSERT_H
20#define LEMON_ASSERT_H
[66]21
22/// \ingroup exceptions
23/// \file
[108]24/// \brief Extended assertion handling
[66]25
[108]26#include <lemon/error.h>
[66]27
28namespace lemon {
29
30  /// @{
31
32  ///\e
33  class AssertionFailedError : public LogicError {
34  protected:
[108]35    const char *_assertion;
36    const char *_file;
37    int _line;
38    const char *_function;
39    const char *_message;
[66]40
41    mutable ExceptionMember<std::string> _message_holder;
42  public:
43    ///\e
[108]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) {}
[66]48
49    ///\e
[108]50    const char* assertion() const { return _assertion; }
[66]51    ///\e
[108]52    const char* message() const { return _message; }
[66]53    ///\e
[108]54    const char* file() const { return _file; }
[66]55    ///\e
[108]56    const char* function() const { return _function; }
[66]57    ///\e
[108]58    int line() const { return _line; }
[66]59
60
61    virtual const char* what() const throw() {
62      try {
63        std::ostringstream ostr;
[108]64        ostr << _file << ":" << _line << ": ";
65        if (_function)
66          ostr << _function << ": ";
67        ostr << _message;
68        if (_assertion)
69           ostr << " (assertion '" << _assertion << "' failed)";
[66]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    }
[108]77    virtual ~AssertionFailedError() throw() {}
[66]78  };
79
80
[108]81  inline void assert_fail_log(const char *file, int line,
82                              const char *function,
83                              const std::exception& exception,
84                              const char *assertion)
[66]85  {
[108]86    std::cerr << file << ":" << line << ": ";
87    if (function)
88      std::cerr << function << ": ";
89    std::cerr << exception.what();
[66]90    if (assertion)
[108]91      std::cerr << " (assertion '" << assertion << "' failed)";
92    std::cerr << std::endl;
[66]93  }
94
[108]95  inline void assert_fail_log(const char *file, int line, const char *function,
96                              const char *message, const char *assertion)
[66]97  {
[108]98    std::cerr << file << ":" << line << ": ";
99    if (function)
100      std::cerr << function << ": ";
101    std::cerr << message;
[66]102    if (assertion)
[108]103      std::cerr << " (assertion '" << assertion << "' failed)";
104    std::cerr << std::endl;
[66]105  }
106
[108]107  inline void assert_fail_log(const char *file, int line, const char *function,
108                              const std::string& message, const char *assertion)
[66]109  {
[108]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  {
[112]118    assert_fail_log(file, line, function, exception, assertion);
[108]119    std::abort();
120  }
121
122  inline void assert_fail_abort(const char *file, int line,
123                                const char *function, const char* message,
124                                const char *assertion)
125  {
[112]126    assert_fail_log(file, line, function, message, assertion);
[108]127    std::abort();
128  }
129
130  inline void assert_fail_abort(const char *file, int line,
131                                const char *function,
132                                const std::string& message,
133                                const char *assertion)
134  {
[112]135    assert_fail_log(file, line, function, message.c_str(), assertion);
136    std::abort();
[108]137  }
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  {
[112]160    throw AssertionFailedError(file, line, function, message.c_str(), assertion);
[66]161  }
162
163  template <typename Exception>
[108]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))
[66]168  {
169    throw exception;
170  }
171
[108]172  inline void assert_fail_exception(const char *file, int line,
173                                    const char *function, const char *message,
174                                    const char *assertion)
[66]175  {
[108]176    throw AssertionFailedError(file, line, function, message, assertion);
[66]177  }
178
[108]179  inline void assert_fail_exception(const char *file, int line,
180                                    const char *function,
181                                    const std::string& message,
182                                    const char *assertion)
[66]183  {
[112]184    throw AssertionFailedError(file, line, function, message.c_str(), assertion);
[66]185  }
186
187/// @}
188
189}
[108]190#endif // LEMON_ASSERT_H
[66]191
192#undef LEMON_ASSERT
193#undef LEMON_FIXME
194
[108]195#if (defined(LEMON_ASSERT_LOG) ? 1 : 0) +               \
196  (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
[112]200#error "LEMON assertion system is not set properly"
[66]201#endif
202
[108]203#if ((defined(LEMON_ASSERT_LOG) ? 1 : 0) +              \
204     (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 ||     \
[112]208     defined(LEMON_ENABLE_ASSERTS)) &&                  \
[108]209  defined(LEMON_DISABLE_ASSERTS)
[112]210#error "LEMON assertion system is not set properly"
[66]211#endif
212
[108]213
214#if defined LEMON_ASSERT_LOG
215#  undef LEMON_ASSERT_HANDLER
216#  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_log
217#elif defined LEMON_ASSERT_ABORT
218#  undef LEMON_ASSERT_HANDLER
219#  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
227#  undef LEMON_ASSERT_HANDLER
228#  ifndef LEMON_CUSTOM_ASSERT_HANDLER
229#    error "LEMON_CUSTOM_ASSERT_HANDLER is not set"
[66]230#  endif
[108]231#  define LEMON_ASSERT_HANDLER LEMON_CUSTOM_ASSERT_HANDLER
232#elif defined LEMON_ENABLE_ASSERTS
233#  undef LEMON_ASSERT_HANDLER
234#  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort
235#else
236#  undef LEMON_ASSERT_HANDLER
237#endif
238
239
240#ifndef LEMON_FUNCTION_NAME
241#  define LEMON_FUNCTION_NAME (__PRETTY_FUNCTION__)
[66]242#endif
243
244#ifdef DOXYGEN
245
[108]246/// \ingroup exceptions
247///
[112]248/// \brief Macro for assertion with customizable message
[66]249///
[112]250/// Macro for assertion with customizable message. 
251/// \param exp An expression that must be convertible to \c bool.
252/// If it is \c false, then an assertion is raised. The concrete
253/// behaviour depends on the settings of the assertion system.
254/// \param msg A <tt>const char*</tt>, a <tt>const std::string&</tt> or
255/// a <tt>const std::exception&</tt> parameter, which can be used to
256/// provide information about the circumstances of the failed assertion.
[66]257///
[112]258/// The assertions are disabled in the default behaviour.
259/// You can enable them with the following code:
[66]260/// \code
261/// #define LEMON_ENABLE_ASSERTS
262/// \endcode
[108]263/// or with compilation parameters:
264/// \code
265/// g++ -DLEMON_ENABLE_ASSERTS
266/// make CXXFLAGS='-DLEMON_ENABLE_ASSERTS'
267/// \endcode
268///
[112]269/// The LEMON assertion system has a wide range of customization
270/// properties. As a default behaviour the failed assertion prints a
271/// short log message to the standard error and aborts the execution.
[66]272///
[108]273/// The following modes can be used in the assertion system:
[66]274///
[112]275/// - \c LEMON_ASSERT_LOG The failed assertion prints a short log
276///   message to the standard error and continues the execution.
277/// - \c LEMON_ASSERT_ABORT This mode is similar to the
278///   \c LEMON_ASSERT_LOG, but it aborts the program. It is the default
279///   behaviour mode when the assertions are enabled with
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
[108]288///   can not be thrown polymorphically), otherwise an \ref
289///   lemon::AssertionFailedError "AssertionFailedError" is thrown with
[112]290///   the given parameters.
291/// - \c LEMON_ASSERT_CUSTOM The user can define own assertion handler
292///   functions. Three overloaded functions should be defined with the
293///   following parameter lists:
[108]294///   \code
[112]295///     void custom_assert_handler(const char* file, int line, const char* function,
296///                                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);
[108]301///   \endcode
302///   The name of the functions should be defined as the \c
303///   LEMON_CUSTOM_ASSERT_HANDLER macro name.
304///   \code
305///     #define LEMON_CUSTOM_ASSERT_HANDLER custom_assert_handler
306///   \endcode
307///   Whenever an assertion is occured, one of the custom assertion
[112]308///   handlers is called with appropiate parameters.
[66]309///
[112]310/// The assertion mode can also be changed within one compilation unit.
311/// If the macros are redefined with other settings and the
312/// \ref lemon/assert.h "assert.h" file is reincluded, then the
313/// behaviour is changed appropiately to the new settings.
[108]314#  define LEMON_ASSERT(exp, msg)                                        \
315  (static_cast<void> (!!(exp) ? 0 : (                                   \
316    LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                            \
317                         LEMON_FUNCTION_NAME,                           \
318                         msg, #exp), 0)))
319
320
321/// \ingroup exceptions
[66]322///
[108]323/// \brief Macro for mark not yet implemented features.
324///
325/// Macro for mark not yet implemented features and outstanding bugs.
326/// It is close to be the shortcut of the following code:
327/// \code
328///   LEMON_ASSERT(false, msg);
329/// \endcode
330#  define LEMON_FIXME(msg)                                              \
331       (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME,   \
332                             "FIXME: " msg, static_cast<const char*>(0)))
[66]333
334#else
335
[108]336#  ifndef LEMON_ASSERT_HANDLER
[112]337#    define LEMON_ASSERT(exp, msg)  (static_cast<void>(0))
[108]338#    define LEMON_FIXME(msg) (static_cast<void>(0))
[66]339#  else
340#    define LEMON_ASSERT(exp, msg)                 \
341       (static_cast<void> (!!(exp) ? 0 : (         \
342         LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \
[108]343                              LEMON_FUNCTION_NAME, \
344                              msg, #exp), 0)))
345#    define LEMON_FIXME(msg) \
346       (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME,   \
347                             "FIXME: " msg,  static_cast<const char*>(0)))
[66]348#  endif
[108]349
[66]350#endif
351
352
Note: See TracBrowser for help on using the repository browser.