alpar@906: /* -*- C++ -*- alpar@921: * src/lemon/error.h - Part of LEMON, a generic C++ optimization library alpar@906: * alpar@906: * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport alpar@906: * (Egervary Combinatorial Optimization Research Group, EGRES). alpar@906: * alpar@906: * Permission to use, modify and distribute this software is granted alpar@906: * provided that this copyright notice appears in all copies. For alpar@906: * precise terms see the accompanying LICENSE file. alpar@906: * alpar@906: * This software is provided "AS IS" with no warranty of any kind, alpar@906: * express or implied, and with no claim as to its suitability for any alpar@906: * purpose. alpar@906: * alpar@906: */ alpar@883: alpar@921: #ifndef LEMON_ERROR_H alpar@921: #define LEMON_ERROR_H alpar@883: alpar@883: //! \ingroup misc alpar@883: //! \file alpar@883: //! \brief Basic error handling (signaling) routines. alpar@883: alpar@883: #include alpar@883: #include alpar@883: #include alpar@883: klao@1056: #include alpar@883: alpar@921: namespace lemon { alpar@883: klao@1056: /// Exception-safe convenient "error message" class. klao@1056: class ErrorMessage { klao@1056: protected: alpar@1061: ///\e klao@1056: boost::shared_ptr buf; klao@1056: alpar@1061: ///\e klao@1056: bool init() throw() { klao@1056: try { klao@1056: buf.reset(new std::ostringstream); klao@1056: } klao@1056: catch(...) { klao@1056: buf.reset(); klao@1056: } klao@1056: return buf; klao@1056: } klao@1056: klao@1056: public: klao@1056: alpar@1061: ///\e klao@1056: ErrorMessage() throw() { init(); } klao@1056: alpar@1061: ///\e klao@1056: ErrorMessage(const char *message) throw() { klao@1056: init(); klao@1056: *this << message; klao@1056: } klao@1056: alpar@1061: ///\e klao@1056: ErrorMessage(const std::string &message) throw() { klao@1056: init(); klao@1056: *this << message; klao@1056: } klao@1056: alpar@1061: ///\e klao@1056: template klao@1056: ErrorMessage& operator<<(const T &t) throw() { klao@1056: if( !buf ) return *this; klao@1056: klao@1056: try { klao@1056: *buf << t; klao@1056: } klao@1056: catch(...) { klao@1056: buf.reset(); klao@1056: } klao@1056: } klao@1056: alpar@1061: ///\e klao@1056: const char* message() throw() { klao@1056: if( !buf ) return 0; klao@1056: klao@1056: const char* mes = 0; klao@1056: try { klao@1056: mes = buf->str().c_str(); klao@1056: } klao@1056: catch(...) {} klao@1056: return mes; klao@1056: } klao@1056: klao@1056: }; klao@1056: alpar@883: /** alpar@883: * \brief Generic exception class. alpar@883: * klao@1056: * Base class for exceptions used in LEMON. alpar@883: */ klao@1056: class Exception : public std::exception, public ErrorMessage { alpar@883: public: alpar@1061: ///\e klao@1056: Exception() throw() {} alpar@1061: ///\e klao@1056: explicit Exception(const std::string &s) throw() klao@1056: : ErrorMessage(s) {} alpar@1061: ///\e alpar@883: virtual ~Exception() throw() {} alpar@883: alpar@1061: ///\e alpar@883: virtual const char* what() const throw() { klao@1056: const char *mes = message(); klao@1056: if( mes ) return mes; klao@1056: return "lemon::Exception"; klao@1056: } klao@1056: }; klao@1056: alpar@1061: ///\e klao@1056: class LogicError : public Exception { alpar@1061: ///\e klao@1056: explicit LogicError(const std::string &s) klao@1056: : Exception(s) {} klao@1056: }; klao@1056: alpar@1061: ///\e klao@1056: class RuntimeError : public Exception { alpar@1061: ///\e klao@1056: explicit RuntimeError(const std::string &s) klao@1056: : Exception(s) {} klao@1056: }; klao@1056: alpar@1061: ///\e klao@1056: class RangeError : public RuntimeError { alpar@1061: ///\e klao@1056: explicit RangeError(const std::string &s) klao@1056: : RuntimeError(s) {} klao@1056: }; klao@1056: alpar@1061: ///\e klao@1056: class IOError : public RuntimeError { alpar@1061: ///\e klao@1056: explicit IOError(const std::string &s) klao@1056: : RuntimeError(s) {} klao@1056: }; klao@1056: alpar@1061: ///\e klao@1056: class DataFormatError : public IOError { alpar@1061: ///\e klao@1056: explicit DataFormatError(const std::string &message) klao@1056: : IOError(message) : line(0) {} alpar@1061: ///\e klao@1056: DataFormatError(const std::string &file_name, int line_num, alpar@1061: const std::string &message) klao@1056: : IOError(message), line(line_num) { set_file(file_name); } klao@1056: alpar@1061: ///\e klao@1056: void set_line(int line_num) { line=line_num; } alpar@1061: ///\e klao@1056: void set_file(const std::string &file_name) { klao@1056: try { klao@1056: file.reset(new std::string); klao@1056: *file = file_name; klao@1056: } klao@1056: catch(...) { klao@1056: file.reset(); klao@1056: } alpar@883: } alpar@883: alpar@1061: ///\e klao@1056: virtual const char* what() const { klao@1056: const char *mes = 0; klao@1056: try { klao@1056: std::ostringstream ostr; klao@1056: ostr << IOError::what(); klao@1056: if( file || line ) { klao@1056: ostr << " ("; klao@1056: if( file ) ostr << "in file" << *file; klao@1056: if( line ) ostr << " at line" << line; klao@1056: } klao@1056: mes = ostr.str().c_str(); klao@1056: } klao@1056: catch(...) {} klao@1056: if( mes ) return mes; klao@1056: return "lemon::DataFormatError"; klao@1056: } alpar@883: }; alpar@883: klao@1056: klao@1056: klao@1056: /**************** Macros ****************/ klao@1056: klao@1056: alpar@883: /** klao@1056: * \brief Macro for assertions with customizable message alpar@883: */ klao@1056: klao@1056: # define lemon_assert(exp, msg) \ klao@1056: if(!(exp)) { \ klao@1056: std::cerr << __FILE__ ":" << __LINE__ << ": " << (msg) << std::endl; \ klao@1056: abort; \ klao@1056: } klao@1056: alpar@883: alpar@883: /** alpar@883: * \brief Macro for mark not yet implemented features. alpar@883: * alpar@883: * \todo Is this the right place for this? It should be used only in alpar@883: * modules under development. alpar@883: */ alpar@883: klao@1056: # define FIXME(msg) lemon_assert(0, "FIXME: " msg) alpar@883: alpar@883: } alpar@921: #endif // LEMON_ERROR_H