lemon/error.h
author deba
Tue, 17 Oct 2006 10:50:57 +0000
changeset 2247 269a0dcee70b
parent 2153 b1fb96088350
child 2386 81b47fc5c444
permissions -rw-r--r--
Update the Path concept
Concept check for paths

DirPath renamed to Path
The interface updated to the new lemon interface
Make difference between the empty path and the path from one node
Builder interface have not been changed
// I wanted but there was not accordance about it

UPath is removed
It was a buggy implementation, it could not iterate on the
nodes in the right order
Right way to use undirected paths => path of edges in undirected graphs

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