COIN-OR::LEMON - Graph Library

Changeset 1067:47939f501c81 in lemon-0.x for src/work/klao/error.h


Ignore:
Timestamp:
01/10/05 00:28:18 (20 years ago)
Author:
Mihaly Barasz
Branch:
default
Phase:
public
Convert:
svn:c9d7d8f5-90d6-0310-b91f-818b3a526b0e/lemon/trunk@1463
Message:

Advances in error.h

  • More clear exception usage concept
  • sketch of LEMON_ASSERT interface
  • test file
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/work/klao/error.h

    r1061 r1067  
    2020//! \ingroup misc
    2121//! \file
    22 //! \brief Basic error handling (signaling) routines.
     22//! \brief Basic exception classes and error handling.
    2323
    2424#include <exception>
    2525#include <string>
    2626#include <sstream>
     27#include <iostream>
     28#include <cstdlib>
    2729
    2830#include <boost/shared_ptr.hpp>
     
    3133
    3234  /// Exception-safe convenient "error message" class.
     35
     36  /// Helper class which provides a convenient ostream-like (operator <<
     37  /// based) interface to create a string message. Mostly useful in
     38  /// exception classes (therefore the name).
    3339  class ErrorMessage {
    3440  protected:
    35   ///\e
     41    ///\e
    3642    boost::shared_ptr<std::ostringstream> buf;
    3743   
    38   ///\e
     44    ///\e
    3945    bool init() throw() {
    4046      try {
     
    4955  public:
    5056
    51   ///\e
     57    ///\e
    5258    ErrorMessage() throw() { init(); }
    5359
    54   ///\e
     60    ///\e
    5561    ErrorMessage(const char *message) throw() {
    5662      init();
     
    5864    }
    5965
    60   ///\e
     66    ///\e
    6167    ErrorMessage(const std::string &message) throw() {
    6268      init();
     
    6470    }
    6571
    66   ///\e
     72    ///\e
    6773    template <typename T>
    6874    ErrorMessage& operator<<(const T &t) throw() {
     
    7783    }
    7884
    79   ///\e
     85    ///\e
    8086    const char* message() throw() {
    8187      if( !buf ) return 0;
     
    96102   * Base class for exceptions used in LEMON.
    97103   */
    98   class Exception : public std::exception, public ErrorMessage {
    99   public:
    100   ///\e
    101     Exception() throw() {}
    102   ///\e
    103     explicit Exception(const std::string &s) throw()
    104       : ErrorMessage(s) {}
    105   ///\e
     104  class Exception : public std::exception {
     105  protected:
     106    ///\e
     107    const char *message;
     108
     109  public:
     110    ///\e
     111    Exception() throw() : message(0) {}
     112    ///\e
     113    explicit Exception(const char *msg) throw()
     114      : message(msg) {}
     115    ///\e
    106116    virtual ~Exception() throw() {}
    107117   
    108   ///\e
     118    ///\e
    109119    virtual const char* what() const throw() {
    110       const char *mes = message();
    111       if( mes ) return mes;
     120      if( message ) return message;
    112121      return "lemon::Exception";
    113122    }
     
    116125  ///\e
    117126  class LogicError : public Exception {
    118   ///\e
    119     explicit LogicError(const std::string &s)
     127  public:
     128    ///\e
     129    explicit LogicError() {}
     130    ///\e
     131    explicit LogicError(const char *s)
    120132      : Exception(s) {}
    121133  };
     
    123135  ///\e
    124136  class RuntimeError : public Exception {
    125   ///\e
    126     explicit RuntimeError(const std::string &s)
     137  public:
     138    ///\e
     139    explicit RuntimeError() {}
     140    ///\e
     141    explicit RuntimeError(const char *s)
    127142      : Exception(s) {}
    128143  };
    129144
    130   ///\e 
     145  ///\e
    131146  class RangeError : public RuntimeError {
    132   ///\e
    133     explicit RangeError(const std::string &s)
     147  public:
     148    ///\e
     149    explicit RangeError(const char *s)
    134150      : RuntimeError(s) {}
    135151  };
     
    137153  ///\e
    138154  class IOError : public RuntimeError {
    139   ///\e
    140     explicit IOError(const std::string &s)
     155  public:
     156    ///\e
     157    explicit IOError(const char *s)
    141158      : RuntimeError(s) {}
    142159  };
     
    144161  ///\e
    145162  class DataFormatError : public IOError {
    146   ///\e
    147     explicit DataFormatError(const std::string &message)
    148       : IOError(message) : line(0) {}
    149   ///\e
     163  protected:
     164    int line;
     165    boost::shared_ptr<std::string> file;
     166
     167  public:
     168    ///\e
     169    explicit DataFormatError(const char *message)
     170      : IOError(message), line(0) {}
     171    ///\e
    150172    DataFormatError(const std::string &file_name, int line_num,
    151                     const std::string &message)
     173                    const char *message)
    152174      : IOError(message), line(line_num) { set_file(file_name); }
    153175
    154   ///\e
     176    ///\e
    155177    void set_line(int line_num) { line=line_num; }
    156   ///\e
     178    ///\e
    157179    void set_file(const std::string &file_name) {
    158180      try {
     
    165187    }
    166188
    167   ///\e
    168     virtual const char* what() const {
     189    ///\e
     190    int get_line() const { return line; }
     191
     192    /// \brief Returns the filename.
     193    ///
     194    /// Returns "(unknown)" if the filename was not specified.
     195    const char* get_file() const {
     196      if( file )
     197        return file->c_str();
     198      else
     199        return "(unknown)";
     200    }
     201
     202    ///\e
     203    virtual const char* what() const throw() {
    169204      const char *mes = 0;
    170205      try {
     
    173208        if( file || line ) {
    174209          ostr << " (";
    175           if( file ) ostr << "in file" << *file;
    176           if( line ) ostr << " at line" << line;
     210          if( file ) ostr << "in file '" << *file << "'";
     211          if( file && line ) ostr << " ";
     212          if( line ) ostr << "at line " << line;
     213          ostr << ")";
    177214        }
    178215        mes = ostr.str().c_str();
     
    182219      return "lemon::DataFormatError";
    183220    }
    184   };
    185 
     221
     222    virtual ~DataFormatError() throw() {}
     223  };
     224
     225
     226  class AssertionFailedError : public LogicError {
     227  protected:
     228    const char *assertion;
     229    const char *file;
     230    int line;
     231    const char *function;
     232    const char *message;
     233  public:
     234    ///\e
     235    AssertionFailedError(const char *_file, int _line, const char *func,
     236                         const char *msg, const char *_assertion = 0) :
     237      assertion(_assertion), file(_file), line(_line), function(func),
     238      message(msg) {}
     239
     240    ///\e
     241    const char* get_assertion() const { return assertion; }
     242    ///\e
     243    const char* get_message() const { return message; }
     244    ///\e
     245    const char* get_file() const { return file; }
     246    ///\e
     247    const char* get_function() const { return function; }
     248    ///\e
     249    int get_line() const { return line; }
     250
     251
     252    virtual const char* what() const throw() {
     253      const char *mes = 0;
     254      try {
     255        std::ostringstream ostr;
     256        ostr << file << ":" << line << ": ";
     257        if( function )
     258          ostr << function << ": ";
     259        ostr << message;
     260        if( assertion )
     261          ostr << " (assertion '" << assertion << "' failed)";
     262        mes = ostr.str().c_str();
     263      }
     264      catch(...) {}
     265      if( mes ) return mes;
     266      return "lemon::AssertionFailedError";
     267    }
     268
     269    virtual ~AssertionFailedError() throw() {}
     270  };
    186271
    187272
     
    189274
    190275
    191   /**
    192    * \brief Macro for assertions with customizable message
    193    */
    194 
    195 # define lemon_assert(exp, msg) \
    196     if(!(exp)) { \
    197       std::cerr << __FILE__ ":" << __LINE__ << ": " << (msg) << std::endl; \
    198       abort; \
    199     }
    200 
    201 
    202   /**
    203    * \brief Macro for mark not yet implemented features.
    204    *
    205    * \todo Is this the right place for this? It should be used only in
    206    * modules under development.
    207    */
    208 
    209 # define FIXME(msg) lemon_assert(0, "FIXME: " msg)
     276  inline
     277  void assert_fail(const char *file, int line, const char *func,
     278                   const char *message, const char *assertion = 0,
     279                   bool do_abort=true)
     280  {
     281    using namespace std;
     282    cerr << file << ":" << line << ": ";
     283    if( func )
     284      cerr << func << ": ";
     285    cerr << message;
     286    if( assertion )
     287      cerr << " (assertion '" << assertion << "' failed)";
     288    cerr << endl;
     289    if(do_abort)
     290      abort();
     291  }
     292
     293  inline
     294  void assert_fail_throw(const char *file, int line, const char *func,
     295                   const char *message, const char *assertion = 0,
     296                   bool = true)
     297  {
     298    throw AssertionFailedError(file, line, func, message, assertion);
     299  }
     300
    210301
    211302}
    212303#endif // LEMON_ERROR_H
     304
     305#undef LEMON_ASSERT
     306#undef LEMON_FIXME
     307
     308#ifndef LEMON_ASSERT_ABORT
     309#  define LEMON_ASSERT_ABORT 1
     310#endif
     311
     312#ifndef LEMON_ASSERT_HANDLER
     313#  define LEMON_ASSERT_HANDLER ::lemon::assert_fail
     314#endif
     315
     316#if defined(NDEBUG) || defined(LEMON_DISABLE_ASSERTS)
     317
     318#  define LEMON_ASSERT(exp, msg)  (static_cast<void> (0))
     319
     320#else
     321
     322/**
     323 * \brief Macro for assertions with customizable message
     324 *
     325 * \todo __PRETTY_FUNCTION__ should be replaced by something
     326 * compiler-independant, like BOOST_CURRENT_FUNCTION
     327 */
     328
     329#  define LEMON_ASSERT(exp, msg)                 \
     330     (static_cast<void> (!!(exp) ? 0 : (         \
     331       LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \
     332                            __PRETTY_FUNCTION__, \
     333                            (msg), #exp, LEMON_ASSERT_ABORT), 0)))
     334
     335# endif // NDEBUG
     336
     337/**
     338 * \brief Macro for mark not yet implemented features.
     339 *
     340 * \todo Is this the right place for this? It should be used only in
     341 * modules under development.
     342 *
     343 * \todo __PRETTY_FUNCTION__ should be replaced by something
     344 * compiler-independant, like BOOST_CURRENT_FUNCTION
     345 */
     346
     347# define LEMON_FIXME(msg) \
     348    (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, __PRETTY_FUNCTION__, \
     349                          "FIXME: " msg))
Note: See TracChangeset for help on using the changeset viewer.