diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/error.h --- a/src/lemon/error.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,540 +0,0 @@ -/* -*- C++ -*- - * - * src/lemon/error.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi - * Kutatocsoport (Egervary Research Group on Combinatorial Optimization, - * EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_ERROR_H -#define LEMON_ERROR_H - -//! \ingroup exceptions -//! \file -//! \brief Basic exception classes and error handling. - -#include -#include -#include -#include -#include -#include - -namespace lemon { - - /// \addtogroup exceptions - /// @{ - - /// \brief Exception safe wrapper class. - /// - /// Exception safe wrapper class to implement the members of exceptions. - template - class ExceptionMember { - public: - typedef _Type Type; - - ExceptionMember() throw () { - try { - ptr.reset(new Type()); - } catch (...) {} - } - - ExceptionMember(const Type& type) throw () { - try { - ptr.reset(new Type()); - if (ptr.get() == 0) return; - *ptr = type; - } catch (...) {} - } - - ExceptionMember(const ExceptionMember& copy) throw() { - try { - if (!copy.valid()) return; - ptr.reset(new Type()); - if (ptr.get() == 0) return; - *ptr = copy.get(); - } catch (...) {} - } - - ExceptionMember& operator=(const ExceptionMember& copy) { - if (ptr.get() == 0) return; - try { - if (!copy.valid()) return; - *ptr = copy.get(); - } catch (...) {} - } - - void set(const Type& type) { - if (ptr.get() == 0) return; - try { - *ptr = type; - } catch (...) {} - } - - const Type& get() const { - return *ptr; - } - - bool valid() const { - return ptr.get() != 0; - } - - private: - std::auto_ptr<_Type> ptr; - }; - - /// Exception-safe convenient "error message" class. - - /// Helper class which provides a convenient ostream-like (operator << - /// based) interface to create a string message. Mostly useful in - /// exception classes (therefore the name). - class ErrorMessage { - protected: - ///\e - ///\todo The good solution is boost:shared_ptr... - mutable - std::auto_ptr buf; - - ///\e - bool init() throw() { - try { - buf.reset(new std::ostringstream); - } - catch(...) { - buf.reset(); - } - return buf.get(); - } - - public: - - ///\e - ErrorMessage() throw() { init(); } - - ErrorMessage(const ErrorMessage& em) throw() : buf(em.buf) { } - - ///\e - ErrorMessage(const char *message) throw() { - init(); - *this << message; - } - - ///\e - ErrorMessage(const std::string &message) throw() { - init(); - *this << message; - } - - ///\e - template - ErrorMessage& operator<<(const T &t) throw() { - if( ! buf.get() ) return *this; - - try { - *buf << t; - } - catch(...) { - buf.reset(); - } - return *this; - } - - ///\e - const char* message() throw() { - if( ! buf.get() ) return 0; - - const char* mes = 0; - try { - mes = buf->str().c_str(); - } - catch(...) {} - return mes; - } - - }; - - /** - * \brief Generic exception class. - * - * Base class for exceptions used in LEMON. - */ - class Exception : public std::exception { - public: - ///\e - Exception() {} - ///\e - virtual ~Exception() throw() {} - - ///\e - virtual const char* exceptionName() const { - return "lemon::Exception"; - } - - ///\e - virtual const char* what() const throw() { - return exceptionName(); - } - }; - - /** - * \brief One of the two main subclasses of \ref Exception. - * - * Logic errors represent problems in the internal logic of a program; - * in theory, these are preventable, and even detectable before the - * program runs (e.g., violations of class invariants). - * - * A typical example for this is \ref UninitializedParameter. - */ - class LogicError : public Exception { - public: - virtual const char* exceptionName() const { - return "lemon::LogicError"; - } - }; - - /** - * \brief \ref Exception for uninitialized parameters. - * - * This error represents problems in the initialization - * of the parameters of the algorithms. - */ - class UninitializedParameter : public LogicError { - public: - virtual const char* exceptionName() const { - return "lemon::UninitializedParameter"; - } - }; - - - /** - * \brief One of the two main subclasses of \ref Exception. - * - * Runtime errors represent problems outside the scope of a program; - * they cannot be easily predicted and can generally only be caught as - * the program executes. - */ - class RuntimeError : public Exception { - public: - virtual const char* exceptionName() const { - return "lemon::RuntimeError"; - } - }; - - ///\e - class RangeError : public RuntimeError { - public: - virtual const char* exceptionName() const { - return "lemon::RangeError"; - } - }; - - ///\e - class IOError : public RuntimeError { - public: - virtual const char* exceptionName() const { - return "lemon::IOError"; - } - }; - - ///\e - class DataFormatError : public IOError { - protected: - ExceptionMember _message; - ExceptionMember _file; - int _line; - - mutable ExceptionMember _message_holder; - public: - - DataFormatError(const DataFormatError &dfe) : - IOError(dfe), _message(dfe._message), _file(dfe._file), - _line(dfe._line) {} - - ///\e - explicit DataFormatError(const char *the_message) - : _message(the_message), _line(0) {} - - ///\e - DataFormatError(const std::string &file_name, int line_num, - const char *the_message) - : _message(the_message), _line(line_num) { file(file_name); } - - ///\e - void line(int line) { _line = line; } - ///\e - void message(const std::string& message) { _message.set(message); } - ///\e - void file(const std::string &file) { _file.set(file); } - - ///\e - int line() const { return _line; } - ///\e - const char* message() const { - if (_message.valid() && !_message.get().empty()) { - return _message.get().c_str(); - } else { - return 0; - } - } - - /// \brief Returns the filename. - /// - /// Returns \e null if the filename was not specified. - const char* file() const { - if (_file.valid() && !_file.get().empty()) { - return _file.get().c_str(); - } else { - return 0; - } - } - - ///\e - virtual const char* what() const throw() { - try { - std::ostringstream ostr; - ostr << exceptionName() << ": "; - if (message()) ostr << message(); - if( file() || line() != 0 ) { - ostr << " ("; - if( file() ) ostr << "in file '" << file() << "'"; - if( file() && line() != 0 ) ostr << " "; - if( line() != 0 ) ostr << "at line " << line(); - ostr << ")"; - } - _message_holder.set(ostr.str()); - } - catch (...) {} - if( _message_holder.valid()) return _message_holder.get().c_str(); - return exceptionName(); - } - - virtual const char* exceptionName() const { - return "lemon::DataFormatError"; - } - - virtual ~DataFormatError() throw() {} - }; - - class IOParameterError : public LogicError { - protected: - ExceptionMember _message; - ExceptionMember _file; - - mutable ExceptionMember _message_holder; - public: - - IOParameterError(const IOParameterError &ile) : - LogicError(ile), _message(ile._message), _file(ile._file) {} - - ///\e - explicit IOParameterError(const char *the_message) - : _message(the_message) {} - - ///\e - IOParameterError(const char *file_name, const char *the_message) - : _message(the_message), _file(file_name) {} - - ///\e - void message(const std::string& message) { _message.set(message); } - ///\e - void file(const std::string &file) { _file.set(file); } - - ///\e - const char* message() const { - if (_message.valid()) { - return _message.get().c_str(); - } else { - return 0; - } - } - - /// \brief Returns the filename. - /// - /// Returns \e null if the filename was not specified. - const char* file() const { - if (_file.valid()) { - return _file.get().c_str(); - } else { - return 0; - } - } - - ///\e - virtual const char* what() const throw() { - try { - std::ostringstream ostr; - if (message()) ostr << message(); - if (file()) ostr << "(when reading file '" << file() << "')"; - _message_holder.set(ostr.str()); - } - catch (...) {} - if( _message_holder.valid() ) return _message_holder.get().c_str(); - return exceptionName(); - } - - virtual const char* exceptionName() const { - return "lemon::IOParameterError"; - } - - virtual ~IOParameterError() throw() {} - }; - - - ///\e - class AssertionFailedError : public LogicError { - protected: - const char *assertion; - const char *file; - int line; - const char *function; - const char *message; - - mutable ExceptionMember _message_holder; - public: - ///\e - AssertionFailedError(const char *_file, int _line, const char *func, - const char *msg, const char *_assertion = 0) : - assertion(_assertion), file(_file), line(_line), function(func), - message(msg) {} - - ///\e - const char* get_assertion() const { return assertion; } - ///\e - const char* get_message() const { return message; } - ///\e - const char* get_file() const { return file; } - ///\e - const char* get_function() const { return function; } - ///\e - int get_line() const { return line; } - - - virtual const char* what() const throw() { - try { - std::ostringstream ostr; - ostr << file << ":" << line << ": "; - if( function ) - ostr << function << ": "; - ostr << message; - if( assertion ) - ostr << " (assertion '" << assertion << "' failed)"; - _message_holder.set(ostr.str()); - return ostr.str().c_str(); - } - catch(...) {} - if( _message_holder.valid() ) return _message_holder.get().c_str(); - return exceptionName(); - } - - virtual const char* exceptionName() const { - return "lemon::AssertionFailedError"; - } - - virtual ~AssertionFailedError() throw() {} - }; - - - /**************** Macros ****************/ - - - inline - void assert_fail(const char *file, int line, const char *func, - const char *message, const char *assertion = 0, - bool do_abort=true) - { - using namespace std; - cerr << file << ":" << line << ": "; - if( func ) - cerr << func << ": "; - cerr << message; - if( assertion ) - cerr << " (assertion '" << assertion << "' failed)"; - cerr << endl; - if(do_abort) - abort(); - } - - inline - void assert_fail_throw(const char *file, int line, const char *func, - const char *message, const char *assertion = 0, - bool = true) - { - throw AssertionFailedError(file, line, func, message, assertion); - } - -/// @} - -} -#endif // LEMON_ERROR_H - -#undef LEMON_ASSERT -#undef LEMON_FIXME - -#ifndef LEMON_ASSERT_ABORT -# define LEMON_ASSERT_ABORT 1 -#endif - -#ifndef LEMON_ASSERT_HANDLER -# ifdef LEMON_ASSERT_EXCEPTION -# define LEMON_ASSERT_HANDLER ::lemon::assert_fail_throw -# else -# define LEMON_ASSERT_HANDLER ::lemon::assert_fail -# endif -#endif - -#if defined(NDEBUG) || defined(LEMON_DISABLE_ASSERTS) - -# define LEMON_ASSERT(exp, msg) (static_cast (0)) - -#else - -/** - * \brief Macro for assertions with customizable message - * - * Macro for assertions with customizable message. - * - * The behaviour can be customized with LEMON_ASSERT_HANDLER, - * LEMON_ASSERT_EXCEPTION and LEMON_ASSERT_ABORT defines. Asserts can be - * disabled by defining either NDEBUG or LEMON_DISABLE_ASSERTS macros. - * - * \todo We should provide some way to reset to the default behaviour, - * shouldn't we? - * - * \todo This whole 'assert' business should be placed in a separate - * include file. - * - * \todo __PRETTY_FUNCTION__ should be replaced by something - * compiler-independent, like BOOST_CURRENT_FUNCTION - */ - -# define LEMON_ASSERT(exp, msg) \ - (static_cast (!!(exp) ? 0 : ( \ - LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \ - __PRETTY_FUNCTION__, \ - (msg), #exp, LEMON_ASSERT_ABORT), 0))) - -#endif // NDEBUG || LEMON_DISABLE_ASSERTS - -/** - * \brief Macro for mark not yet implemented features. - * - * \todo Is this the right place for this? It should be used only in - * modules under development. - * - * \todo __PRETTY_FUNCTION__ should be replaced by something - * compiler-independent, like BOOST_CURRENT_FUNCTION - */ - -# define LEMON_FIXME(msg) \ - (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, __PRETTY_FUNCTION__, \ - "FIXME: " msg))