lemon/assert.h
author Alpar Juttner <alpar@cs.elte.hu>
Thu, 25 Feb 2021 09:46:12 +0100
changeset 1209 4a170261cc54
parent 1072 0e30f63d45d0
permissions -rw-r--r--
Merge #638
     1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library.
     4  *
     5  * Copyright (C) 2003-2013
     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 
    28 namespace lemon {
    29 
    30   inline void assert_fail_abort(const char *file, int line,
    31                                 const char *function, const char* message,
    32                                 const char *assertion)
    33   {
    34     std::cerr << file << ":" << line << ": ";
    35     if (function)
    36       std::cerr << function << ": ";
    37     std::cerr << message;
    38     if (assertion)
    39       std::cerr << " (assertion '" << assertion << "' failed)";
    40     std::cerr << std::endl;
    41     std::abort();
    42   }
    43 
    44   namespace _assert_bits {
    45 
    46 
    47     inline const char* cstringify(const std::string& str) {
    48       return str.c_str();
    49     }
    50 
    51     inline const char* cstringify(const char* str) {
    52       return str;
    53     }
    54   }
    55 }
    56 
    57 #endif // LEMON_ASSERT_H
    58 
    59 #undef LEMON_ASSERT
    60 #undef LEMON_DEBUG
    61 
    62 #if (defined(LEMON_ASSERT_ABORT) ? 1 : 0) +               \
    63   (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) > 1
    64 #error "LEMON assertion system is not set properly"
    65 #endif
    66 
    67 #if ((defined(LEMON_ASSERT_ABORT) ? 1 : 0) +            \
    68      (defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) == 1 ||     \
    69      defined(LEMON_ENABLE_ASSERTS)) &&                  \
    70   (defined(LEMON_DISABLE_ASSERTS) ||                    \
    71    defined(NDEBUG))
    72 #error "LEMON assertion system is not set properly"
    73 #endif
    74 
    75 
    76 #if defined LEMON_ASSERT_ABORT
    77 #  undef LEMON_ASSERT_HANDLER
    78 #  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort
    79 #elif defined LEMON_ASSERT_CUSTOM
    80 #  undef LEMON_ASSERT_HANDLER
    81 #  ifndef LEMON_CUSTOM_ASSERT_HANDLER
    82 #    error "LEMON_CUSTOM_ASSERT_HANDLER is not set"
    83 #  endif
    84 #  define LEMON_ASSERT_HANDLER LEMON_CUSTOM_ASSERT_HANDLER
    85 #elif defined LEMON_DISABLE_ASSERTS
    86 #  undef LEMON_ASSERT_HANDLER
    87 #elif defined NDEBUG
    88 #  undef LEMON_ASSERT_HANDLER
    89 #else
    90 #  define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort
    91 #endif
    92 
    93 #ifndef LEMON_FUNCTION_NAME
    94 #  if defined __GNUC__
    95 #    define LEMON_FUNCTION_NAME (__PRETTY_FUNCTION__)
    96 #  elif defined _MSC_VER
    97 #    define LEMON_FUNCTION_NAME (__FUNCSIG__)
    98 #  elif __STDC_VERSION__ >= 199901L
    99 #    define LEMON_FUNCTION_NAME (__func__)
   100 #  else
   101 #    define LEMON_FUNCTION_NAME ("<unknown>")
   102 #  endif
   103 #endif
   104 
   105 #ifdef DOXYGEN
   106 
   107 /// \ingroup exceptions
   108 ///
   109 /// \brief Macro for assertion with customizable message
   110 ///
   111 /// Macro for assertion with customizable message.
   112 /// \param exp An expression that must be convertible to \c bool.  If it is \c
   113 /// false, then an assertion is raised. The concrete behaviour depends on the
   114 /// settings of the assertion system.
   115 /// \param msg A <tt>const char*</tt> parameter, which can be used to provide
   116 /// information about the circumstances of the failed assertion.
   117 ///
   118 /// The assertions are enabled in the default behaviour.
   119 /// You can disable them with the following code:
   120 /// \code
   121 /// #define LEMON_DISABLE_ASSERTS
   122 /// \endcode
   123 /// or with compilation parameters:
   124 /// \code
   125 /// g++ -DLEMON_DISABLE_ASSERTS
   126 /// make CXXFLAGS='-DLEMON_DISABLE_ASSERTS'
   127 /// \endcode
   128 /// The checking is also disabled when the standard macro \c NDEBUG is defined.
   129 ///
   130 /// As a default behaviour the failed assertion prints a short log message to
   131 /// the standard error and aborts the execution.
   132 ///
   133 /// However, the following modes can be used in the assertion system:
   134 /// - \c LEMON_ASSERT_ABORT The failed assertion prints a short log message to
   135 ///   the standard error and aborts the program. It is the default behaviour.
   136 /// - \c LEMON_ASSERT_CUSTOM The user can define own assertion handler
   137 ///   function.
   138 ///   \code
   139 ///     void custom_assert_handler(const char* file, int line,
   140 ///                                const char* function, const char* message,
   141 ///                                const char* assertion);
   142 ///   \endcode
   143 ///   The name of the function should be defined as the \c
   144 ///   LEMON_CUSTOM_ASSERT_HANDLER macro name.
   145 ///   \code
   146 ///     #define LEMON_CUSTOM_ASSERT_HANDLER custom_assert_handler
   147 ///   \endcode
   148 ///   Whenever an assertion is occured, the custom assertion
   149 ///   handler is called with appropiate parameters.
   150 ///
   151 /// The assertion mode can also be changed within one compilation unit.
   152 /// If the macros are redefined with other settings and the
   153 /// \ref lemon/assert.h "assert.h" file is reincluded, then the
   154 /// behaviour is changed appropiately to the new settings.
   155 #  define LEMON_ASSERT(exp, msg)                                        \
   156   (static_cast<void> (!!(exp) ? 0 : (                                   \
   157     LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                            \
   158                          LEMON_FUNCTION_NAME,                           \
   159                          ::lemon::_assert_bits::cstringify(msg), #exp), 0)))
   160 
   161 /// \ingroup exceptions
   162 ///
   163 /// \brief Macro for internal assertions
   164 ///
   165 /// Macro for internal assertions, it is used in the library to check
   166 /// the consistency of results of algorithms, several pre- and
   167 /// postconditions and invariants. The checking is disabled by
   168 /// default, but it can be turned on with the macro \c
   169 /// LEMON_ENABLE_DEBUG.
   170 /// \code
   171 /// #define LEMON_ENABLE_DEBUG
   172 /// \endcode
   173 /// or with compilation parameters:
   174 /// \code
   175 /// g++ -DLEMON_ENABLE_DEBUG
   176 /// make CXXFLAGS='-DLEMON_ENABLE_DEBUG'
   177 /// \endcode
   178 ///
   179 /// This macro works like the \c LEMON_ASSERT macro, therefore the
   180 /// current behaviour depends on the settings of \c LEMON_ASSERT
   181 /// macro.
   182 ///
   183 /// \see LEMON_ASSERT
   184 #  define LEMON_DEBUG(exp, msg)                                         \
   185   (static_cast<void> (!!(exp) ? 0 : (                                   \
   186     LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                            \
   187                          LEMON_FUNCTION_NAME,                           \
   188                          ::lemon::_assert_bits::cstringify(msg), #exp), 0)))
   189 
   190 #else
   191 
   192 #  ifndef LEMON_ASSERT_HANDLER
   193 #    define LEMON_ASSERT(exp, msg)  (static_cast<void>(0))
   194 #    define LEMON_DEBUG(exp, msg) (static_cast<void>(0))
   195 #  else
   196 #    define LEMON_ASSERT(exp, msg)                                      \
   197        (static_cast<void> (!!(exp) ? 0 : (                              \
   198         LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                        \
   199                              LEMON_FUNCTION_NAME,                       \
   200                              ::lemon::_assert_bits::cstringify(msg),    \
   201                              #exp), 0)))
   202 #    if defined LEMON_ENABLE_DEBUG
   203 #      define LEMON_DEBUG(exp, msg)                                     \
   204          (static_cast<void> (!!(exp) ? 0 : (                            \
   205            LEMON_ASSERT_HANDLER(__FILE__, __LINE__,                     \
   206                                 LEMON_FUNCTION_NAME,                    \
   207                                 ::lemon::_assert_bits::cstringify(msg), \
   208                                 #exp), 0)))
   209 #    else
   210 #      define LEMON_DEBUG(exp, msg) (static_cast<void>(0))
   211 #    endif
   212 #  endif
   213 
   214 #endif