Latest LEMON exception and assert concepts
authorklao
Thu, 03 Feb 2005 19:24:42 +0000
changeset 11205d8d64bde9c5
parent 1119 d3504fc075dc
child 1121 8f066fdf6dc9
Latest LEMON exception and assert concepts
src/work/klao/error.h
src/work/klao/error_test.cc
     1.1 --- a/src/work/klao/error.h	Thu Feb 03 16:08:56 2005 +0000
     1.2 +++ b/src/work/klao/error.h	Thu Feb 03 19:24:42 2005 +0000
     1.3 @@ -102,99 +102,112 @@
     1.4     * Base class for exceptions used in LEMON.
     1.5     */
     1.6    class Exception : public std::exception {
     1.7 -  protected:
     1.8 -    ///\e
     1.9 -    const char *message;
    1.10 -
    1.11    public:
    1.12      ///\e 
    1.13 -    Exception() throw() : message(0) {}
    1.14 -    ///\e 
    1.15 -    explicit Exception(const char *msg) throw()
    1.16 -      : message(msg) {}
    1.17 +    Exception() {}
    1.18      ///\e 
    1.19      virtual ~Exception() throw() {}
    1.20 +
    1.21 +    ///\e
    1.22 +    virtual const char* exceptionName() const {
    1.23 +      return "lemon::Exception";
    1.24 +    }
    1.25      
    1.26      ///\e 
    1.27      virtual const char* what() const throw() {
    1.28 -      if( message ) return message;
    1.29 -      return "lemon::Exception";
    1.30 +      return exceptionName();
    1.31      }
    1.32    };
    1.33  
    1.34 -  ///\e 
    1.35 +  /**
    1.36 +   * \brief One of the two main subclasses of \ref Exception.
    1.37 +   *
    1.38 +   * Logic errors represent problems in the internal logic of a program;
    1.39 +   * in theory, these are preventable, and even detectable before the
    1.40 +   * program runs (e.g., violations of class invariants).
    1.41 +   *
    1.42 +   * For a typical example \see UninitializedParameterError.
    1.43 +   */
    1.44    class LogicError : public Exception {
    1.45    public:
    1.46 -    ///\e 
    1.47 -    explicit LogicError() {}
    1.48 -    ///\e 
    1.49 -    explicit LogicError(const char *s)
    1.50 -      : Exception(s) {}
    1.51 +    virtual const char* exceptionName() const {
    1.52 +      return "lemon::LogicError";
    1.53 +    }
    1.54    };
    1.55  
    1.56 -  ///\e 
    1.57 +  
    1.58 +  /**
    1.59 +   * \brief One of the two main subclasses of \ref Exception.
    1.60 +   *
    1.61 +   * Runtime errors represent problems outside the scope of a program;
    1.62 +   * they cannot be easily predicted and can generally only be caught as
    1.63 +   * the program executes.
    1.64 +   */
    1.65    class RuntimeError : public Exception {
    1.66    public:
    1.67 -    ///\e
    1.68 -    explicit RuntimeError() {}
    1.69 -    ///\e
    1.70 -    explicit RuntimeError(const char *s)
    1.71 -      : Exception(s) {}
    1.72 +    virtual const char* exceptionName() const {
    1.73 +      return "lemon::RuntimeError";
    1.74 +    }
    1.75    };
    1.76  
    1.77    ///\e
    1.78    class RangeError : public RuntimeError {
    1.79    public:
    1.80 -    ///\e 
    1.81 -    explicit RangeError(const char *s)
    1.82 -      : RuntimeError(s) {}
    1.83 +    virtual const char* exceptionName() const {
    1.84 +      return "lemon::RangeError";
    1.85 +    }
    1.86    };
    1.87  
    1.88    ///\e 
    1.89    class IOError : public RuntimeError {
    1.90    public:
    1.91 -    ///\e 
    1.92 -    explicit IOError(const char *s)
    1.93 -      : RuntimeError(s) {}
    1.94 +    virtual const char* exceptionName() const {
    1.95 +      return "lemon::IOError";
    1.96 +    }
    1.97    };
    1.98  
    1.99    ///\e 
   1.100    class DataFormatError : public IOError {
   1.101    protected:
   1.102 -    int line;
   1.103 -    boost::shared_ptr<std::string> file;
   1.104 +    const char *_message;
   1.105 +    int _line;
   1.106 +    boost::shared_ptr<std::string> _file;
   1.107  
   1.108    public:
   1.109      ///\e 
   1.110 -    explicit DataFormatError(const char *message)
   1.111 -      : IOError(message), line(0) {}
   1.112 +    explicit DataFormatError(const char *the_message)
   1.113 +      : _message(the_message), _line(0) {}
   1.114      ///\e 
   1.115      DataFormatError(const std::string &file_name, int line_num,
   1.116 -		    const char *message)
   1.117 -      : IOError(message), line(line_num) { set_file(file_name); }
   1.118 +		    const char *the_message)
   1.119 +      : _message(the_message), _line(line_num) { file(file_name); }
   1.120  
   1.121      ///\e 
   1.122 -    void set_line(int line_num) { line=line_num; }
   1.123 +    void line(int line_num) { _line=line_num; }
   1.124      ///\e 
   1.125 -    void set_file(const std::string &file_name) {
   1.126 +    void message(char *the_message) { _message=the_message; }
   1.127 +    ///\e 
   1.128 +    void file(const std::string &file_name) {
   1.129        try {
   1.130 -	file.reset(new std::string);
   1.131 -	*file = file_name;
   1.132 +	_file.reset(new std::string);
   1.133 +	*_file = file_name;
   1.134        }
   1.135        catch(...) {
   1.136 -	file.reset();
   1.137 +	_file.reset();
   1.138        }
   1.139      }
   1.140  
   1.141      ///\e
   1.142 -    int get_line() const { return line; }
   1.143 +    int line() const { return _line; }
   1.144 +    ///\e
   1.145 +    const char* message() const { return _message; }
   1.146  
   1.147      /// \brief Returns the filename.
   1.148      ///
   1.149      /// Returns \e "(unknown)" if the filename was not specified.
   1.150 -    const char* get_file() const {
   1.151 -      if( file )
   1.152 -	return file->c_str();
   1.153 +    const char* file() const {
   1.154 +      if( _file )
   1.155 +	return _file->c_str();
   1.156        else
   1.157  	return "(unknown)";
   1.158      }
   1.159 @@ -204,18 +217,22 @@
   1.160        const char *mes = 0;
   1.161        try {
   1.162  	std::ostringstream ostr;
   1.163 -	ostr << IOError::what();
   1.164 -	if( file || line ) {
   1.165 +	ostr << _message;
   1.166 +	if( _file || _line ) {
   1.167  	  ostr << " (";
   1.168 -	  if( file ) ostr << "in file '" << *file << "'";
   1.169 -	  if( file && line ) ostr << " ";
   1.170 -	  if( line ) ostr << "at line " << line;
   1.171 +	  if( _file ) ostr << "in file '" << *_file << "'";
   1.172 +	  if( _file && _line ) ostr << " ";
   1.173 +	  if( _line ) ostr << "at line " << _line;
   1.174  	  ostr << ")";
   1.175  	}
   1.176  	mes = ostr.str().c_str();
   1.177        }
   1.178        catch(...) {}
   1.179        if( mes ) return mes;
   1.180 +      return exceptionName();
   1.181 +    }
   1.182 +
   1.183 +    virtual const char* exceptionName() const {
   1.184        return "lemon::DataFormatError";
   1.185      }
   1.186  
   1.187 @@ -264,6 +281,10 @@
   1.188        }
   1.189        catch(...) {}
   1.190        if( mes ) return mes;
   1.191 +      return exceptionName();
   1.192 +    }
   1.193 +
   1.194 +    virtual const char* exceptionName() const {
   1.195        return "lemon::AssertionFailedError";
   1.196      }
   1.197  
   1.198 @@ -311,7 +332,11 @@
   1.199  #endif
   1.200  
   1.201  #ifndef LEMON_ASSERT_HANDLER
   1.202 -#  define LEMON_ASSERT_HANDLER ::lemon::assert_fail
   1.203 +#  ifdef LEMON_ASSERT_EXCEPTION
   1.204 +#    define LEMON_ASSERT_HANDLER ::lemon::assert_fail_throw
   1.205 +#  else
   1.206 +#    define LEMON_ASSERT_HANDLER ::lemon::assert_fail
   1.207 +#  endif
   1.208  #endif
   1.209  
   1.210  #if defined(NDEBUG) || defined(LEMON_DISABLE_ASSERTS)
   1.211 @@ -323,6 +348,18 @@
   1.212  /**
   1.213   * \brief Macro for assertions with customizable message
   1.214   *
   1.215 + * Macro for assertions with customizable message.
   1.216 + *
   1.217 + * The behaviour can be customized with LEMON_ASSERT_HANDLER,
   1.218 + * LEMON_ASSERT_EXCEPTION and LEMON_ASSERT_ABORT defines. Asserts can be
   1.219 + * disabled by defining either NDEBUG or LEMON_DISABLE_ASSERTS macros.
   1.220 + *
   1.221 + * \todo We should provide some way to reset to the default behaviour,
   1.222 + * shouldn't we?
   1.223 + *
   1.224 + * \todo This whole 'assert' business should be placed in a separate
   1.225 + * include file.
   1.226 + *
   1.227   * \todo __PRETTY_FUNCTION__ should be replaced by something
   1.228   * compiler-independant, like BOOST_CURRENT_FUNCTION
   1.229   */
   1.230 @@ -333,7 +370,7 @@
   1.231                              __PRETTY_FUNCTION__, \
   1.232  			    (msg), #exp, LEMON_ASSERT_ABORT), 0)))
   1.233  
   1.234 -# endif // NDEBUG
   1.235 +#endif // NDEBUG || LEMON_DISABLE_ASSERTS
   1.236  
   1.237  /**
   1.238   * \brief Macro for mark not yet implemented features.
     2.1 --- a/src/work/klao/error_test.cc	Thu Feb 03 16:08:56 2005 +0000
     2.2 +++ b/src/work/klao/error_test.cc	Thu Feb 03 19:24:42 2005 +0000
     2.3 @@ -15,8 +15,8 @@
     2.4      parse_line();
     2.5    }
     2.6    catch(lemon::DataFormatError &e) {
     2.7 -    e.set_file(fn);
     2.8 -    e.set_line(5);
     2.9 +    e.file(fn);
    2.10 +    e.line(5);
    2.11      throw;
    2.12    }
    2.13  }
    2.14 @@ -27,26 +27,47 @@
    2.15    try {
    2.16      parse_file("input.txt");
    2.17    }
    2.18 +  catch(lemon::Exception &e) {
    2.19 +    cerr << "Exception '" << e.exceptionName()
    2.20 +	 << "' caught: " << endl;
    2.21 +    cerr << e.what() << endl;
    2.22 +  }
    2.23    catch(exception &e) {
    2.24      cerr << "Exception caught: " << endl;
    2.25      cerr << e.what() << endl;
    2.26    }
    2.27  
    2.28    try {
    2.29 +    throw lemon::LogicError();
    2.30 +  }
    2.31 +  catch(lemon::Exception &e) {
    2.32 +    cerr << "Exception '" << e.exceptionName()
    2.33 +	 << "' caught: " << endl;
    2.34 +    cerr << e.what() << endl;
    2.35 +  }
    2.36 +
    2.37 +  try {
    2.38      fail_assert();
    2.39    }
    2.40 +  catch(lemon::Exception &e) {
    2.41 +    cerr << "Exception '" << e.exceptionName()
    2.42 +	 << "' caught: " << endl;
    2.43 +    cerr << e.what() << endl;
    2.44 +  }
    2.45    catch(exception &e) {
    2.46      cerr << "Exception caught: " << endl;
    2.47      cerr << e.what() << endl;
    2.48    }
    2.49  
    2.50 +  cerr << endl;
    2.51 +
    2.52    // assert(1==0);
    2.53    LEMON_ASSERT(1==0, "Ellentmondas");
    2.54    LEMON_FIXME("Nincs kesz");
    2.55  }
    2.56  
    2.57  #undef LEMON_ASSERT_HANDLER
    2.58 -#define LEMON_ASSERT_HANDLER ::lemon::assert_fail_throw
    2.59 +#define LEMON_ASSERT_EXCEPTION
    2.60  
    2.61  #include <error.h>
    2.62