Port error.h from svn -r3438 + minor changes (error_test does not pass!)
authorPeter Kovacs <kpeter@inf.elte.hu>
Thu, 07 Feb 2008 11:52:16 +0000
changeset 665f7a8570687d
parent 64 761622e5ed4c
child 67 9de02aa380de
Port error.h from svn -r3438 + minor changes (error_test does not pass!)

In svn -r3438 error_test is not used as a test program and it does not pass.
lemon/Makefile.am
lemon/error.h
test/Makefile.am
test/error_test.cc
     1.1 --- a/lemon/Makefile.am	Mon Feb 04 13:32:36 2008 +0100
     1.2 +++ b/lemon/Makefile.am	Thu Feb 07 11:52:16 2008 +0000
     1.3 @@ -16,9 +16,10 @@
     1.4  
     1.5  lemon_HEADERS += \
     1.6          lemon/dim2.h \
     1.7 +	lemon/error.h \
     1.8 +	lemon/list_graph.h \
     1.9  	lemon/maps.h \
    1.10          lemon/random.h \
    1.11 -	lemon/list_graph.h \
    1.12          lemon/tolerance.h
    1.13  
    1.14  bits_HEADERS += \
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/lemon/error.h	Thu Feb 07 11:52:16 2008 +0000
     2.3 @@ -0,0 +1,675 @@
     2.4 +/* -*- C++ -*-
     2.5 + *
     2.6 + * This file is a part of LEMON, a generic C++ optimization library
     2.7 + *
     2.8 + * Copyright (C) 2003-2008
     2.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
    2.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
    2.11 + *
    2.12 + * Permission to use, modify and distribute this software is granted
    2.13 + * provided that this copyright notice appears in all copies. For
    2.14 + * precise terms see the accompanying LICENSE file.
    2.15 + *
    2.16 + * This software is provided "AS IS" with no warranty of any kind,
    2.17 + * express or implied, and with no claim as to its suitability for any
    2.18 + * purpose.
    2.19 + *
    2.20 + */
    2.21 +
    2.22 +#ifndef LEMON_ERROR_H
    2.23 +#define LEMON_ERROR_H
    2.24 +
    2.25 +/// \ingroup exceptions
    2.26 +/// \file
    2.27 +/// \brief Basic exception classes and error handling.
    2.28 +
    2.29 +#include <exception>
    2.30 +#include <string>
    2.31 +#include <sstream>
    2.32 +#include <iostream>
    2.33 +#include <cstdlib>
    2.34 +#include <memory>
    2.35 +
    2.36 +namespace lemon {
    2.37 +
    2.38 +  /// \addtogroup exceptions
    2.39 +  /// @{
    2.40 +
    2.41 +  /// \brief Exception safe wrapper class.
    2.42 +  ///
    2.43 +  /// Exception safe wrapper class to implement the members of exceptions.
    2.44 +  template <typename _Type>
    2.45 +  class ExceptionMember {
    2.46 +  public:
    2.47 +    typedef _Type Type;
    2.48 +
    2.49 +    ExceptionMember() throw() {
    2.50 +      try {
    2.51 +	ptr.reset(new Type());
    2.52 +      } catch (...) {}
    2.53 +    }
    2.54 +
    2.55 +    ExceptionMember(const Type& type) throw() {
    2.56 +      try {
    2.57 +	ptr.reset(new Type());
    2.58 +	if (ptr.get() == 0) return;
    2.59 +	*ptr = type;
    2.60 +      } catch (...) {}
    2.61 +    }
    2.62 +
    2.63 +    ExceptionMember(const ExceptionMember& copy) throw() {
    2.64 +      try {
    2.65 +	if (!copy.valid()) return;
    2.66 +	ptr.reset(new Type());
    2.67 +	if (ptr.get() == 0) return;
    2.68 +	*ptr = copy.get();
    2.69 +      } catch (...) {}
    2.70 +    }
    2.71 +
    2.72 +    ExceptionMember& operator=(const ExceptionMember& copy) throw() {
    2.73 +      if (ptr.get() == 0) return;
    2.74 +      try {
    2.75 +	if (!copy.valid()) return;
    2.76 + 	*ptr = copy.get();
    2.77 +      } catch (...) {}
    2.78 +    }
    2.79 +
    2.80 +    void set(const Type& type) throw() {
    2.81 +      if (ptr.get() == 0) return;
    2.82 +      try {
    2.83 +	*ptr = type;
    2.84 +      } catch (...) {}
    2.85 +    }
    2.86 +
    2.87 +    const Type& get() const {
    2.88 +      return *ptr;
    2.89 +    }
    2.90 +
    2.91 +    bool valid() const throw() {
    2.92 +      return ptr.get() != 0;
    2.93 +    }
    2.94 +
    2.95 +  private:
    2.96 +    std::auto_ptr<_Type> ptr;
    2.97 +  };
    2.98 +
    2.99 +  /// Exception-safe convenient "error message" class.
   2.100 +
   2.101 +  /// Helper class which provides a convenient ostream-like (operator <<
   2.102 +  /// based) interface to create a string message. Mostly useful in
   2.103 +  /// exception classes (therefore the name).
   2.104 +  class ErrorMessage {
   2.105 +  protected:
   2.106 +    ///\e
   2.107 +
   2.108 +    ///\todo The good solution is boost::shared_ptr...
   2.109 +    ///
   2.110 +    mutable std::auto_ptr<std::ostringstream> buf;
   2.111 +
   2.112 +    ///\e
   2.113 +    bool init() throw() {
   2.114 +      try {
   2.115 +	buf.reset(new std::ostringstream);
   2.116 +      }
   2.117 +      catch(...) {
   2.118 +	buf.reset();
   2.119 +      }
   2.120 +      return buf.get();
   2.121 +    }
   2.122 +
   2.123 +  public:
   2.124 +
   2.125 +    ///\e
   2.126 +    ErrorMessage() throw() { init(); }
   2.127 +
   2.128 +    ErrorMessage(const ErrorMessage& em) throw() : buf(em.buf) { }
   2.129 +
   2.130 +    ///\e
   2.131 +    ErrorMessage(const char *msg) throw() {
   2.132 +      init();
   2.133 +      *this << msg;
   2.134 +    }
   2.135 +
   2.136 +    ///\e
   2.137 +    ErrorMessage(const std::string &msg) throw() {
   2.138 +      init();
   2.139 +      *this << msg;
   2.140 +    }
   2.141 +
   2.142 +    ///\e
   2.143 +    template <typename T>
   2.144 +    ErrorMessage& operator<<(const T &t) throw() {
   2.145 +      if( ! buf.get() ) return *this;
   2.146 +
   2.147 +      try {
   2.148 +	*buf << t;
   2.149 +      }
   2.150 +      catch(...) {
   2.151 +	buf.reset();
   2.152 +      }
   2.153 +      return *this;
   2.154 +    }
   2.155 +
   2.156 +    ///\e
   2.157 +    const char* message() throw() {
   2.158 +      if( ! buf.get() ) return 0;
   2.159 +
   2.160 +      const char* mes = 0;
   2.161 +      try {
   2.162 +	mes = buf->str().c_str();
   2.163 +      }
   2.164 +      catch(...) {}
   2.165 +      return mes;
   2.166 +    }
   2.167 +
   2.168 +  };
   2.169 +
   2.170 +  /// Generic exception class.
   2.171 +
   2.172 +  /// Base class for exceptions used in LEMON.
   2.173 +  ///
   2.174 +  class Exception : public std::exception {
   2.175 +  public:
   2.176 +    ///\e
   2.177 +    Exception() {}
   2.178 +    ///\e
   2.179 +    virtual ~Exception() throw() {}
   2.180 +    ///\e
   2.181 +    virtual const char* what() const throw() {
   2.182 +      return "lemon::Exception";
   2.183 +    }
   2.184 +  };
   2.185 +
   2.186 +  /// One of the two main subclasses of \ref Exception.
   2.187 +
   2.188 +  /// Logic errors represent problems in the internal logic of a program;
   2.189 +  /// in theory, these are preventable, and even detectable before the
   2.190 +  /// program runs (e.g. violations of class invariants).
   2.191 +  ///
   2.192 +  /// A typical example for this is \ref UninitializedParameter.
   2.193 +  class LogicError : public Exception {
   2.194 +  public:
   2.195 +    virtual const char* what() const throw() {
   2.196 +      return "lemon::LogicError";
   2.197 +    }
   2.198 +  };
   2.199 +
   2.200 +  /// \ref Exception for uninitialized parameters.
   2.201 +
   2.202 +  /// This error represents problems in the initialization
   2.203 +  /// of the parameters of the algorithms.
   2.204 +  class UninitializedParameter : public LogicError {
   2.205 +  public:
   2.206 +    virtual const char* what() const throw() {
   2.207 +      return "lemon::UninitializedParameter";
   2.208 +    }
   2.209 +  };
   2.210 +
   2.211 +
   2.212 +  /// One of the two main subclasses of \ref Exception.
   2.213 +
   2.214 +  /// Runtime errors represent problems outside the scope of a program;
   2.215 +  /// they cannot be easily predicted and can generally only be caught
   2.216 +  /// as the program executes.
   2.217 +  class RuntimeError : public Exception {
   2.218 +  public:
   2.219 +    virtual const char* what() const throw() {
   2.220 +      return "lemon::RuntimeError";
   2.221 +    }
   2.222 +  };
   2.223 +
   2.224 +  ///\e
   2.225 +  class RangeError : public RuntimeError {
   2.226 +  public:
   2.227 +    virtual const char* what() const throw() {
   2.228 +      return "lemon::RangeError";
   2.229 +    }
   2.230 +  };
   2.231 +
   2.232 +  ///\e
   2.233 +  class IoError : public RuntimeError {
   2.234 +  public:
   2.235 +    virtual const char* what() const throw() {
   2.236 +      return "lemon::IoError";
   2.237 +    }
   2.238 +  };
   2.239 +
   2.240 +  ///\e
   2.241 +  class DataFormatError : public IoError {
   2.242 +  protected:
   2.243 +    ExceptionMember<std::string> _message;
   2.244 +    ExceptionMember<std::string> _file;
   2.245 +    int _line;
   2.246 +
   2.247 +    mutable ExceptionMember<std::string> _message_holder;
   2.248 +  public:
   2.249 +
   2.250 +    DataFormatError(const DataFormatError &dfe) :
   2.251 +      IoError(dfe), _message(dfe._message), _file(dfe._file),
   2.252 +      _line(dfe._line) {}
   2.253 +
   2.254 +    ///\e
   2.255 +    explicit DataFormatError(const char *the_message)
   2.256 +      : _message(the_message), _line(0) {}
   2.257 +
   2.258 +    ///\e
   2.259 +    DataFormatError(const std::string &file_name, int line_num,
   2.260 +		    const char *the_message)
   2.261 +      : _message(the_message), _line(line_num) { file(file_name); }
   2.262 +
   2.263 +    ///\e
   2.264 +    void line(int ln) { _line = ln; }
   2.265 +    ///\e
   2.266 +    void message(const std::string& msg) { _message.set(msg); }
   2.267 +    ///\e
   2.268 +    void file(const std::string &fl) { _file.set(fl); }
   2.269 +
   2.270 +    ///\e
   2.271 +    int line() const { return _line; }
   2.272 +    ///\e
   2.273 +    const char* message() const {
   2.274 +      if (_message.valid() && !_message.get().empty()) {
   2.275 +	return _message.get().c_str();
   2.276 +      } else {
   2.277 +	return 0;
   2.278 +      }
   2.279 +    }
   2.280 +
   2.281 +    /// \brief Returns the filename.
   2.282 +    ///
   2.283 +    /// Returns \e null if the filename was not specified.
   2.284 +    const char* file() const {
   2.285 +      if (_file.valid() && !_file.get().empty()) {
   2.286 +	return _file.get().c_str();
   2.287 +      } else {
   2.288 +	return 0;
   2.289 +      }
   2.290 +    }
   2.291 +
   2.292 +    ///\e
   2.293 +    virtual const char* what() const throw() {
   2.294 +      try {
   2.295 +	std::ostringstream ostr;
   2.296 +	ostr << "lemon:DataFormatError" << ": ";
   2.297 +	if (message()) ostr << message();
   2.298 +	if( file() || line() != 0 ) {
   2.299 +	  ostr << " (";
   2.300 +	  if( file() ) ostr << "in file '" << file() << "'";
   2.301 +	  if( file() && line() != 0 ) ostr << " ";
   2.302 +	  if( line() != 0 ) ostr << "at line " << line();
   2.303 +	  ostr << ")";
   2.304 +	}
   2.305 +	_message_holder.set(ostr.str());
   2.306 +      }
   2.307 +      catch (...) {}
   2.308 +      if( _message_holder.valid()) return _message_holder.get().c_str();
   2.309 +      return "lemon:DataFormatError";
   2.310 +    }
   2.311 +
   2.312 +    virtual ~DataFormatError() throw() {}
   2.313 +  };
   2.314 +
   2.315 +  ///\e
   2.316 +  class FileOpenError : public IoError {
   2.317 +  protected:
   2.318 +    ExceptionMember<std::string> _file;
   2.319 +
   2.320 +    mutable ExceptionMember<std::string> _message_holder;
   2.321 +  public:
   2.322 +
   2.323 +    FileOpenError(const FileOpenError &foe) :
   2.324 +      IoError(foe), _file(foe._file) {}
   2.325 +
   2.326 +    ///\e
   2.327 +    explicit FileOpenError(const std::string& fl)
   2.328 +      : _file(fl) {}
   2.329 +
   2.330 +
   2.331 +    ///\e
   2.332 +    void file(const std::string &fl) { _file.set(fl); }
   2.333 +
   2.334 +    /// \brief Returns the filename.
   2.335 +    ///
   2.336 +    /// Returns \e null if the filename was not specified.
   2.337 +    const char* file() const {
   2.338 +      if (_file.valid() && !_file.get().empty()) {
   2.339 +	return _file.get().c_str();
   2.340 +      } else {
   2.341 +	return 0;
   2.342 +      }
   2.343 +    }
   2.344 +
   2.345 +    ///\e
   2.346 +    virtual const char* what() const throw() {
   2.347 +      try {
   2.348 +	std::ostringstream ostr;
   2.349 +	ostr << "lemon::FileOpenError" << ": ";
   2.350 +	ostr << "Cannot open file - " << file();
   2.351 +	_message_holder.set(ostr.str());
   2.352 +      }
   2.353 +      catch (...) {}
   2.354 +      if( _message_holder.valid()) return _message_holder.get().c_str();
   2.355 +      return "lemon::FileOpenError";
   2.356 +    }
   2.357 +    virtual ~FileOpenError() throw() {}
   2.358 +  };
   2.359 +
   2.360 +  class IoParameterError : public IoError {
   2.361 +  protected:
   2.362 +    ExceptionMember<std::string> _message;
   2.363 +    ExceptionMember<std::string> _file;
   2.364 +
   2.365 +    mutable ExceptionMember<std::string> _message_holder;
   2.366 +  public:
   2.367 +
   2.368 +    IoParameterError(const IoParameterError &ile) :
   2.369 +      IoError(ile), _message(ile._message), _file(ile._file) {}
   2.370 +
   2.371 +    ///\e
   2.372 +    explicit IoParameterError(const char *the_message)
   2.373 +      : _message(the_message) {}
   2.374 +
   2.375 +    ///\e
   2.376 +    IoParameterError(const char *file_name, const char *the_message)
   2.377 +      : _message(the_message), _file(file_name) {}
   2.378 +
   2.379 +     ///\e
   2.380 +    void message(const std::string& msg) { _message.set(msg); }
   2.381 +    ///\e
   2.382 +    void file(const std::string &fl) { _file.set(fl); }
   2.383 +
   2.384 +     ///\e
   2.385 +    const char* message() const {
   2.386 +      if (_message.valid()) {
   2.387 +	return _message.get().c_str();
   2.388 +      } else {
   2.389 +	return 0;
   2.390 +      }
   2.391 +    }
   2.392 +
   2.393 +    /// \brief Returns the filename.
   2.394 +    ///
   2.395 +    /// Returns \c 0 if the filename was not specified.
   2.396 +    const char* file() const {
   2.397 +      if (_file.valid()) {
   2.398 +	return _file.get().c_str();
   2.399 +      } else {
   2.400 +	return 0;
   2.401 +      }
   2.402 +    }
   2.403 +
   2.404 +    ///\e
   2.405 +    virtual const char* what() const throw() {
   2.406 +      try {
   2.407 +	std::ostringstream ostr;
   2.408 +	if (message()) ostr << message();
   2.409 +	if (file()) ostr << "(when reading file '" << file() << "')";
   2.410 +	_message_holder.set(ostr.str());
   2.411 +      }
   2.412 +      catch (...) {}
   2.413 +      if( _message_holder.valid() ) return _message_holder.get().c_str();
   2.414 +      return "lemon:IoParameterError";
   2.415 +    }
   2.416 +    virtual ~IoParameterError() throw() {}
   2.417 +  };
   2.418 +
   2.419 +
   2.420 +  ///\e
   2.421 +  class AssertionFailedError : public LogicError {
   2.422 +  protected:
   2.423 +    const char *assertion;
   2.424 +    const char *file;
   2.425 +    int line;
   2.426 +    const char *function;
   2.427 +    const char *message;
   2.428 +
   2.429 +    mutable ExceptionMember<std::string> _message_holder;
   2.430 +  public:
   2.431 +    ///\e
   2.432 +    AssertionFailedError(const char *_file, int _line, const char *func,
   2.433 +			 const char *msg, const char *_assertion = 0) :
   2.434 +      assertion(_assertion), file(_file), line(_line), function(func),
   2.435 +      message(msg) {}
   2.436 +
   2.437 +    ///\e
   2.438 +    const char* get_assertion() const { return assertion; }
   2.439 +    ///\e
   2.440 +    const char* get_message() const { return message; }
   2.441 +    ///\e
   2.442 +    const char* get_file() const { return file; }
   2.443 +    ///\e
   2.444 +    const char* get_function() const { return function; }
   2.445 +    ///\e
   2.446 +    int get_line() const { return line; }
   2.447 +
   2.448 +
   2.449 +    virtual const char* what() const throw() {
   2.450 +      try {
   2.451 +	std::ostringstream ostr;
   2.452 +	ostr << file << ":" << line << ": ";
   2.453 +	if( function )
   2.454 +	  ostr << function << ": ";
   2.455 +	ostr << message;
   2.456 +	if( assertion )
   2.457 +	   ostr << " (assertion '" << assertion << "' failed)";
   2.458 +	_message_holder.set(ostr.str());
   2.459 +	return ostr.str().c_str();
   2.460 +      }
   2.461 +      catch(...) {}
   2.462 +      if( _message_holder.valid() ) return _message_holder.get().c_str();
   2.463 +      return "lemon::AssertionFailedError";
   2.464 +    }
   2.465 +   virtual ~AssertionFailedError() throw() {}
   2.466 +  };
   2.467 +
   2.468 +
   2.469 +  /****************  Macros  ****************/
   2.470 +
   2.471 +
   2.472 +  template <typename Exception>
   2.473 +  inline void assert_fail(const char *file, int line,
   2.474 +                          const char *func,
   2.475 +                          Exception exception,
   2.476 +                          const char *assertion = 0,
   2.477 +                          bool do_abort=true)
   2.478 +  {
   2.479 +    using namespace std;
   2.480 +    cerr << file << ":" << line << ": ";
   2.481 +    if (func)
   2.482 +      cerr << func << ": ";
   2.483 +    cerr << exception.what();
   2.484 +    if (assertion)
   2.485 +      cerr << " (assertion '" << assertion << "' failed)";
   2.486 +    cerr << endl;
   2.487 +    if (do_abort)
   2.488 +      abort();
   2.489 +  }
   2.490 +
   2.491 +  template <>
   2.492 +  inline void assert_fail<const char *>(const char *file, int line,
   2.493 +                                        const char *func,
   2.494 +                                        const char *message,
   2.495 +                                        const char *assertion,
   2.496 +                                        bool do_abort)
   2.497 +  {
   2.498 +    using namespace std;
   2.499 +    cerr << file << ":" << line << ": ";
   2.500 +    if (func)
   2.501 +      cerr << func << ": ";
   2.502 +    cerr << message;
   2.503 +    if (assertion)
   2.504 +      cerr << " (assertion '" << assertion << "' failed)";
   2.505 +    cerr << endl;
   2.506 +    if (do_abort)
   2.507 +      abort();
   2.508 +  }
   2.509 +
   2.510 +  template <>
   2.511 +  inline void assert_fail<std::string>(const char *file, int line,
   2.512 +                                       const char *func,
   2.513 +                                       std::string message,
   2.514 +                                       const char *assertion,
   2.515 +                                       bool do_abort)
   2.516 +  {
   2.517 +    assert_fail(file, line, func, message.c_str(), assertion, do_abort);
   2.518 +  }
   2.519 +
   2.520 +  template <typename Exception>
   2.521 +  inline void assert_fail_failure(const char *file, int line, const char *func,
   2.522 +			   Exception exception,
   2.523 +			   const char *assertion = 0,
   2.524 +			   bool = true)
   2.525 +  {
   2.526 +    throw AssertionFailedError(file, line, func, exception.what(), assertion);
   2.527 +  }
   2.528 +
   2.529 +  template <>
   2.530 +  inline void assert_fail_failure<const char *>(const char *file, int line,
   2.531 +                                                const char *func,
   2.532 +                                                const char *message,
   2.533 +                                                const char *assertion,
   2.534 +                                                bool)
   2.535 +  {
   2.536 +    throw AssertionFailedError(file, line, func, message, assertion);
   2.537 +  }
   2.538 +
   2.539 +  template <>
   2.540 +  inline void assert_fail_failure<std::string>(const char *file, int line,
   2.541 +                                               const char *func,
   2.542 +                                               std::string message,
   2.543 +                                               const char *assertion,
   2.544 +                                               bool)
   2.545 +  {
   2.546 +    assert_fail_failure(file, line, func, message.c_str(), assertion, true);
   2.547 +  }
   2.548 +
   2.549 +  template <typename Exception>
   2.550 +  inline void assert_fail_exception(const char *file, int line, const char *func,
   2.551 +			     Exception exception,
   2.552 +			     const char *assertion = 0, bool = true)
   2.553 +  {
   2.554 +    throw exception;
   2.555 +  }
   2.556 +
   2.557 +  template <>
   2.558 +  inline void assert_fail_exception<const char *>(const char *file, int line,
   2.559 +					   const char *func,
   2.560 +					   const char *message,
   2.561 +					   const char *assertion,
   2.562 +					   bool)
   2.563 +  {
   2.564 +    throw AssertionFailedError(file, line, func, message, assertion);
   2.565 +  }
   2.566 +
   2.567 +  template <>
   2.568 +  inline void assert_fail_exception<std::string>(const char *file, int line,
   2.569 +                                                 const char *func,
   2.570 +                                                 std::string message,
   2.571 +                                                 const char *assertion,
   2.572 +                                                 bool)
   2.573 +  {
   2.574 +    assert_fail_exception(file, line, func, message.c_str(), assertion, true);
   2.575 +  }
   2.576 +
   2.577 +/// @}
   2.578 +
   2.579 +}
   2.580 +#endif // LEMON_ERROR_H
   2.581 +
   2.582 +#undef LEMON_ASSERT
   2.583 +#undef LEMON_FIXME
   2.584 +
   2.585 +#ifdef LEMON_ENABLE_ASSERTS
   2.586 +#  define LEMON_ASSERT_ABORT
   2.587 +#endif
   2.588 +
   2.589 +#ifndef LEMON_ASSERT_DO_ABORT
   2.590 +#  define LEMON_ASSERT_DO_ABORT 1
   2.591 +#endif
   2.592 +
   2.593 +#ifndef LEMON_ASSERT_HANDLER
   2.594 +#  if defined LEMON_ASSERT_EXCEPTION
   2.595 +#    define LEMON_ASSERT_HANDLER ::lemon::assert_fail_exception
   2.596 +#  elif defined LEMON_ASSERT_FAILURE
   2.597 +#    define LEMON_ASSERT_HANDLER ::lemon::assert_fail_failure
   2.598 +#  elif defined LEMON_ASSERT_ABORT
   2.599 +#    define LEMON_ASSERT_HANDLER ::lemon::assert_fail
   2.600 +#  else
   2.601 +#    define LEMON_DISABLE_ASSERTS
   2.602 +#  endif
   2.603 +#endif
   2.604 +
   2.605 +#ifdef DOXYGEN
   2.606 +
   2.607 +/// \brief Macro for assertions with customizable message
   2.608 +///
   2.609 +/// Macro for assertions with customizable message.
   2.610 +///
   2.611 +/// The assertions are disabled in the default behaviour. You can
   2.612 +/// enable the assertions with the
   2.613 +/// \code
   2.614 +/// #define LEMON_ENABLE_ASSERTS
   2.615 +/// \endcode
   2.616 +/// Then an assert
   2.617 +/// provides a log on the standard error about the assertion and aborts
   2.618 +/// the program if LEMON_ASSERT_DO_ABORT is also defined (otherwise the
   2.619 +/// program keeps on running).
   2.620 +/// By defining LEMON_ASSERT_FAILURE or
   2.621 +/// LEMON_ASSERT_EXCEPTION, you can set other behaviour to the
   2.622 +/// assertions. In case LEMON_ASSERT_FAILURE is given, LEMON_ASSERT
   2.623 +/// will always throw an \c AssertionFailedError exception with
   2.624 +/// the \c msg error message. By using
   2.625 +/// LEMON_ASSERT_EXCEPTION, one can define an arbitrary exception to be thrown.
   2.626 +///
   2.627 +/// The LEMON_ASSERT macro should be called with the \c exp parameter
   2.628 +/// which should be an expression convertible to bool. If the given
   2.629 +/// parameter is false the assertion is raised and one of the assertion
   2.630 +/// behaviour will be activated. The \c msg should be either a const
   2.631 +/// char* message or an exception. When the \c msg is an exception the
   2.632 +/// \ref lemon::Exception::what() "what()" function is called to retrieve and
   2.633 +/// display the error message.
   2.634 +///
   2.635 +/// \todo We should provide some way to reset to the default behaviour,
   2.636 +/// shouldn't we?
   2.637 +///
   2.638 +/// \todo This whole 'assert' business should be placed in a separate
   2.639 +/// include file. The boost assert is not guarded by header sentries
   2.640 +/// which may help to change the behaviour of the assertions in
   2.641 +/// the files.
   2.642 +///
   2.643 +/// \todo __PRETTY_FUNCTION__ should be replaced by something
   2.644 +/// compiler-independent, like BOOST_CURRENT_FUNCTION
   2.645 +
   2.646 +#  define LEMON_ASSERT(exp, msg)                 \
   2.647 +     (static_cast<void> (!!(exp) ? 0 : (         \
   2.648 +       LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \
   2.649 +                            __PRETTY_FUNCTION__, \
   2.650 +                            msg, #exp, LEMON_ASSERT_DO_ABORT), 0)))
   2.651 +
   2.652 +#else
   2.653 +#  if defined LEMON_DISABLE_ASSERTS
   2.654 +
   2.655 +#    define LEMON_ASSERT(exp, msg)  (static_cast<void> (0))
   2.656 +
   2.657 +#  else
   2.658 +#    define LEMON_ASSERT(exp, msg)                 \
   2.659 +       (static_cast<void> (!!(exp) ? 0 : (         \
   2.660 +         LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \
   2.661 +                              __PRETTY_FUNCTION__, \
   2.662 +                              msg, #exp, LEMON_ASSERT_DO_ABORT), 0)))
   2.663 +#  endif
   2.664 +#endif
   2.665 +
   2.666 +/**
   2.667 + * \brief Macro for mark not yet implemented features.
   2.668 + *
   2.669 + * \todo Is this the right place for this? It should be used only in
   2.670 + * modules under development.
   2.671 + *
   2.672 + * \todo __PRETTY_FUNCTION__ should be replaced by something
   2.673 + * compiler-independent, like BOOST_CURRENT_FUNCTION
   2.674 + */
   2.675 +
   2.676 +#define LEMON_FIXME(msg) \
   2.677 +    (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, __PRETTY_FUNCTION__, \
   2.678 +			  "FIXME: " msg))
     3.1 --- a/test/Makefile.am	Mon Feb 04 13:32:36 2008 +0100
     3.2 +++ b/test/Makefile.am	Thu Feb 07 11:52:16 2008 +0000
     3.3 @@ -19,6 +19,7 @@
     3.4  
     3.5  test_digraph_test_SOURCES = test/digraph_test.cc
     3.6  test_dim_test_SOURCES = test/dim_test.cc
     3.7 +#test_error_test_SOURCES = test/error_test.cc
     3.8  test_graph_test_SOURCES = test/graph_test.cc
     3.9  test_random_test_SOURCES = test/random_test.cc
    3.10  test_test_tools_fail_SOURCES = test/test_tools_fail.cc
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/test/error_test.cc	Thu Feb 07 11:52:16 2008 +0000
     4.3 @@ -0,0 +1,68 @@
     4.4 +/* -*- C++ -*-
     4.5 + *
     4.6 + * This file is a part of LEMON, a generic C++ optimization library
     4.7 + *
     4.8 + * Copyright (C) 2003-2008
     4.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
    4.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
    4.11 + *
    4.12 + * Permission to use, modify and distribute this software is granted
    4.13 + * provided that this copyright notice appears in all copies. For
    4.14 + * precise terms see the accompanying LICENSE file.
    4.15 + *
    4.16 + * This software is provided "AS IS" with no warranty of any kind,
    4.17 + * express or implied, and with no claim as to its suitability for any
    4.18 + * purpose.
    4.19 + *
    4.20 + */
    4.21 +
    4.22 +#include <iostream>
    4.23 +
    4.24 +#include <lemon/error.h>
    4.25 +#include "test_tools.h"
    4.26 +
    4.27 +using namespace lemon;
    4.28 +using std::cout;
    4.29 +using std::endl;
    4.30 +
    4.31 +void faulty_fn() {
    4.32 +  fault("This is a fault message");
    4.33 +}
    4.34 +
    4.35 +void exception_fn() {
    4.36 +  throw Exception("This is a function throwing exception with some args: ")
    4.37 +    << 5 << ", " << 18;
    4.38 +}
    4.39 +
    4.40 +void unfinished_fn() {
    4.41 +  LEMON_FIXME("unfinished_fn() is unfinished!");
    4.42 +}
    4.43 +
    4.44 +
    4.45 +int main() {
    4.46 +  try {
    4.47 +    faulty_fn();
    4.48 +    check(false, "A faulty function did not fail.");
    4.49 +  }
    4.50 +  catch(const Exception &e) {
    4.51 +    cout << "Exeption = \"" << e.what() << "\" (Right behaviour)" << endl;
    4.52 +  }
    4.53 +
    4.54 +  try {
    4.55 +    exception_fn();
    4.56 +    check(false, "The function did not throw Exception.");
    4.57 +  }
    4.58 +  catch(const Exception &e) {
    4.59 +    cout << "Exeption = \"" << e.what() << "\" (Right behaviour)" << endl;
    4.60 +  }
    4.61 +
    4.62 +  try {
    4.63 +    unfinished_fn();
    4.64 +    check(false, "FIXME macro does not work.");
    4.65 +  }
    4.66 +  catch(const Exception &e) {
    4.67 +    cout << "Exeption = \"" << e.what() << "\" (Right behaviour)" << endl;
    4.68 +  }
    4.69 +
    4.70 +  return 0;
    4.71 +}