lemon/assert.h
changeset 277 7abfb55f1ecc
parent 266 112ed801139d
child 290 f6899946c1ac
equal deleted inserted replaced
8:74b27bba5c3e 9:fe70398a4969
    25 
    25 
    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_abort(const char *file, int line,
    31                               const char *message, const char *assertion)
    31                                 const char *function, const char* message,
       
    32                                 const char *assertion)
    32   {
    33   {
    33     std::cerr << file << ":" << line << ": ";
    34     std::cerr << file << ":" << line << ": ";
    34     if (function)
    35     if (function)
    35       std::cerr << function << ": ";
    36       std::cerr << function << ": ";
    36     std::cerr << message;
    37     std::cerr << message;
    37     if (assertion)
    38     if (assertion)
    38       std::cerr << " (assertion '" << assertion << "' failed)";
    39       std::cerr << " (assertion '" << assertion << "' failed)";
    39     std::cerr << std::endl;
    40     std::cerr << std::endl;
    40   }
       
    41 
       
    42   inline void assert_fail_abort(const char *file, int line,
       
    43                                 const char *function, const char* message,
       
    44                                 const char *assertion)
       
    45   {
       
    46     assert_fail_log(file, line, function, message, assertion);
       
    47     std::abort();
    41     std::abort();
    48   }
    42   }
    49 
    43 
    50   namespace _assert_bits {
    44   namespace _assert_bits {
    51 
    45 
    61 }
    55 }
    62 
    56 
    63 #endif // LEMON_ASSERT_H
    57 #endif // LEMON_ASSERT_H
    64 
    58 
    65 #undef LEMON_ASSERT
    59 #undef LEMON_ASSERT
    66 #undef LEMON_FIXME
       
    67 #undef LEMON_DEBUG
    60 #undef LEMON_DEBUG
    68 
    61 
    69 #if (defined(LEMON_ASSERT_LOG) ? 1 : 0) +               \
    62 #if (defined(LEMON_ASSERT_ABORT) ? 1 : 0) +               \
    70   (defined(LEMON_ASSERT_ABORT) ? 1 : 0) +               \
       
    71   (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) > 1
    63   (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) > 1
    72 #error "LEMON assertion system is not set properly"
    64 #error "LEMON assertion system is not set properly"
    73 #endif
    65 #endif
    74 
    66 
    75 #if ((defined(LEMON_ASSERT_LOG) ? 1 : 0) +              \
    67 #if ((defined(LEMON_ASSERT_ABORT) ? 1 : 0) +            \
    76      (defined(LEMON_ASSERT_ABORT) ? 1 : 0) +            \
       
    77      (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) == 1 ||     \
    68      (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) == 1 ||     \
    78      defined(LEMON_ENABLE_ASSERTS)) &&                  \
    69      defined(LEMON_ENABLE_ASSERTS)) &&                  \
    79   (defined(LEMON_DISABLE_ASSERTS) ||                    \
    70   (defined(LEMON_DISABLE_ASSERTS) ||                    \
    80    defined(NDEBUG))
    71    defined(NDEBUG))
    81 #error "LEMON assertion system is not set properly"
    72 #error "LEMON assertion system is not set properly"
    82 #endif
    73 #endif
    83 
    74 
    84 
    75 
    85 #if defined LEMON_ASSERT_LOG
    76 #if defined LEMON_ASSERT_ABORT
    86 #  undef LEMON_ASSERT_HANDLER
       
    87 #  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_log
       
    88 #elif defined LEMON_ASSERT_ABORT
       
    89 #  undef LEMON_ASSERT_HANDLER
    77 #  undef LEMON_ASSERT_HANDLER
    90 #  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort
    78 #  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort
    91 #elif defined LEMON_ASSERT_CUSTOM
    79 #elif defined LEMON_ASSERT_CUSTOM
    92 #  undef LEMON_ASSERT_HANDLER
    80 #  undef LEMON_ASSERT_HANDLER
    93 #  ifndef LEMON_CUSTOM_ASSERT_HANDLER
    81 #  ifndef LEMON_CUSTOM_ASSERT_HANDLER
   118 
   106 
   119 /// \ingroup exceptions
   107 /// \ingroup exceptions
   120 ///
   108 ///
   121 /// \brief Macro for assertion with customizable message
   109 /// \brief Macro for assertion with customizable message
   122 ///
   110 ///
   123 /// Macro for assertion with customizable message.  \param exp An
   111 /// Macro for assertion with customizable message.  
   124 /// expression that must be convertible to \c bool.  If it is \c
   112 /// \param exp An expression that must be convertible to \c bool.  If it is \c
   125 /// false, then an assertion is raised. The concrete behaviour depends
   113 /// false, then an assertion is raised. The concrete behaviour depends on the
   126 /// on the settings of the assertion system.  \param msg A <tt>const
   114 /// settings of the assertion system.
   127 /// char*</tt> parameter, which can be used to provide information
   115 /// \param msg A <tt>const char*</tt> parameter, which can be used to provide
   128 /// about the circumstances of the failed assertion.
   116 /// information about the circumstances of the failed assertion.
   129 ///
   117 ///
   130 /// The assertions are enabled in the default behaviour.
   118 /// The assertions are enabled in the default behaviour.
   131 /// You can disable them with the following code:
   119 /// You can disable them with the following code:
   132 /// \code
   120 /// \code
   133 /// #define LEMON_DISABLE_ASSERTS
   121 /// #define LEMON_DISABLE_ASSERTS
   137 /// g++ -DLEMON_DISABLE_ASSERTS
   125 /// g++ -DLEMON_DISABLE_ASSERTS
   138 /// make CXXFLAGS='-DLEMON_DISABLE_ASSERTS'
   126 /// make CXXFLAGS='-DLEMON_DISABLE_ASSERTS'
   139 /// \endcode
   127 /// \endcode
   140 /// The checking is also disabled when the standard macro \c NDEBUG is defined.
   128 /// The checking is also disabled when the standard macro \c NDEBUG is defined.
   141 ///
   129 ///
   142 /// The LEMON assertion system has a wide range of customization
   130 /// As a default behaviour the failed assertion prints a short log message to
   143 /// properties. As a default behaviour the failed assertion prints a
   131 /// the standard error and aborts the execution.
   144 /// short log message to the standard error and aborts the execution.
   132 ///
   145 ///
   133 /// However, the following modes can be used in the assertion system:
   146 /// The following modes can be used in the assertion system:
   134 /// - \c LEMON_ASSERT_ABORT The failed assertion prints a short log message to
   147 ///
   135 ///   the standard error and aborts the program. It is the default behaviour.
   148 /// - \c LEMON_ASSERT_LOG The failed assertion prints a short log
       
   149 ///   message to the standard error and continues the execution.
       
   150 /// - \c LEMON_ASSERT_ABORT This mode is similar to the \c
       
   151 ///   LEMON_ASSERT_LOG, but it aborts the program. It is the default
       
   152 ///   behaviour.
       
   153 /// - \c LEMON_ASSERT_CUSTOM The user can define own assertion handler
   136 /// - \c LEMON_ASSERT_CUSTOM The user can define own assertion handler
   154 ///   function.
   137 ///   function.
   155 ///   \code
   138 ///   \code
   156 ///     void custom_assert_handler(const char* file, int line,
   139 ///     void custom_assert_handler(const char* file, int line,
   157 ///                                const char* function, const char* message,
   140 ///                                const char* function, const char* message,
   175                          LEMON_FUNCTION_NAME,                           \
   158                          LEMON_FUNCTION_NAME,                           \
   176                          ::lemon::_assert_bits::cstringify(msg), #exp), 0)))
   159                          ::lemon::_assert_bits::cstringify(msg), #exp), 0)))
   177 
   160 
   178 /// \ingroup exceptions
   161 /// \ingroup exceptions
   179 ///
   162 ///
   180 /// \brief Macro for mark not yet implemented features.
       
   181 ///
       
   182 /// Macro for mark not yet implemented features and outstanding bugs.
       
   183 /// It is close to be the shortcut of the following code:
       
   184 /// \code
       
   185 ///   LEMON_ASSERT(false, msg);
       
   186 /// \endcode
       
   187 ///
       
   188 /// \see LEMON_ASSERT
       
   189 #  define LEMON_FIXME(msg)                                              \
       
   190   (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME,        \
       
   191                         ::lemon::_assert_bits::cstringify(msg),         \
       
   192                         static_cast<const char*>(0)))
       
   193 
       
   194 /// \ingroup exceptions
       
   195 ///
       
   196 /// \brief Macro for internal assertions
   163 /// \brief Macro for internal assertions
   197 ///
   164 ///
   198 /// Macro for internal assertions, it is used in the library to check
   165 /// Macro for internal assertions, it is used in the library to check
   199 /// the consistency of results of algorithms, several pre- and
   166 /// the consistency of results of algorithms, several pre- and
   200 /// postconditions and invariants. The checking is disabled by
   167 /// postconditions and invariants. The checking is disabled by
   222 
   189 
   223 #else
   190 #else
   224 
   191 
   225 #  ifndef LEMON_ASSERT_HANDLER
   192 #  ifndef LEMON_ASSERT_HANDLER
   226 #    define LEMON_ASSERT(exp, msg)  (static_cast<void>(0))
   193 #    define LEMON_ASSERT(exp, msg)  (static_cast<void>(0))
   227 #    define LEMON_FIXME(msg) (static_cast<void>(0))
       
   228 #    define LEMON_DEBUG(exp, msg) (static_cast<void>(0))
   194 #    define LEMON_DEBUG(exp, msg) (static_cast<void>(0))
   229 #  else
   195 #  else
   230 #    define LEMON_ASSERT(exp, msg)                                      \
   196 #    define LEMON_ASSERT(exp, msg)                                      \
   231        (static_cast<void> (!!(exp) ? 0 : (                              \
   197        (static_cast<void> (!!(exp) ? 0 : (                              \
   232         LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                        \
   198         LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                        \
   233                              LEMON_FUNCTION_NAME,                       \
   199                              LEMON_FUNCTION_NAME,                       \
   234                              ::lemon::_assert_bits::cstringify(msg),    \
   200                              ::lemon::_assert_bits::cstringify(msg),    \
   235                              #exp), 0)))
   201                              #exp), 0)))
   236 #    define LEMON_FIXME(msg)                                            \
       
   237        (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME,   \
       
   238                              ::lemon::_assert_bits::cstringify(msg),    \
       
   239                              static_cast<const char*>(0)))
       
   240 
       
   241 #    if LEMON_ENABLE_DEBUG
   202 #    if LEMON_ENABLE_DEBUG
   242 #      define LEMON_DEBUG(exp, msg)                                     \
   203 #      define LEMON_DEBUG(exp, msg)                                     \
   243          (static_cast<void> (!!(exp) ? 0 : (                            \
   204          (static_cast<void> (!!(exp) ? 0 : (                            \
   244            LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                     \
   205            LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                     \
   245                                 LEMON_FUNCTION_NAME,                    \
   206                                 LEMON_FUNCTION_NAME,                    \