lemon/assert.h
changeset 209 765619b7cbb2
parent 142 8b703d177341
child 210 81cfc04531e8
equal deleted inserted replaced
3:3f0e1f9ec054 4:3f1f13ef82cd
     1 /* -*- C++ -*-
     1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
     2  *
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library
     3  * This file is a part of LEMON, a generic C++ optimization library.
     4  *
     4  *
     5  * Copyright (C) 2003-2008
     5  * Copyright (C) 2003-2008
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     8  *
     8  *
    26 #include <lemon/error.h>
    26 #include <lemon/error.h>
    27 
    27 
    28 namespace lemon {
    28 namespace lemon {
    29 
    29 
    30   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,
    31 			      const char *message, const char *assertion)
    31                               const char *message, const char *assertion)
    32   {
    32   {
    33     std::cerr << file << ":" << line << ": ";
    33     std::cerr << file << ":" << line << ": ";
    34     if (function)
    34     if (function)
    35       std::cerr << function << ": ";
    35       std::cerr << function << ": ";
    36     std::cerr << message;
    36     std::cerr << message;
    38       std::cerr << " (assertion '" << assertion << "' failed)";
    38       std::cerr << " (assertion '" << assertion << "' failed)";
    39     std::cerr << std::endl;
    39     std::cerr << std::endl;
    40   }
    40   }
    41 
    41 
    42   inline void assert_fail_abort(const char *file, int line,
    42   inline void assert_fail_abort(const char *file, int line,
    43 				const char *function, const char* message,
    43                                 const char *function, const char* message,
    44 				const char *assertion)
    44                                 const char *assertion)
    45   {
    45   {
    46     assert_fail_log(file, line, function, message, assertion);
    46     assert_fail_log(file, line, function, message, assertion);
    47     std::abort();
    47     std::abort();
    48   }
    48   }
    49 
    49 
    50   namespace _assert_bits {
    50   namespace _assert_bits {
    51     
    51 
    52     
    52 
    53     inline const char* cstringify(const std::string& str) {
    53     inline const char* cstringify(const std::string& str) {
    54       return str.c_str();
    54       return str.c_str();
    55     }
    55     }
    56 
    56 
    57     inline const char* cstringify(const char* str) {
    57     inline const char* cstringify(const char* str) {
    58       return str;
    58       return str;
    59     }    
    59     }
    60   }
    60   }
    61 }
    61 }
    62 
    62 
    63 #endif // LEMON_ASSERT_H
    63 #endif // LEMON_ASSERT_H
    64 
    64 
    65 #undef LEMON_ASSERT
    65 #undef LEMON_ASSERT
    66 #undef LEMON_FIXME
    66 #undef LEMON_FIXME
    67 #undef LEMON_DEBUG
    67 #undef LEMON_DEBUG
    68 
    68 
    69 #if (defined(LEMON_ASSERT_LOG) ? 1 : 0) +		\
    69 #if (defined(LEMON_ASSERT_LOG) ? 1 : 0) +                \
    70   (defined(LEMON_ASSERT_ABORT) ? 1 : 0) +		\
    70   (defined(LEMON_ASSERT_ABORT) ? 1 : 0) +                \
    71   (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) > 1
    71   (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) > 1
    72 #error "LEMON assertion system is not set properly"
    72 #error "LEMON assertion system is not set properly"
    73 #endif
    73 #endif
    74 
    74 
    75 #if ((defined(LEMON_ASSERT_LOG) ? 1 : 0) +		\
    75 #if ((defined(LEMON_ASSERT_LOG) ? 1 : 0) +                \
    76      (defined(LEMON_ASSERT_ABORT) ? 1 : 0) +		\
    76      (defined(LEMON_ASSERT_ABORT) ? 1 : 0) +                \
    77      (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) == 1 ||	\
    77      (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) == 1 ||        \
    78      defined(LEMON_ENABLE_ASSERTS)) &&			\
    78      defined(LEMON_ENABLE_ASSERTS)) &&                        \
    79   (defined(LEMON_DISABLE_ASSERTS) ||			\
    79   (defined(LEMON_DISABLE_ASSERTS) ||                        \
    80    defined(NDEBUG))
    80    defined(NDEBUG))
    81 #error "LEMON assertion system is not set properly"
    81 #error "LEMON assertion system is not set properly"
    82 #endif
    82 #endif
    83 
    83 
    84 
    84 
   134 /// \code
   134 /// \code
   135 /// g++ -DLEMON_DISABLE_ASSERTS
   135 /// g++ -DLEMON_DISABLE_ASSERTS
   136 /// make CXXFLAGS='-DLEMON_DISABLE_ASSERTS'
   136 /// make CXXFLAGS='-DLEMON_DISABLE_ASSERTS'
   137 /// \endcode
   137 /// \endcode
   138 /// The checking is also disabled when the standard macro \c NDEBUG is defined.
   138 /// The checking is also disabled when the standard macro \c NDEBUG is defined.
   139 /// 
   139 ///
   140 /// The LEMON assertion system has a wide range of customization
   140 /// The LEMON assertion system has a wide range of customization
   141 /// properties. As a default behaviour the failed assertion prints a
   141 /// properties. As a default behaviour the failed assertion prints a
   142 /// short log message to the standard error and aborts the execution.
   142 /// short log message to the standard error and aborts the execution.
   143 ///
   143 ///
   144 /// The following modes can be used in the assertion system: 
   144 /// The following modes can be used in the assertion system:
   145 ///
   145 ///
   146 /// - \c LEMON_ASSERT_LOG The failed assertion prints a short log
   146 /// - \c LEMON_ASSERT_LOG The failed assertion prints a short log
   147 ///   message to the standard error and continues the execution.
   147 ///   message to the standard error and continues the execution.
   148 /// - \c LEMON_ASSERT_ABORT This mode is similar to the \c
   148 /// - \c LEMON_ASSERT_ABORT This mode is similar to the \c
   149 ///   LEMON_ASSERT_LOG, but it aborts the program. It is the default
   149 ///   LEMON_ASSERT_LOG, but it aborts the program. It is the default
   153 ///   \code
   153 ///   \code
   154 ///     void custom_assert_handler(const char* file, int line, const char* function,
   154 ///     void custom_assert_handler(const char* file, int line, const char* function,
   155 ///                                const char* message, const char* assertion);
   155 ///                                const char* message, const char* assertion);
   156 ///   \endcode
   156 ///   \endcode
   157 ///   The name of the function should be defined as the \c
   157 ///   The name of the function should be defined as the \c
   158 ///   LEMON_CUSTOM_ASSERT_HANDLER macro name. 
   158 ///   LEMON_CUSTOM_ASSERT_HANDLER macro name.
   159 ///   \code
   159 ///   \code
   160 ///     #define LEMON_CUSTOM_ASSERT_HANDLER custom_assert_handler
   160 ///     #define LEMON_CUSTOM_ASSERT_HANDLER custom_assert_handler
   161 ///   \endcode
   161 ///   \endcode
   162 ///   Whenever an assertion is occured, the custom assertion
   162 ///   Whenever an assertion is occured, the custom assertion
   163 ///   handler is called with appropiate parameters.
   163 ///   handler is called with appropiate parameters.
   164 ///
   164 ///
   165 /// The assertion mode can also be changed within one compilation unit.
   165 /// The assertion mode can also be changed within one compilation unit.
   166 /// If the macros are redefined with other settings and the
   166 /// If the macros are redefined with other settings and the
   167 /// \ref lemon/assert.h "assert.h" file is reincluded, then the
   167 /// \ref lemon/assert.h "assert.h" file is reincluded, then the
   168 /// behaviour is changed appropiately to the new settings.
   168 /// behaviour is changed appropiately to the new settings.
   169 #  define LEMON_ASSERT(exp, msg)					\
   169 #  define LEMON_ASSERT(exp, msg)                                        \
   170   (static_cast<void> (!!(exp) ? 0 : (					\
   170   (static_cast<void> (!!(exp) ? 0 : (                                        \
   171     LEMON_ASSERT_HANDLER(__FILE__, __LINE__,				\
   171     LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                                \
   172 			 LEMON_FUNCTION_NAME,				\
   172                          LEMON_FUNCTION_NAME,                                \
   173 			 ::lemon::_assert_bits::cstringify(msg), #exp), 0)))
   173                          ::lemon::_assert_bits::cstringify(msg), #exp), 0)))
   174 
   174 
   175 /// \ingroup exceptions
   175 /// \ingroup exceptions
   176 ///
   176 ///
   177 /// \brief Macro for mark not yet implemented features.
   177 /// \brief Macro for mark not yet implemented features.
   178 ///
   178 ///
   180 /// It is close to be the shortcut of the following code:
   180 /// It is close to be the shortcut of the following code:
   181 /// \code
   181 /// \code
   182 ///   LEMON_ASSERT(false, msg);
   182 ///   LEMON_ASSERT(false, msg);
   183 /// \endcode
   183 /// \endcode
   184 ///
   184 ///
   185 /// \see LEMON_ASSERT 
   185 /// \see LEMON_ASSERT
   186 #  define LEMON_FIXME(msg)						\
   186 #  define LEMON_FIXME(msg)                                                \
   187   (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME,	\
   187   (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME,        \
   188 			::lemon::_assert_bits::cstringify(msg),		\
   188                         ::lemon::_assert_bits::cstringify(msg),                \
   189 			static_cast<const char*>(0)))
   189                         static_cast<const char*>(0)))
   190 
   190 
   191 /// \ingroup exceptions
   191 /// \ingroup exceptions
   192 ///
   192 ///
   193 /// \brief Macro for internal assertions
   193 /// \brief Macro for internal assertions
   194 ///
   194 ///
   208 ///
   208 ///
   209 /// This macro works like the \c LEMON_ASSERT macro, therefore the
   209 /// This macro works like the \c LEMON_ASSERT macro, therefore the
   210 /// current behaviour depends on the settings of \c LEMON_ASSERT
   210 /// current behaviour depends on the settings of \c LEMON_ASSERT
   211 /// macro.
   211 /// macro.
   212 ///
   212 ///
   213 /// \see LEMON_ASSERT 
   213 /// \see LEMON_ASSERT
   214 #  define LEMON_DEBUG(exp, msg)						\
   214 #  define LEMON_DEBUG(exp, msg)                                                \
   215   (static_cast<void> (!!(exp) ? 0 : (					\
   215   (static_cast<void> (!!(exp) ? 0 : (                                        \
   216     LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                            \
   216     LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                            \
   217 			 LEMON_FUNCTION_NAME,				\
   217                          LEMON_FUNCTION_NAME,                                \
   218 			 ::lemon::_assert_bits::cstringify(msg), #exp), 0)))
   218                          ::lemon::_assert_bits::cstringify(msg), #exp), 0)))
   219 
   219 
   220 #else
   220 #else
   221 
   221 
   222 #  ifndef LEMON_ASSERT_HANDLER
   222 #  ifndef LEMON_ASSERT_HANDLER
   223 #    define LEMON_ASSERT(exp, msg)  (static_cast<void>(0))
   223 #    define LEMON_ASSERT(exp, msg)  (static_cast<void>(0))
   224 #    define LEMON_FIXME(msg) (static_cast<void>(0))
   224 #    define LEMON_FIXME(msg) (static_cast<void>(0))
   225 #    define LEMON_DEBUG(exp, msg) (static_cast<void>(0))
   225 #    define LEMON_DEBUG(exp, msg) (static_cast<void>(0))
   226 #  else
   226 #  else
   227 #    define LEMON_ASSERT(exp, msg)					\
   227 #    define LEMON_ASSERT(exp, msg)                                        \
   228        (static_cast<void> (!!(exp) ? 0 : (				\
   228        (static_cast<void> (!!(exp) ? 0 : (                                \
   229         LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                        \
   229         LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                        \
   230 			     LEMON_FUNCTION_NAME,			\
   230                              LEMON_FUNCTION_NAME,                        \
   231 			     ::lemon::_assert_bits::cstringify(msg),	\
   231                              ::lemon::_assert_bits::cstringify(msg),        \
   232 			     #exp), 0)))
   232                              #exp), 0)))
   233 #    define LEMON_FIXME(msg)						\
   233 #    define LEMON_FIXME(msg)                                                \
   234        (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME,	\
   234        (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME,        \
   235 			     ::lemon::_assert_bits::cstringify(msg),	\
   235                              ::lemon::_assert_bits::cstringify(msg),        \
   236 			     static_cast<const char*>(0)))
   236                              static_cast<const char*>(0)))
   237 
   237 
   238 #    if LEMON_ENABLE_DEBUG
   238 #    if LEMON_ENABLE_DEBUG
   239 #      define LEMON_DEBUG(exp, msg)
   239 #      define LEMON_DEBUG(exp, msg)
   240          (static_cast<void> (!!(exp) ? 0 : (         \
   240          (static_cast<void> (!!(exp) ? 0 : (         \
   241            LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \
   241            LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \
   242                                 LEMON_FUNCTION_NAME, \
   242                                 LEMON_FUNCTION_NAME, \
   243 				::lemon::_assert_bits::cstringify(msg),	\
   243                                 ::lemon::_assert_bits::cstringify(msg),        \
   244 				#exp), 0)))
   244                                 #exp), 0)))
   245 #    else
   245 #    else
   246 #      define LEMON_DEBUG(exp, msg) (static_cast<void>(0))
   246 #      define LEMON_DEBUG(exp, msg) (static_cast<void>(0))
   247 #    endif
   247 #    endif
   248 #  endif
   248 #  endif
   249 
   249