lemon/error.h
author hegyi
Mon, 21 Nov 2005 18:03:20 +0000
changeset 1823 cb082cdf3667
parent 1746 874e4bc21435
child 1827 dc660ed95b31
permissions -rw-r--r--
NewMapWin has become Dialog instead of Window. Therefore it is created dynamically, when there is need for it, instead of keeping one instance in memory. This solution is slower, but more correct than before.
alpar@906
     1
/* -*- C++ -*-
ladanyi@1435
     2
 * lemon/error.h - Part of LEMON, a generic C++ optimization library
alpar@906
     3
 *
alpar@1164
     4
 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi
alpar@1359
     5
 * Kutatocsoport (Egervary Research Group on Combinatorial Optimization,
klao@1157
     6
 * EGRES).
alpar@906
     7
 *
alpar@906
     8
 * Permission to use, modify and distribute this software is granted
alpar@906
     9
 * provided that this copyright notice appears in all copies. For
alpar@906
    10
 * precise terms see the accompanying LICENSE file.
alpar@906
    11
 *
alpar@906
    12
 * This software is provided "AS IS" with no warranty of any kind,
alpar@906
    13
 * express or implied, and with no claim as to its suitability for any
alpar@906
    14
 * purpose.
alpar@906
    15
 *
alpar@906
    16
 */
alpar@883
    17
alpar@921
    18
#ifndef LEMON_ERROR_H
alpar@921
    19
#define LEMON_ERROR_H
alpar@883
    20
alpar@1151
    21
//! \ingroup exceptions
alpar@883
    22
//! \file
klao@1067
    23
//! \brief Basic exception classes and error handling.
alpar@883
    24
alpar@883
    25
#include <exception>
alpar@883
    26
#include <string>
alpar@883
    27
#include <sstream>
klao@1067
    28
#include <iostream>
klao@1067
    29
#include <cstdlib>
klao@1157
    30
#include <memory>
alpar@883
    31
alpar@921
    32
namespace lemon {
alpar@883
    33
deba@1207
    34
  /// \addtogroup exceptions
deba@1207
    35
  /// @{
deba@1207
    36
  
deba@1207
    37
  /// \brief Exception safe wrapper class.
deba@1207
    38
  ///
deba@1207
    39
  /// Exception safe wrapper class to implement the members of exceptions.
deba@1207
    40
  template <typename _Type>
deba@1207
    41
  class ExceptionMember {
deba@1207
    42
  public:
deba@1207
    43
    typedef _Type Type;
deba@1207
    44
deba@1207
    45
    ExceptionMember() throw () {
deba@1207
    46
      try {
deba@1207
    47
	ptr.reset(new Type());
deba@1207
    48
      } catch (...) {}
deba@1207
    49
    }
deba@1207
    50
deba@1207
    51
    ExceptionMember(const Type& type) throw () {
deba@1207
    52
      try {
deba@1207
    53
	ptr.reset(new Type());
deba@1207
    54
	if (ptr.get() == 0) return;
deba@1207
    55
	*ptr = type;
deba@1207
    56
      } catch (...) {}
deba@1207
    57
    }
deba@1207
    58
deba@1207
    59
    ExceptionMember(const ExceptionMember& copy) throw() {
deba@1207
    60
      try {
deba@1207
    61
	if (!copy.valid()) return;
deba@1207
    62
	ptr.reset(new Type());
deba@1207
    63
	if (ptr.get() == 0) return;
deba@1207
    64
	*ptr = copy.get();
deba@1207
    65
      } catch (...) {}
deba@1207
    66
    }
deba@1207
    67
deba@1207
    68
    ExceptionMember& operator=(const ExceptionMember& copy) {
deba@1207
    69
      if (ptr.get() == 0) return;
deba@1207
    70
      try {
deba@1207
    71
	if (!copy.valid()) return;
deba@1207
    72
 	*ptr = copy.get();
deba@1207
    73
      } catch (...) {}
deba@1207
    74
    }
deba@1207
    75
deba@1207
    76
    void set(const Type& type) {
deba@1207
    77
      if (ptr.get() == 0) return;
deba@1207
    78
      try {
deba@1207
    79
	*ptr = type;
deba@1207
    80
      } catch (...) {}
deba@1207
    81
    }
deba@1207
    82
deba@1207
    83
    const Type& get() const {
deba@1207
    84
      return *ptr;
deba@1207
    85
    }
deba@1207
    86
deba@1207
    87
    bool valid() const {
deba@1207
    88
      return ptr.get() != 0;
deba@1207
    89
    }
deba@1207
    90
    
deba@1207
    91
  private:
deba@1207
    92
    std::auto_ptr<_Type> ptr;
deba@1207
    93
  };
alpar@1151
    94
klao@1056
    95
  /// Exception-safe convenient "error message" class.
klao@1067
    96
klao@1067
    97
  /// Helper class which provides a convenient ostream-like (operator <<
klao@1067
    98
  /// based) interface to create a string message. Mostly useful in
klao@1067
    99
  /// exception classes (therefore the name).
klao@1056
   100
  class ErrorMessage {
klao@1056
   101
  protected:
klao@1067
   102
    ///\e 
alpar@1536
   103
alpar@1536
   104
    ///\todo The good solution is boost::shared_ptr...
alpar@1536
   105
    ///
klao@1157
   106
    mutable
klao@1157
   107
    std::auto_ptr<std::ostringstream> buf;
klao@1056
   108
    
klao@1067
   109
    ///\e 
klao@1056
   110
    bool init() throw() {
klao@1056
   111
      try {
klao@1056
   112
	buf.reset(new std::ostringstream);
klao@1056
   113
      }
klao@1056
   114
      catch(...) {
klao@1056
   115
	buf.reset();
klao@1056
   116
      }
klao@1157
   117
      return buf.get();
klao@1056
   118
    }
klao@1056
   119
klao@1056
   120
  public:
klao@1056
   121
klao@1067
   122
    ///\e 
klao@1056
   123
    ErrorMessage() throw() { init(); }
klao@1056
   124
klao@1157
   125
    ErrorMessage(const ErrorMessage& em) throw() : buf(em.buf) { }
klao@1157
   126
klao@1067
   127
    ///\e 
klao@1056
   128
    ErrorMessage(const char *message) throw() {
klao@1056
   129
      init();
klao@1056
   130
      *this << message;
klao@1056
   131
    }
klao@1056
   132
klao@1067
   133
    ///\e 
klao@1056
   134
    ErrorMessage(const std::string &message) throw() {
klao@1056
   135
      init();
klao@1056
   136
      *this << message;
klao@1056
   137
    }
klao@1056
   138
klao@1067
   139
    ///\e 
klao@1056
   140
    template <typename T>
klao@1056
   141
    ErrorMessage& operator<<(const T &t) throw() {
klao@1157
   142
      if( ! buf.get() ) return *this;
klao@1056
   143
klao@1056
   144
      try {
klao@1056
   145
	*buf << t;
klao@1056
   146
      }
klao@1056
   147
      catch(...) {
klao@1056
   148
	buf.reset();
klao@1056
   149
      }
deba@1207
   150
      return *this;
klao@1056
   151
    }
klao@1056
   152
klao@1067
   153
    ///\e 
klao@1056
   154
    const char* message() throw() {
klao@1157
   155
      if( ! buf.get() ) return 0;
klao@1056
   156
klao@1056
   157
      const char* mes = 0;
klao@1056
   158
      try {
klao@1056
   159
	mes = buf->str().c_str();
klao@1056
   160
      }
klao@1056
   161
      catch(...) {}
klao@1056
   162
      return mes;
klao@1056
   163
    }
klao@1056
   164
    
klao@1056
   165
  };
klao@1056
   166
alpar@883
   167
  /**
alpar@883
   168
   * \brief Generic exception class.
alpar@883
   169
   *
klao@1056
   170
   * Base class for exceptions used in LEMON.
alpar@883
   171
   */
klao@1067
   172
  class Exception : public std::exception {
alpar@883
   173
  public:
klao@1067
   174
    ///\e 
klao@1120
   175
    Exception() {}
klao@1067
   176
    ///\e 
alpar@883
   177
    virtual ~Exception() throw() {}
klao@1120
   178
klao@1120
   179
    ///\e
klao@1120
   180
    virtual const char* exceptionName() const {
klao@1120
   181
      return "lemon::Exception";
klao@1120
   182
    }
alpar@883
   183
    
klao@1067
   184
    ///\e 
alpar@883
   185
    virtual const char* what() const throw() {
klao@1120
   186
      return exceptionName();
klao@1056
   187
    }
klao@1056
   188
  };
klao@1056
   189
klao@1120
   190
  /**
klao@1120
   191
   * \brief One of the two main subclasses of \ref Exception.
klao@1120
   192
   *
klao@1120
   193
   * Logic errors represent problems in the internal logic of a program;
klao@1120
   194
   * in theory, these are preventable, and even detectable before the
klao@1120
   195
   * program runs (e.g., violations of class invariants).
klao@1120
   196
   *
alpar@1125
   197
   * A typical example for this is \ref UninitializedParameter.
klao@1120
   198
   */
klao@1056
   199
  class LogicError : public Exception {
klao@1067
   200
  public:
klao@1120
   201
    virtual const char* exceptionName() const {
klao@1120
   202
      return "lemon::LogicError";
klao@1120
   203
    }
klao@1056
   204
  };
klao@1056
   205
alpar@1125
   206
  /**
alpar@1125
   207
   * \brief \ref Exception for uninitialized parameters.
alpar@1125
   208
   *
alpar@1125
   209
   * This error represents problems in the initialization
alpar@1125
   210
   * of the parameters of the algorithms.
alpar@1125
   211
   */
alpar@1125
   212
  class UninitializedParameter : public LogicError {
alpar@1125
   213
  public:
alpar@1125
   214
    virtual const char* exceptionName() const {
alpar@1125
   215
      return "lemon::UninitializedParameter";
alpar@1125
   216
    }
alpar@1125
   217
  };
alpar@1125
   218
klao@1120
   219
  
klao@1120
   220
  /**
klao@1120
   221
   * \brief One of the two main subclasses of \ref Exception.
klao@1120
   222
   *
klao@1120
   223
   * Runtime errors represent problems outside the scope of a program;
klao@1120
   224
   * they cannot be easily predicted and can generally only be caught as
klao@1120
   225
   * the program executes.
klao@1120
   226
   */
klao@1056
   227
  class RuntimeError : public Exception {
klao@1067
   228
  public:
klao@1120
   229
    virtual const char* exceptionName() const {
klao@1120
   230
      return "lemon::RuntimeError";
klao@1120
   231
    }
klao@1056
   232
  };
klao@1056
   233
klao@1067
   234
  ///\e
klao@1056
   235
  class RangeError : public RuntimeError {
klao@1067
   236
  public:
klao@1120
   237
    virtual const char* exceptionName() const {
klao@1120
   238
      return "lemon::RangeError";
klao@1120
   239
    }
klao@1056
   240
  };
klao@1056
   241
alpar@1061
   242
  ///\e 
klao@1056
   243
  class IOError : public RuntimeError {
klao@1067
   244
  public:
klao@1120
   245
    virtual const char* exceptionName() const {
klao@1120
   246
      return "lemon::IOError";
klao@1120
   247
    }
klao@1056
   248
  };
klao@1056
   249
alpar@1061
   250
  ///\e 
klao@1056
   251
  class DataFormatError : public IOError {
klao@1067
   252
  protected:
deba@1207
   253
    ExceptionMember<std::string> _message;
deba@1207
   254
    ExceptionMember<std::string> _file;
klao@1120
   255
    int _line;
klao@1157
   256
deba@1207
   257
    mutable ExceptionMember<std::string> _message_holder;
klao@1067
   258
  public:
klao@1157
   259
klao@1157
   260
    DataFormatError(const DataFormatError &dfe) : 
deba@1207
   261
      IOError(dfe), _message(dfe._message), _file(dfe._file),
deba@1207
   262
      _line(dfe._line) {}
klao@1157
   263
klao@1067
   264
    ///\e 
klao@1120
   265
    explicit DataFormatError(const char *the_message)
klao@1120
   266
      : _message(the_message), _line(0) {}
deba@1207
   267
klao@1067
   268
    ///\e 
klao@1056
   269
    DataFormatError(const std::string &file_name, int line_num,
klao@1120
   270
		    const char *the_message)
klao@1120
   271
      : _message(the_message), _line(line_num) { file(file_name); }
klao@1056
   272
klao@1067
   273
    ///\e 
deba@1207
   274
    void line(int line) { _line = line; }
klao@1067
   275
    ///\e 
deba@1207
   276
    void message(const std::string& message) { _message.set(message); }
klao@1120
   277
    ///\e 
deba@1207
   278
    void file(const std::string &file) { _file.set(file); }
deba@1207
   279
 
deba@1207
   280
    ///\e
deba@1207
   281
    int line() const { return _line; }
deba@1207
   282
    ///\e
deba@1207
   283
    const char* message() const { 
deba@1207
   284
      if (_message.valid() && !_message.get().empty()) {
deba@1207
   285
	return _message.get().c_str();
deba@1207
   286
      } else {
deba@1207
   287
	return 0;
klao@1056
   288
      }
alpar@883
   289
    }
alpar@883
   290
klao@1067
   291
    /// \brief Returns the filename.
klao@1067
   292
    ///
deba@1207
   293
    /// Returns \e null if the filename was not specified.
klao@1120
   294
    const char* file() const {
deba@1207
   295
      if (_file.valid() && !_file.get().empty()) {
deba@1207
   296
	return _file.get().c_str();
deba@1207
   297
      } else {
deba@1207
   298
	return 0;
deba@1207
   299
      }
klao@1067
   300
    }
klao@1067
   301
klao@1067
   302
    ///\e 
klao@1067
   303
    virtual const char* what() const throw() {
klao@1056
   304
      try {
klao@1056
   305
	std::ostringstream ostr;
alpar@1399
   306
	ostr << exceptionName() << ": ";
deba@1207
   307
	if (message()) ostr << message();
deba@1207
   308
	if( file() || line() != 0 ) {
klao@1056
   309
	  ostr << " (";
deba@1207
   310
	  if( file() ) ostr << "in file '" << file() << "'";
deba@1207
   311
	  if( file() && line() != 0 ) ostr << " ";
deba@1207
   312
	  if( line() != 0 ) ostr << "at line " << line();
klao@1067
   313
	  ostr << ")";
klao@1056
   314
	}
deba@1207
   315
	_message_holder.set(ostr.str());
klao@1056
   316
      }
deba@1207
   317
      catch (...) {}
deba@1207
   318
      if( _message_holder.valid()) return _message_holder.get().c_str();
klao@1120
   319
      return exceptionName();
klao@1120
   320
    }
klao@1120
   321
klao@1120
   322
    virtual const char* exceptionName() const {
klao@1056
   323
      return "lemon::DataFormatError";
klao@1056
   324
    }
klao@1067
   325
klao@1067
   326
    virtual ~DataFormatError() throw() {}
alpar@883
   327
  };
alpar@883
   328
deba@1746
   329
  ///\e 
deba@1746
   330
  class FileOpenError : public IOError {
deba@1746
   331
  protected:
deba@1746
   332
    ExceptionMember<std::string> _file;
deba@1746
   333
deba@1746
   334
    mutable ExceptionMember<std::string> _message_holder;
deba@1746
   335
  public:
deba@1746
   336
deba@1746
   337
    FileOpenError(const FileOpenError &foe) : 
deba@1746
   338
      IOError(foe), _file(foe._file) {}
deba@1746
   339
deba@1746
   340
    ///\e 
deba@1746
   341
    explicit FileOpenError(const std::string& file)
deba@1746
   342
      : _file(file) {}
deba@1746
   343
deba@1746
   344
deba@1746
   345
    ///\e 
deba@1746
   346
    void file(const std::string &file) { _file.set(file); }
deba@1746
   347
 
deba@1746
   348
    /// \brief Returns the filename.
deba@1746
   349
    ///
deba@1746
   350
    /// Returns \e null if the filename was not specified.
deba@1746
   351
    const char* file() const {
deba@1746
   352
      if (_file.valid() && !_file.get().empty()) {
deba@1746
   353
	return _file.get().c_str();
deba@1746
   354
      } else {
deba@1746
   355
	return 0;
deba@1746
   356
      }
deba@1746
   357
    }
deba@1746
   358
deba@1746
   359
    ///\e 
deba@1746
   360
    virtual const char* what() const throw() {
deba@1746
   361
      try {
deba@1746
   362
	std::ostringstream ostr;
deba@1746
   363
	ostr << exceptionName() << ": ";
deba@1746
   364
	ostr << "Cannot open file - " << file();
deba@1746
   365
	_message_holder.set(ostr.str());
deba@1746
   366
      }
deba@1746
   367
      catch (...) {}
deba@1746
   368
      if( _message_holder.valid()) return _message_holder.get().c_str();
deba@1746
   369
      return exceptionName();
deba@1746
   370
    }
deba@1746
   371
deba@1746
   372
    virtual const char* exceptionName() const {
deba@1746
   373
      return "lemon::FileOpenError";
deba@1746
   374
    }
deba@1746
   375
deba@1746
   376
    virtual ~FileOpenError() throw() {}
deba@1746
   377
  };
deba@1746
   378
deba@1213
   379
  class IOParameterError : public LogicError {
deba@1207
   380
  protected:
deba@1207
   381
    ExceptionMember<std::string> _message;
deba@1207
   382
    ExceptionMember<std::string> _file;
deba@1207
   383
deba@1207
   384
    mutable ExceptionMember<std::string> _message_holder;
deba@1207
   385
  public:
deba@1207
   386
deba@1213
   387
    IOParameterError(const IOParameterError &ile) : 
deba@1213
   388
      LogicError(ile), _message(ile._message), _file(ile._file) {}
deba@1207
   389
deba@1207
   390
    ///\e 
deba@1213
   391
    explicit IOParameterError(const char *the_message)
deba@1213
   392
      : _message(the_message) {}
deba@1207
   393
deba@1207
   394
    ///\e 
deba@1213
   395
    IOParameterError(const char *file_name, const char *the_message)
deba@1393
   396
      : _message(the_message), _file(file_name) {}
deba@1207
   397
deba@1207
   398
     ///\e 
deba@1207
   399
    void message(const std::string& message) { _message.set(message); }
deba@1207
   400
    ///\e 
deba@1207
   401
    void file(const std::string &file) { _file.set(file); }
deba@1207
   402
 
deba@1207
   403
     ///\e
deba@1207
   404
    const char* message() const { 
deba@1207
   405
      if (_message.valid()) {
deba@1207
   406
	return _message.get().c_str();
deba@1207
   407
      } else {
deba@1207
   408
	return 0;
deba@1207
   409
      }
deba@1207
   410
    }
deba@1207
   411
deba@1207
   412
    /// \brief Returns the filename.
deba@1207
   413
    ///
deba@1207
   414
    /// Returns \e null if the filename was not specified.
deba@1207
   415
    const char* file() const {
deba@1207
   416
      if (_file.valid()) {
deba@1207
   417
	return _file.get().c_str();
deba@1207
   418
      } else {
deba@1207
   419
	return 0;
deba@1207
   420
      }
deba@1207
   421
    }
deba@1207
   422
deba@1207
   423
    ///\e 
deba@1207
   424
    virtual const char* what() const throw() {
deba@1207
   425
      try {
deba@1207
   426
	std::ostringstream ostr;
deba@1207
   427
	if (message()) ostr << message();
deba@1207
   428
	if (file()) ostr << "(when reading file '" << file() << "')";
deba@1207
   429
	_message_holder.set(ostr.str());
deba@1207
   430
      }
deba@1207
   431
      catch (...) {}
deba@1207
   432
      if( _message_holder.valid() ) return _message_holder.get().c_str();
deba@1207
   433
      return exceptionName();
deba@1207
   434
    }
deba@1207
   435
deba@1207
   436
    virtual const char* exceptionName() const {
deba@1213
   437
      return "lemon::IOParameterError";
deba@1207
   438
    }
deba@1207
   439
deba@1213
   440
    virtual ~IOParameterError() throw() {}
deba@1207
   441
  };
deba@1207
   442
klao@1056
   443
klao@1068
   444
  ///\e
klao@1067
   445
  class AssertionFailedError : public LogicError {
klao@1067
   446
  protected:
klao@1067
   447
    const char *assertion;
klao@1067
   448
    const char *file;
klao@1067
   449
    int line;
klao@1067
   450
    const char *function;
klao@1067
   451
    const char *message;
deba@1213
   452
deba@1213
   453
    mutable ExceptionMember<std::string> _message_holder;
klao@1067
   454
  public:
klao@1067
   455
    ///\e
klao@1067
   456
    AssertionFailedError(const char *_file, int _line, const char *func,
klao@1067
   457
			 const char *msg, const char *_assertion = 0) :
klao@1067
   458
      assertion(_assertion), file(_file), line(_line), function(func),
klao@1067
   459
      message(msg) {}
klao@1067
   460
klao@1067
   461
    ///\e
klao@1067
   462
    const char* get_assertion() const { return assertion; }
klao@1067
   463
    ///\e
klao@1067
   464
    const char* get_message() const { return message; }
klao@1067
   465
    ///\e
klao@1067
   466
    const char* get_file() const { return file; }
klao@1067
   467
    ///\e
klao@1067
   468
    const char* get_function() const { return function; }
klao@1067
   469
    ///\e
klao@1067
   470
    int get_line() const { return line; }
klao@1067
   471
klao@1067
   472
klao@1067
   473
    virtual const char* what() const throw() {
klao@1067
   474
      try {
klao@1067
   475
	std::ostringstream ostr;
klao@1067
   476
	ostr << file << ":" << line << ": ";
klao@1067
   477
	if( function )
klao@1067
   478
	  ostr << function << ": ";
klao@1067
   479
	ostr << message;
klao@1067
   480
	if( assertion )
deba@1213
   481
	   ostr << " (assertion '" << assertion << "' failed)";
deba@1213
   482
	_message_holder.set(ostr.str());
klao@1209
   483
	return ostr.str().c_str();
klao@1067
   484
      }
klao@1067
   485
      catch(...) {}
deba@1213
   486
      if( _message_holder.valid() ) return _message_holder.get().c_str();
klao@1120
   487
      return exceptionName();
klao@1120
   488
    }
klao@1120
   489
klao@1120
   490
    virtual const char* exceptionName() const {
klao@1067
   491
      return "lemon::AssertionFailedError";
klao@1067
   492
    }
klao@1067
   493
klao@1067
   494
    virtual ~AssertionFailedError() throw() {}
klao@1067
   495
  };
klao@1067
   496
klao@1056
   497
klao@1056
   498
  /****************  Macros  ****************/
klao@1056
   499
klao@1056
   500
deba@1785
   501
  template <typename Exception>
deba@1785
   502
  inline void assert_fail(const char *file, int line, const char *func,
deba@1785
   503
		   Exception exception, const char *assertion = 0,
klao@1067
   504
		   bool do_abort=true)
klao@1067
   505
  {
klao@1067
   506
    using namespace std;
klao@1067
   507
    cerr << file << ":" << line << ": ";
klao@1067
   508
    if( func )
klao@1067
   509
      cerr << func << ": ";
deba@1785
   510
    cerr << exception.what();
deba@1785
   511
    if( assertion )
deba@1785
   512
      cerr << " (assertion '" << assertion << "' failed)";
deba@1785
   513
    cerr << endl;
deba@1785
   514
    if(do_abort)
deba@1785
   515
      abort();
deba@1785
   516
  }
deba@1785
   517
deba@1785
   518
  template <>
deba@1785
   519
  inline void assert_fail<const char *>(const char *file, int line, const char *func,
deba@1785
   520
				 const char *message, 
deba@1785
   521
				 const char *assertion,
deba@1785
   522
				 bool do_abort)
deba@1785
   523
  {
deba@1785
   524
    using namespace std;
deba@1785
   525
    cerr << file << ":" << line << ": ";
deba@1785
   526
    if( func )
deba@1785
   527
      cerr << func << ": ";
klao@1067
   528
    cerr << message;
klao@1067
   529
    if( assertion )
klao@1067
   530
      cerr << " (assertion '" << assertion << "' failed)";
klao@1067
   531
    cerr << endl;
klao@1067
   532
    if(do_abort)
klao@1067
   533
      abort();
klao@1067
   534
  }
klao@1056
   535
deba@1785
   536
  template <typename Exception>
deba@1785
   537
  inline void assert_fail_failure(const char *file, int line, const char *func,
deba@1785
   538
			   Exception exception, 
deba@1785
   539
			   const char *assertion = 0,
deba@1785
   540
			   bool = true)
deba@1785
   541
  {
deba@1785
   542
    throw AssertionFailedError(file, line, func, exception.what(), assertion);
deba@1785
   543
  }
deba@1785
   544
deba@1785
   545
  template <>
deba@1785
   546
  inline void assert_fail_failure<const char *>(const char *file, int line, 
deba@1785
   547
					 const char *func,
deba@1785
   548
					 const char *message, 
deba@1785
   549
					 const char *assertion,
deba@1785
   550
					 bool)
deba@1785
   551
  {
deba@1785
   552
    throw AssertionFailedError(file, line, func, message, assertion);
deba@1785
   553
  }
deba@1785
   554
deba@1785
   555
  template <typename Exception> 
deba@1785
   556
  inline void assert_fail_exception(const char *file, int line, const char *func,
deba@1785
   557
			     Exception exception, 
deba@1785
   558
			     const char *assertion = 0, bool = true)
deba@1785
   559
  {
deba@1785
   560
    throw exception;
deba@1785
   561
  }
deba@1785
   562
deba@1785
   563
  template <> 
deba@1785
   564
  inline void assert_fail_exception<const char *>(const char *file, int line, 
deba@1785
   565
					   const char *func,
deba@1785
   566
					   const char *message, 
deba@1785
   567
					   const char *assertion,
deba@1785
   568
					   bool)
klao@1067
   569
  {
klao@1067
   570
    throw AssertionFailedError(file, line, func, message, assertion);
klao@1067
   571
  }
klao@1056
   572
alpar@1151
   573
/// @}
alpar@883
   574
alpar@883
   575
}
alpar@921
   576
#endif // LEMON_ERROR_H
klao@1067
   577
klao@1067
   578
#undef LEMON_ASSERT
klao@1067
   579
#undef LEMON_FIXME
klao@1067
   580
klao@1067
   581
#ifndef LEMON_ASSERT_ABORT
klao@1067
   582
#  define LEMON_ASSERT_ABORT 1
klao@1067
   583
#endif
klao@1067
   584
klao@1067
   585
#ifndef LEMON_ASSERT_HANDLER
deba@1785
   586
#  if defined LEMON_ASSERT_EXCEPTION
deba@1785
   587
#    define LEMON_ASSERT_HANDLER ::lemon::assert_fail_exception
deba@1785
   588
#  elif defined LEMON_ASSERT_FAILURE
deba@1785
   589
#    define LEMON_ASSERT_HANDLER ::lemon::assert_fail_failure
klao@1120
   590
#  else
klao@1120
   591
#    define LEMON_ASSERT_HANDLER ::lemon::assert_fail
klao@1120
   592
#  endif
klao@1067
   593
#endif
klao@1067
   594
klao@1067
   595
#if defined(NDEBUG) || defined(LEMON_DISABLE_ASSERTS)
klao@1067
   596
klao@1067
   597
#  define LEMON_ASSERT(exp, msg)  (static_cast<void> (0))
klao@1067
   598
klao@1067
   599
#else
klao@1067
   600
klao@1067
   601
/**
klao@1067
   602
 * \brief Macro for assertions with customizable message
klao@1067
   603
 *
klao@1120
   604
 * Macro for assertions with customizable message.
klao@1120
   605
 *
klao@1120
   606
 * The behaviour can be customized with LEMON_ASSERT_HANDLER,
klao@1120
   607
 * LEMON_ASSERT_EXCEPTION and LEMON_ASSERT_ABORT defines. Asserts can be
klao@1120
   608
 * disabled by defining either NDEBUG or LEMON_DISABLE_ASSERTS macros.
klao@1120
   609
 *
klao@1120
   610
 * \todo We should provide some way to reset to the default behaviour,
klao@1120
   611
 * shouldn't we?
klao@1120
   612
 *
klao@1120
   613
 * \todo This whole 'assert' business should be placed in a separate
deba@1785
   614
 * include file. The boost assert is not guarded by header sentries
deba@1785
   615
 * which may help to change the behaviour of the assertions in 
deba@1785
   616
 * the files.
klao@1120
   617
 *
klao@1067
   618
 * \todo __PRETTY_FUNCTION__ should be replaced by something
zsuzska@1274
   619
 * compiler-independent, like BOOST_CURRENT_FUNCTION
klao@1067
   620
 */
klao@1067
   621
klao@1067
   622
#  define LEMON_ASSERT(exp, msg)                 \
klao@1067
   623
     (static_cast<void> (!!(exp) ? 0 : (         \
klao@1067
   624
       LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \
klao@1067
   625
                            __PRETTY_FUNCTION__, \
klao@1067
   626
			    (msg), #exp, LEMON_ASSERT_ABORT), 0)))
klao@1067
   627
klao@1120
   628
#endif // NDEBUG || LEMON_DISABLE_ASSERTS
klao@1067
   629
klao@1067
   630
/**
klao@1067
   631
 * \brief Macro for mark not yet implemented features.
klao@1067
   632
 *
klao@1067
   633
 * \todo Is this the right place for this? It should be used only in
klao@1067
   634
 * modules under development.
klao@1067
   635
 *
klao@1067
   636
 * \todo __PRETTY_FUNCTION__ should be replaced by something
zsuzska@1274
   637
 * compiler-independent, like BOOST_CURRENT_FUNCTION
klao@1067
   638
 */
klao@1067
   639
klao@1067
   640
# define LEMON_FIXME(msg) \
klao@1067
   641
    (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, __PRETTY_FUNCTION__, \
klao@1067
   642
			  "FIXME: " msg))