lemon/assert.h
changeset 124 ae7785fe8431
parent 112 d2ee5e7f00ef
child 142 8b703d177341
     1.1 --- a/lemon/assert.h	Tue Apr 08 22:51:26 2008 +0200
     1.2 +++ b/lemon/assert.h	Sat Apr 12 20:38:51 2008 +0100
     1.3 @@ -27,71 +27,6 @@
     1.4  
     1.5  namespace lemon {
     1.6  
     1.7 -  /// @{
     1.8 -
     1.9 -  ///\e
    1.10 -  class AssertionFailedError : public LogicError {
    1.11 -  protected:
    1.12 -    const char *_assertion;
    1.13 -    const char *_file;
    1.14 -    int _line;
    1.15 -    const char *_function;
    1.16 -    const char *_message;
    1.17 -
    1.18 -    mutable ExceptionMember<std::string> _message_holder;
    1.19 -  public:
    1.20 -    ///\e
    1.21 -    AssertionFailedError(const char *file, int line, const char *function,
    1.22 -			 const char *msg, const char *assertion = 0) :
    1.23 -      _assertion(assertion), _file(file), _line(line), 
    1.24 -      _function(function), _message(msg) {}
    1.25 -
    1.26 -    ///\e
    1.27 -    const char* assertion() const { return _assertion; }
    1.28 -    ///\e
    1.29 -    const char* message() const { return _message; }
    1.30 -    ///\e
    1.31 -    const char* file() const { return _file; }
    1.32 -    ///\e
    1.33 -    const char* function() const { return _function; }
    1.34 -    ///\e
    1.35 -    int line() const { return _line; }
    1.36 -
    1.37 -
    1.38 -    virtual const char* what() const throw() {
    1.39 -      try {
    1.40 -	std::ostringstream ostr;
    1.41 -	ostr << _file << ":" << _line << ": ";
    1.42 -	if (_function)
    1.43 -	  ostr << _function << ": ";
    1.44 -	ostr << _message;
    1.45 -	if (_assertion)
    1.46 -	   ostr << " (assertion '" << _assertion << "' failed)";
    1.47 -	_message_holder.set(ostr.str());
    1.48 -	return ostr.str().c_str();
    1.49 -      }
    1.50 -      catch(...) {}
    1.51 -      if( _message_holder.valid() ) return _message_holder.get().c_str();
    1.52 -      return "lemon::AssertionFailedError";
    1.53 -    }
    1.54 -    virtual ~AssertionFailedError() throw() {}
    1.55 -  };
    1.56 -
    1.57 -
    1.58 -  inline void assert_fail_log(const char *file, int line,
    1.59 -			      const char *function,
    1.60 -			      const std::exception& exception, 
    1.61 -			      const char *assertion)
    1.62 -  {
    1.63 -    std::cerr << file << ":" << line << ": ";
    1.64 -    if (function)
    1.65 -      std::cerr << function << ": ";
    1.66 -    std::cerr << exception.what();
    1.67 -    if (assertion)
    1.68 -      std::cerr << " (assertion '" << assertion << "' failed)";
    1.69 -    std::cerr << std::endl;
    1.70 -  }
    1.71 -
    1.72    inline void assert_fail_log(const char *file, int line, const char *function,
    1.73  			      const char *message, const char *assertion)
    1.74    {
    1.75 @@ -104,21 +39,6 @@
    1.76      std::cerr << std::endl;
    1.77    }
    1.78  
    1.79 -  inline void assert_fail_log(const char *file, int line, const char *function, 
    1.80 -			      const std::string& message, const char *assertion)
    1.81 -  {
    1.82 -    assert_fail_log(file, line, function, message.c_str(), assertion);
    1.83 -  }
    1.84 -
    1.85 -  inline void assert_fail_abort(const char *file, int line, 
    1.86 -				const char *function,
    1.87 -				const std::exception& exception,
    1.88 -				const char *assertion)
    1.89 -  {
    1.90 -    assert_fail_log(file, line, function, exception, assertion);
    1.91 -    std::abort();
    1.92 -  }
    1.93 -
    1.94    inline void assert_fail_abort(const char *file, int line,
    1.95  				const char *function, const char* message,
    1.96  				const char *assertion)
    1.97 @@ -127,86 +47,37 @@
    1.98      std::abort();
    1.99    }
   1.100  
   1.101 -  inline void assert_fail_abort(const char *file, int line, 
   1.102 -				const char *function, 
   1.103 -				const std::string& message,
   1.104 -				const char *assertion)
   1.105 -  {
   1.106 -    assert_fail_log(file, line, function, message.c_str(), assertion);
   1.107 -    std::abort();
   1.108 +  namespace _assert_bits {
   1.109 +    
   1.110 +    
   1.111 +    inline const char* cstringify(const std::string& str) {
   1.112 +      return str.c_str();
   1.113 +    }
   1.114 +
   1.115 +    inline const char* cstringify(const char* str) {
   1.116 +      return str;
   1.117 +    }    
   1.118    }
   1.119 +}
   1.120  
   1.121 -  inline void assert_fail_error(const char *file, int line, 
   1.122 -				  const char *function,
   1.123 -				  const std::exception& exception,
   1.124 -				  const char *assertion)
   1.125 -  {
   1.126 -    throw AssertionFailedError(file, line, function, 
   1.127 -			       exception.what(), assertion);
   1.128 -  }
   1.129 -
   1.130 -  inline void assert_fail_error(const char *file, int line,
   1.131 -				  const char *function, const char *message,
   1.132 -				  const char *assertion)
   1.133 -  {
   1.134 -    throw AssertionFailedError(file, line, function, message, assertion);
   1.135 -  }
   1.136 -
   1.137 -  inline void assert_fail_error(const char *file, int line,
   1.138 -				  const char *function, 
   1.139 -				  const std::string& message,
   1.140 -				  const char *assertion)
   1.141 -  {
   1.142 -    throw AssertionFailedError(file, line, function, message.c_str(), assertion);
   1.143 -  }
   1.144 -
   1.145 -  template <typename Exception>
   1.146 -  inline void assert_fail_exception(const char *, int, const char *,
   1.147 -				    const Exception& exception,
   1.148 -				    const char *, const std::exception* = 
   1.149 -				    static_cast<const Exception*>(0))
   1.150 -  {
   1.151 -    throw exception;
   1.152 -  }
   1.153 -
   1.154 -  inline void assert_fail_exception(const char *file, int line,
   1.155 -				    const char *function, const char *message,
   1.156 -				    const char *assertion)
   1.157 -  {
   1.158 -    throw AssertionFailedError(file, line, function, message, assertion);
   1.159 -  }
   1.160 -
   1.161 -  inline void assert_fail_exception(const char *file, int line, 
   1.162 -				    const char *function, 
   1.163 -				    const std::string& message,
   1.164 -				    const char *assertion)
   1.165 -  {
   1.166 -    throw AssertionFailedError(file, line, function, message.c_str(), assertion);
   1.167 -  }
   1.168 -
   1.169 -/// @}
   1.170 -
   1.171 -}
   1.172  #endif // LEMON_ASSERT_H
   1.173  
   1.174  #undef LEMON_ASSERT
   1.175  #undef LEMON_FIXME
   1.176 +#undef LEMON_DEBUG
   1.177  
   1.178  #if (defined(LEMON_ASSERT_LOG) ? 1 : 0) +		\
   1.179    (defined(LEMON_ASSERT_ABORT) ? 1 : 0) +		\
   1.180 -  (defined(LEMON_ASSERT_ERROR) ? 1 : 0) +		\
   1.181 -  (defined(LEMON_ASSERT_EXCEPTION) ? 1 : 0) +		\
   1.182    (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) > 1
   1.183  #error "LEMON assertion system is not set properly"
   1.184  #endif
   1.185  
   1.186  #if ((defined(LEMON_ASSERT_LOG) ? 1 : 0) +		\
   1.187       (defined(LEMON_ASSERT_ABORT) ? 1 : 0) +		\
   1.188 -     (defined(LEMON_ASSERT_ERROR) ? 1 : 0) +		\
   1.189 -     (defined(LEMON_ASSERT_EXCEPTION) ? 1 : 0) +	\
   1.190       (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) == 1 ||	\
   1.191       defined(LEMON_ENABLE_ASSERTS)) &&			\
   1.192 -  defined(LEMON_DISABLE_ASSERTS)
   1.193 +  (defined(LEMON_DISABLE_ASSERTS) ||			\
   1.194 +   defined(NDEBUG))
   1.195  #error "LEMON assertion system is not set properly"
   1.196  #endif
   1.197  
   1.198 @@ -217,26 +88,20 @@
   1.199  #elif defined LEMON_ASSERT_ABORT
   1.200  #  undef LEMON_ASSERT_HANDLER
   1.201  #  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort
   1.202 -#elif defined LEMON_ASSERT_ERROR
   1.203 -#  undef LEMON_ASSERT_HANDLER
   1.204 -#  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_error
   1.205 -#elif defined LEMON_ASSERT_EXCEPTION
   1.206 -#  undef LEMON_ASSERT_HANDLER
   1.207 -#  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_exception
   1.208  #elif defined LEMON_ASSERT_CUSTOM
   1.209  #  undef LEMON_ASSERT_HANDLER
   1.210  #  ifndef LEMON_CUSTOM_ASSERT_HANDLER
   1.211  #    error "LEMON_CUSTOM_ASSERT_HANDLER is not set"
   1.212  #  endif
   1.213  #  define LEMON_ASSERT_HANDLER LEMON_CUSTOM_ASSERT_HANDLER
   1.214 -#elif defined LEMON_ENABLE_ASSERTS
   1.215 +#elif defined LEMON_DISABLE_ASSERTS
   1.216  #  undef LEMON_ASSERT_HANDLER
   1.217 +#elif defined NDEBUG
   1.218 +#  undef LEMON_ASSERT_HANDLER
   1.219 +#else
   1.220  #  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort
   1.221 -#else
   1.222 -#  undef LEMON_ASSERT_HANDLER
   1.223  #endif
   1.224  
   1.225 -
   1.226  #ifndef LEMON_FUNCTION_NAME
   1.227  #  define LEMON_FUNCTION_NAME (__PRETTY_FUNCTION__)
   1.228  #endif
   1.229 @@ -247,24 +112,24 @@
   1.230  ///
   1.231  /// \brief Macro for assertion with customizable message
   1.232  ///
   1.233 -/// Macro for assertion with customizable message.  
   1.234 -/// \param exp An expression that must be convertible to \c bool.
   1.235 -/// If it is \c false, then an assertion is raised. The concrete
   1.236 -/// behaviour depends on the settings of the assertion system.
   1.237 -/// \param msg A <tt>const char*</tt>, a <tt>const std::string&</tt> or
   1.238 -/// a <tt>const std::exception&</tt> parameter, which can be used to
   1.239 -/// provide information about the circumstances of the failed assertion.
   1.240 +/// Macro for assertion with customizable message.  \param exp An
   1.241 +/// expression that must be convertible to \c bool.  If it is \c
   1.242 +/// false, then an assertion is raised. The concrete behaviour depends
   1.243 +/// on the settings of the assertion system.  \param msg A <tt>const
   1.244 +/// char*</tt> parameter, which can be used to provide information
   1.245 +/// about the circumstances of the failed assertion.
   1.246  ///
   1.247 -/// The assertions are disabled in the default behaviour.
   1.248 -/// You can enable them with the following code:
   1.249 +/// The assertions are enabled in the default behaviour.
   1.250 +/// You can disable them with the following code:
   1.251  /// \code
   1.252 -/// #define LEMON_ENABLE_ASSERTS
   1.253 +/// #define LEMON_DISABLE_ASSERTS
   1.254  /// \endcode
   1.255  /// or with compilation parameters:
   1.256  /// \code
   1.257 -/// g++ -DLEMON_ENABLE_ASSERTS
   1.258 -/// make CXXFLAGS='-DLEMON_ENABLE_ASSERTS'
   1.259 +/// g++ -DLEMON_DISABLE_ASSERTS
   1.260 +/// make CXXFLAGS='-DLEMON_DISABLE_ASSERTS'
   1.261  /// \endcode
   1.262 +/// The checking is also disabled when the standard macro \c NDEBUG is defined.
   1.263  /// 
   1.264  /// The LEMON assertion system has a wide range of customization
   1.265  /// properties. As a default behaviour the failed assertion prints a
   1.266 @@ -274,38 +139,22 @@
   1.267  ///
   1.268  /// - \c LEMON_ASSERT_LOG The failed assertion prints a short log
   1.269  ///   message to the standard error and continues the execution.
   1.270 -/// - \c LEMON_ASSERT_ABORT This mode is similar to the
   1.271 -///   \c LEMON_ASSERT_LOG, but it aborts the program. It is the default
   1.272 -///   behaviour mode when the assertions are enabled with
   1.273 -///   \c LEMON_ENABLE_ASSERTS.
   1.274 -/// - \c LEMON_ASSERT_ERROR The assertion throws an
   1.275 -///   \ref lemon::AssertionFailedError "AssertionFailedError".
   1.276 -///   If the \c msg parameter is an exception, then the result of the
   1.277 -///   \ref lemon::Exception::what() "what()" member function is passed
   1.278 -///   as error message.
   1.279 -/// - \c LEMON_ASSERT_EXCEPTION If the specified \c msg is an
   1.280 -///   exception, then it raised directly (solving that the exception
   1.281 -///   can not be thrown polymorphically), otherwise an \ref
   1.282 -///   lemon::AssertionFailedError "AssertionFailedError" is thrown with
   1.283 -///   the given parameters.
   1.284 +/// - \c LEMON_ASSERT_ABORT This mode is similar to the \c
   1.285 +///   LEMON_ASSERT_LOG, but it aborts the program. It is the default
   1.286 +///   behaviour.
   1.287  /// - \c LEMON_ASSERT_CUSTOM The user can define own assertion handler
   1.288 -///   functions. Three overloaded functions should be defined with the
   1.289 -///   following parameter lists:
   1.290 +///   function.
   1.291  ///   \code
   1.292  ///     void custom_assert_handler(const char* file, int line, const char* function,
   1.293  ///                                const char* message, const char* assertion);
   1.294 -///     void custom_assert_handler(const char* file, int line, const char* function,
   1.295 -///                                const std::string& message, const char* assertion);
   1.296 -///     void custom_assert_handler(const char* file, int line, const char* function,
   1.297 -///                                const std::exception& message, const char* assertion);
   1.298  ///   \endcode
   1.299 -///   The name of the functions should be defined as the \c
   1.300 +///   The name of the function should be defined as the \c
   1.301  ///   LEMON_CUSTOM_ASSERT_HANDLER macro name. 
   1.302  ///   \code
   1.303  ///     #define LEMON_CUSTOM_ASSERT_HANDLER custom_assert_handler
   1.304  ///   \endcode
   1.305 -///   Whenever an assertion is occured, one of the custom assertion
   1.306 -///   handlers is called with appropiate parameters.
   1.307 +///   Whenever an assertion is occured, the custom assertion
   1.308 +///   handler is called with appropiate parameters.
   1.309  ///
   1.310  /// The assertion mode can also be changed within one compilation unit.
   1.311  /// If the macros are redefined with other settings and the
   1.312 @@ -315,8 +164,7 @@
   1.313    (static_cast<void> (!!(exp) ? 0 : (					\
   1.314      LEMON_ASSERT_HANDLER(__FILE__, __LINE__,				\
   1.315  			 LEMON_FUNCTION_NAME,				\
   1.316 -			 msg, #exp), 0)))
   1.317 -
   1.318 +			 ::lemon::_assert_bits::cstringify(msg), #exp), 0)))
   1.319  
   1.320  /// \ingroup exceptions
   1.321  ///
   1.322 @@ -327,26 +175,80 @@
   1.323  /// \code
   1.324  ///   LEMON_ASSERT(false, msg);
   1.325  /// \endcode
   1.326 +///
   1.327 +/// \see LEMON_ASSERT 
   1.328  #  define LEMON_FIXME(msg)						\
   1.329 -       (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME,	\
   1.330 -			     "FIXME: " msg, static_cast<const char*>(0)))
   1.331 +  (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME,	\
   1.332 +			::lemon::_assert_bits::cstringify(msg),		\
   1.333 +			static_cast<const char*>(0)))
   1.334 +
   1.335 +/// \ingroup exceptions
   1.336 +///
   1.337 +/// \brief Macro for internal assertions
   1.338 +///
   1.339 +/// Macro for internal assertions, it is used in the library to check
   1.340 +/// the consistency of results of algorithms, several pre- and
   1.341 +/// postconditions and invariants. The checking is disabled by
   1.342 +/// default, but it can be turned on with the macro \c
   1.343 +/// LEMON_ENABLE_DEBUG.
   1.344 +/// \code
   1.345 +/// #define LEMON_ENABLE_DEBUG
   1.346 +/// \endcode
   1.347 +/// or with compilation parameters:
   1.348 +/// \code
   1.349 +/// g++ -DLEMON_ENABLE_DEBUG
   1.350 +/// make CXXFLAGS='-DLEMON_ENABLE_DEBUG'
   1.351 +/// \endcode
   1.352 +///
   1.353 +/// This macro works like the \c LEMON_ASSERT macro, therefore the
   1.354 +/// current behaviour depends on the settings of \c LEMON_ASSERT
   1.355 +/// macro.
   1.356 +///
   1.357 +/// \see LEMON_ASSERT 
   1.358 +#  define LEMON_DEBUG(exp, msg)						\
   1.359 +  (static_cast<void> (!!(exp) ? 0 : (					\
   1.360 +    LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                            \
   1.361 +			 LEMON_FUNCTION_NAME,				\
   1.362 +			 ::lemon::_assert_bits::cstringify(msg), #exp), 0)))
   1.363  
   1.364  #else
   1.365  
   1.366  #  ifndef LEMON_ASSERT_HANDLER
   1.367  #    define LEMON_ASSERT(exp, msg)  (static_cast<void>(0))
   1.368  #    define LEMON_FIXME(msg) (static_cast<void>(0))
   1.369 +#    define LEMON_DEBUG(exp, msg) (static_cast<void>(0))
   1.370  #  else
   1.371 -#    define LEMON_ASSERT(exp, msg)                 \
   1.372 -       (static_cast<void> (!!(exp) ? 0 : (         \
   1.373 -         LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \
   1.374 -                              LEMON_FUNCTION_NAME, \
   1.375 -                              msg, #exp), 0)))
   1.376 -#    define LEMON_FIXME(msg) \
   1.377 +#    define LEMON_ASSERT(exp, msg)					\
   1.378 +       (static_cast<void> (!!(exp) ? 0 : (				\
   1.379 +        LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                        \
   1.380 +			     LEMON_FUNCTION_NAME,			\
   1.381 +			     ::lemon::_assert_bits::cstringify(msg),	\
   1.382 +			     #exp), 0)))
   1.383 +#    define LEMON_FIXME(msg)						\
   1.384         (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME,	\
   1.385 -			     "FIXME: " msg,  static_cast<const char*>(0)))
   1.386 +			     ::lemon::_assert_bits::cstringify(msg),	\
   1.387 +			     static_cast<const char*>(0)))
   1.388 +
   1.389 +#    if LEMON_ENABLE_DEBUG
   1.390 +#      define LEMON_DEBUG(exp, msg)
   1.391 +         (static_cast<void> (!!(exp) ? 0 : (         \
   1.392 +           LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \
   1.393 +                                LEMON_FUNCTION_NAME, \
   1.394 +				::lemon::_assert_bits::cstringify(msg),	\
   1.395 +				#exp), 0)))
   1.396 +#    else
   1.397 +#      define LEMON_DEBUG(exp, msg) (static_cast<void>(0))
   1.398 +#    endif
   1.399  #  endif
   1.400  
   1.401  #endif
   1.402  
   1.403 +#ifdef DOXYGEN
   1.404  
   1.405 +
   1.406 +#else
   1.407 +
   1.408 +
   1.409 +#endif
   1.410 +
   1.411 +