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