1.1 --- a/src/lemon/error.h Sat May 21 21:04:57 2005 +0000
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,540 +0,0 @@
1.4 -/* -*- C++ -*-
1.5 - *
1.6 - * src/lemon/error.h - Part of LEMON, a generic C++ optimization library
1.7 - *
1.8 - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi
1.9 - * Kutatocsoport (Egervary Research Group on Combinatorial Optimization,
1.10 - * EGRES).
1.11 - *
1.12 - * Permission to use, modify and distribute this software is granted
1.13 - * provided that this copyright notice appears in all copies. For
1.14 - * precise terms see the accompanying LICENSE file.
1.15 - *
1.16 - * This software is provided "AS IS" with no warranty of any kind,
1.17 - * express or implied, and with no claim as to its suitability for any
1.18 - * purpose.
1.19 - *
1.20 - */
1.21 -
1.22 -#ifndef LEMON_ERROR_H
1.23 -#define LEMON_ERROR_H
1.24 -
1.25 -//! \ingroup exceptions
1.26 -//! \file
1.27 -//! \brief Basic exception classes and error handling.
1.28 -
1.29 -#include <exception>
1.30 -#include <string>
1.31 -#include <sstream>
1.32 -#include <iostream>
1.33 -#include <cstdlib>
1.34 -#include <memory>
1.35 -
1.36 -namespace lemon {
1.37 -
1.38 - /// \addtogroup exceptions
1.39 - /// @{
1.40 -
1.41 - /// \brief Exception safe wrapper class.
1.42 - ///
1.43 - /// Exception safe wrapper class to implement the members of exceptions.
1.44 - template <typename _Type>
1.45 - class ExceptionMember {
1.46 - public:
1.47 - typedef _Type Type;
1.48 -
1.49 - ExceptionMember() throw () {
1.50 - try {
1.51 - ptr.reset(new Type());
1.52 - } catch (...) {}
1.53 - }
1.54 -
1.55 - ExceptionMember(const Type& type) throw () {
1.56 - try {
1.57 - ptr.reset(new Type());
1.58 - if (ptr.get() == 0) return;
1.59 - *ptr = type;
1.60 - } catch (...) {}
1.61 - }
1.62 -
1.63 - ExceptionMember(const ExceptionMember& copy) throw() {
1.64 - try {
1.65 - if (!copy.valid()) return;
1.66 - ptr.reset(new Type());
1.67 - if (ptr.get() == 0) return;
1.68 - *ptr = copy.get();
1.69 - } catch (...) {}
1.70 - }
1.71 -
1.72 - ExceptionMember& operator=(const ExceptionMember& copy) {
1.73 - if (ptr.get() == 0) return;
1.74 - try {
1.75 - if (!copy.valid()) return;
1.76 - *ptr = copy.get();
1.77 - } catch (...) {}
1.78 - }
1.79 -
1.80 - void set(const Type& type) {
1.81 - if (ptr.get() == 0) return;
1.82 - try {
1.83 - *ptr = type;
1.84 - } catch (...) {}
1.85 - }
1.86 -
1.87 - const Type& get() const {
1.88 - return *ptr;
1.89 - }
1.90 -
1.91 - bool valid() const {
1.92 - return ptr.get() != 0;
1.93 - }
1.94 -
1.95 - private:
1.96 - std::auto_ptr<_Type> ptr;
1.97 - };
1.98 -
1.99 - /// Exception-safe convenient "error message" class.
1.100 -
1.101 - /// Helper class which provides a convenient ostream-like (operator <<
1.102 - /// based) interface to create a string message. Mostly useful in
1.103 - /// exception classes (therefore the name).
1.104 - class ErrorMessage {
1.105 - protected:
1.106 - ///\e
1.107 - ///\todo The good solution is boost:shared_ptr...
1.108 - mutable
1.109 - std::auto_ptr<std::ostringstream> buf;
1.110 -
1.111 - ///\e
1.112 - bool init() throw() {
1.113 - try {
1.114 - buf.reset(new std::ostringstream);
1.115 - }
1.116 - catch(...) {
1.117 - buf.reset();
1.118 - }
1.119 - return buf.get();
1.120 - }
1.121 -
1.122 - public:
1.123 -
1.124 - ///\e
1.125 - ErrorMessage() throw() { init(); }
1.126 -
1.127 - ErrorMessage(const ErrorMessage& em) throw() : buf(em.buf) { }
1.128 -
1.129 - ///\e
1.130 - ErrorMessage(const char *message) throw() {
1.131 - init();
1.132 - *this << message;
1.133 - }
1.134 -
1.135 - ///\e
1.136 - ErrorMessage(const std::string &message) throw() {
1.137 - init();
1.138 - *this << message;
1.139 - }
1.140 -
1.141 - ///\e
1.142 - template <typename T>
1.143 - ErrorMessage& operator<<(const T &t) throw() {
1.144 - if( ! buf.get() ) return *this;
1.145 -
1.146 - try {
1.147 - *buf << t;
1.148 - }
1.149 - catch(...) {
1.150 - buf.reset();
1.151 - }
1.152 - return *this;
1.153 - }
1.154 -
1.155 - ///\e
1.156 - const char* message() throw() {
1.157 - if( ! buf.get() ) return 0;
1.158 -
1.159 - const char* mes = 0;
1.160 - try {
1.161 - mes = buf->str().c_str();
1.162 - }
1.163 - catch(...) {}
1.164 - return mes;
1.165 - }
1.166 -
1.167 - };
1.168 -
1.169 - /**
1.170 - * \brief Generic exception class.
1.171 - *
1.172 - * Base class for exceptions used in LEMON.
1.173 - */
1.174 - class Exception : public std::exception {
1.175 - public:
1.176 - ///\e
1.177 - Exception() {}
1.178 - ///\e
1.179 - virtual ~Exception() throw() {}
1.180 -
1.181 - ///\e
1.182 - virtual const char* exceptionName() const {
1.183 - return "lemon::Exception";
1.184 - }
1.185 -
1.186 - ///\e
1.187 - virtual const char* what() const throw() {
1.188 - return exceptionName();
1.189 - }
1.190 - };
1.191 -
1.192 - /**
1.193 - * \brief One of the two main subclasses of \ref Exception.
1.194 - *
1.195 - * Logic errors represent problems in the internal logic of a program;
1.196 - * in theory, these are preventable, and even detectable before the
1.197 - * program runs (e.g., violations of class invariants).
1.198 - *
1.199 - * A typical example for this is \ref UninitializedParameter.
1.200 - */
1.201 - class LogicError : public Exception {
1.202 - public:
1.203 - virtual const char* exceptionName() const {
1.204 - return "lemon::LogicError";
1.205 - }
1.206 - };
1.207 -
1.208 - /**
1.209 - * \brief \ref Exception for uninitialized parameters.
1.210 - *
1.211 - * This error represents problems in the initialization
1.212 - * of the parameters of the algorithms.
1.213 - */
1.214 - class UninitializedParameter : public LogicError {
1.215 - public:
1.216 - virtual const char* exceptionName() const {
1.217 - return "lemon::UninitializedParameter";
1.218 - }
1.219 - };
1.220 -
1.221 -
1.222 - /**
1.223 - * \brief One of the two main subclasses of \ref Exception.
1.224 - *
1.225 - * Runtime errors represent problems outside the scope of a program;
1.226 - * they cannot be easily predicted and can generally only be caught as
1.227 - * the program executes.
1.228 - */
1.229 - class RuntimeError : public Exception {
1.230 - public:
1.231 - virtual const char* exceptionName() const {
1.232 - return "lemon::RuntimeError";
1.233 - }
1.234 - };
1.235 -
1.236 - ///\e
1.237 - class RangeError : public RuntimeError {
1.238 - public:
1.239 - virtual const char* exceptionName() const {
1.240 - return "lemon::RangeError";
1.241 - }
1.242 - };
1.243 -
1.244 - ///\e
1.245 - class IOError : public RuntimeError {
1.246 - public:
1.247 - virtual const char* exceptionName() const {
1.248 - return "lemon::IOError";
1.249 - }
1.250 - };
1.251 -
1.252 - ///\e
1.253 - class DataFormatError : public IOError {
1.254 - protected:
1.255 - ExceptionMember<std::string> _message;
1.256 - ExceptionMember<std::string> _file;
1.257 - int _line;
1.258 -
1.259 - mutable ExceptionMember<std::string> _message_holder;
1.260 - public:
1.261 -
1.262 - DataFormatError(const DataFormatError &dfe) :
1.263 - IOError(dfe), _message(dfe._message), _file(dfe._file),
1.264 - _line(dfe._line) {}
1.265 -
1.266 - ///\e
1.267 - explicit DataFormatError(const char *the_message)
1.268 - : _message(the_message), _line(0) {}
1.269 -
1.270 - ///\e
1.271 - DataFormatError(const std::string &file_name, int line_num,
1.272 - const char *the_message)
1.273 - : _message(the_message), _line(line_num) { file(file_name); }
1.274 -
1.275 - ///\e
1.276 - void line(int line) { _line = line; }
1.277 - ///\e
1.278 - void message(const std::string& message) { _message.set(message); }
1.279 - ///\e
1.280 - void file(const std::string &file) { _file.set(file); }
1.281 -
1.282 - ///\e
1.283 - int line() const { return _line; }
1.284 - ///\e
1.285 - const char* message() const {
1.286 - if (_message.valid() && !_message.get().empty()) {
1.287 - return _message.get().c_str();
1.288 - } else {
1.289 - return 0;
1.290 - }
1.291 - }
1.292 -
1.293 - /// \brief Returns the filename.
1.294 - ///
1.295 - /// Returns \e null if the filename was not specified.
1.296 - const char* file() const {
1.297 - if (_file.valid() && !_file.get().empty()) {
1.298 - return _file.get().c_str();
1.299 - } else {
1.300 - return 0;
1.301 - }
1.302 - }
1.303 -
1.304 - ///\e
1.305 - virtual const char* what() const throw() {
1.306 - try {
1.307 - std::ostringstream ostr;
1.308 - ostr << exceptionName() << ": ";
1.309 - if (message()) ostr << message();
1.310 - if( file() || line() != 0 ) {
1.311 - ostr << " (";
1.312 - if( file() ) ostr << "in file '" << file() << "'";
1.313 - if( file() && line() != 0 ) ostr << " ";
1.314 - if( line() != 0 ) ostr << "at line " << line();
1.315 - ostr << ")";
1.316 - }
1.317 - _message_holder.set(ostr.str());
1.318 - }
1.319 - catch (...) {}
1.320 - if( _message_holder.valid()) return _message_holder.get().c_str();
1.321 - return exceptionName();
1.322 - }
1.323 -
1.324 - virtual const char* exceptionName() const {
1.325 - return "lemon::DataFormatError";
1.326 - }
1.327 -
1.328 - virtual ~DataFormatError() throw() {}
1.329 - };
1.330 -
1.331 - class IOParameterError : public LogicError {
1.332 - protected:
1.333 - ExceptionMember<std::string> _message;
1.334 - ExceptionMember<std::string> _file;
1.335 -
1.336 - mutable ExceptionMember<std::string> _message_holder;
1.337 - public:
1.338 -
1.339 - IOParameterError(const IOParameterError &ile) :
1.340 - LogicError(ile), _message(ile._message), _file(ile._file) {}
1.341 -
1.342 - ///\e
1.343 - explicit IOParameterError(const char *the_message)
1.344 - : _message(the_message) {}
1.345 -
1.346 - ///\e
1.347 - IOParameterError(const char *file_name, const char *the_message)
1.348 - : _message(the_message), _file(file_name) {}
1.349 -
1.350 - ///\e
1.351 - void message(const std::string& message) { _message.set(message); }
1.352 - ///\e
1.353 - void file(const std::string &file) { _file.set(file); }
1.354 -
1.355 - ///\e
1.356 - const char* message() const {
1.357 - if (_message.valid()) {
1.358 - return _message.get().c_str();
1.359 - } else {
1.360 - return 0;
1.361 - }
1.362 - }
1.363 -
1.364 - /// \brief Returns the filename.
1.365 - ///
1.366 - /// Returns \e null if the filename was not specified.
1.367 - const char* file() const {
1.368 - if (_file.valid()) {
1.369 - return _file.get().c_str();
1.370 - } else {
1.371 - return 0;
1.372 - }
1.373 - }
1.374 -
1.375 - ///\e
1.376 - virtual const char* what() const throw() {
1.377 - try {
1.378 - std::ostringstream ostr;
1.379 - if (message()) ostr << message();
1.380 - if (file()) ostr << "(when reading file '" << file() << "')";
1.381 - _message_holder.set(ostr.str());
1.382 - }
1.383 - catch (...) {}
1.384 - if( _message_holder.valid() ) return _message_holder.get().c_str();
1.385 - return exceptionName();
1.386 - }
1.387 -
1.388 - virtual const char* exceptionName() const {
1.389 - return "lemon::IOParameterError";
1.390 - }
1.391 -
1.392 - virtual ~IOParameterError() throw() {}
1.393 - };
1.394 -
1.395 -
1.396 - ///\e
1.397 - class AssertionFailedError : public LogicError {
1.398 - protected:
1.399 - const char *assertion;
1.400 - const char *file;
1.401 - int line;
1.402 - const char *function;
1.403 - const char *message;
1.404 -
1.405 - mutable ExceptionMember<std::string> _message_holder;
1.406 - public:
1.407 - ///\e
1.408 - AssertionFailedError(const char *_file, int _line, const char *func,
1.409 - const char *msg, const char *_assertion = 0) :
1.410 - assertion(_assertion), file(_file), line(_line), function(func),
1.411 - message(msg) {}
1.412 -
1.413 - ///\e
1.414 - const char* get_assertion() const { return assertion; }
1.415 - ///\e
1.416 - const char* get_message() const { return message; }
1.417 - ///\e
1.418 - const char* get_file() const { return file; }
1.419 - ///\e
1.420 - const char* get_function() const { return function; }
1.421 - ///\e
1.422 - int get_line() const { return line; }
1.423 -
1.424 -
1.425 - virtual const char* what() const throw() {
1.426 - try {
1.427 - std::ostringstream ostr;
1.428 - ostr << file << ":" << line << ": ";
1.429 - if( function )
1.430 - ostr << function << ": ";
1.431 - ostr << message;
1.432 - if( assertion )
1.433 - ostr << " (assertion '" << assertion << "' failed)";
1.434 - _message_holder.set(ostr.str());
1.435 - return ostr.str().c_str();
1.436 - }
1.437 - catch(...) {}
1.438 - if( _message_holder.valid() ) return _message_holder.get().c_str();
1.439 - return exceptionName();
1.440 - }
1.441 -
1.442 - virtual const char* exceptionName() const {
1.443 - return "lemon::AssertionFailedError";
1.444 - }
1.445 -
1.446 - virtual ~AssertionFailedError() throw() {}
1.447 - };
1.448 -
1.449 -
1.450 - /**************** Macros ****************/
1.451 -
1.452 -
1.453 - inline
1.454 - void assert_fail(const char *file, int line, const char *func,
1.455 - const char *message, const char *assertion = 0,
1.456 - bool do_abort=true)
1.457 - {
1.458 - using namespace std;
1.459 - cerr << file << ":" << line << ": ";
1.460 - if( func )
1.461 - cerr << func << ": ";
1.462 - cerr << message;
1.463 - if( assertion )
1.464 - cerr << " (assertion '" << assertion << "' failed)";
1.465 - cerr << endl;
1.466 - if(do_abort)
1.467 - abort();
1.468 - }
1.469 -
1.470 - inline
1.471 - void assert_fail_throw(const char *file, int line, const char *func,
1.472 - const char *message, const char *assertion = 0,
1.473 - bool = true)
1.474 - {
1.475 - throw AssertionFailedError(file, line, func, message, assertion);
1.476 - }
1.477 -
1.478 -/// @}
1.479 -
1.480 -}
1.481 -#endif // LEMON_ERROR_H
1.482 -
1.483 -#undef LEMON_ASSERT
1.484 -#undef LEMON_FIXME
1.485 -
1.486 -#ifndef LEMON_ASSERT_ABORT
1.487 -# define LEMON_ASSERT_ABORT 1
1.488 -#endif
1.489 -
1.490 -#ifndef LEMON_ASSERT_HANDLER
1.491 -# ifdef LEMON_ASSERT_EXCEPTION
1.492 -# define LEMON_ASSERT_HANDLER ::lemon::assert_fail_throw
1.493 -# else
1.494 -# define LEMON_ASSERT_HANDLER ::lemon::assert_fail
1.495 -# endif
1.496 -#endif
1.497 -
1.498 -#if defined(NDEBUG) || defined(LEMON_DISABLE_ASSERTS)
1.499 -
1.500 -# define LEMON_ASSERT(exp, msg) (static_cast<void> (0))
1.501 -
1.502 -#else
1.503 -
1.504 -/**
1.505 - * \brief Macro for assertions with customizable message
1.506 - *
1.507 - * Macro for assertions with customizable message.
1.508 - *
1.509 - * The behaviour can be customized with LEMON_ASSERT_HANDLER,
1.510 - * LEMON_ASSERT_EXCEPTION and LEMON_ASSERT_ABORT defines. Asserts can be
1.511 - * disabled by defining either NDEBUG or LEMON_DISABLE_ASSERTS macros.
1.512 - *
1.513 - * \todo We should provide some way to reset to the default behaviour,
1.514 - * shouldn't we?
1.515 - *
1.516 - * \todo This whole 'assert' business should be placed in a separate
1.517 - * include file.
1.518 - *
1.519 - * \todo __PRETTY_FUNCTION__ should be replaced by something
1.520 - * compiler-independent, like BOOST_CURRENT_FUNCTION
1.521 - */
1.522 -
1.523 -# define LEMON_ASSERT(exp, msg) \
1.524 - (static_cast<void> (!!(exp) ? 0 : ( \
1.525 - LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \
1.526 - __PRETTY_FUNCTION__, \
1.527 - (msg), #exp, LEMON_ASSERT_ABORT), 0)))
1.528 -
1.529 -#endif // NDEBUG || LEMON_DISABLE_ASSERTS
1.530 -
1.531 -/**
1.532 - * \brief Macro for mark not yet implemented features.
1.533 - *
1.534 - * \todo Is this the right place for this? It should be used only in
1.535 - * modules under development.
1.536 - *
1.537 - * \todo __PRETTY_FUNCTION__ should be replaced by something
1.538 - * compiler-independent, like BOOST_CURRENT_FUNCTION
1.539 - */
1.540 -
1.541 -# define LEMON_FIXME(msg) \
1.542 - (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, __PRETTY_FUNCTION__, \
1.543 - "FIXME: " msg))