[Lemon-commits] [lemon_svn] klao: r1463 - in hugo/trunk/src/work: . klao

Lemon SVN svn at lemon.cs.elte.hu
Mon Nov 6 20:45:39 CET 2006


Author: klao
Date: Mon Jan 10 00:28:18 2005
New Revision: 1463

Added:
   hugo/trunk/src/work/klao/error_test.cc
Modified:
   hugo/trunk/src/work/klao/   (props changed)
   hugo/trunk/src/work/klao/Makefile
   hugo/trunk/src/work/klao/error.h
   hugo/trunk/src/work/makefile

Log:
Advances in error.h

 * More clear exception usage concept
 * sketch of LEMON_ASSERT interface
 * test file


Modified: hugo/trunk/src/work/klao/Makefile
==============================================================================
--- hugo/trunk/src/work/klao/Makefile	(original)
+++ hugo/trunk/src/work/klao/Makefile	Mon Jan 10 00:28:18 2005
@@ -1,4 +1,5 @@
-BINARIES = tag_demo
+BINARIES = error_test
 INCLUDEDIRS= -I. -I.. -I../.. -I../{marci,jacint,alpar,johanna,athos,akos} -I$(HOME)/boost
 include ../makefile
 
+CXXFLAGS += $(C)

Modified: hugo/trunk/src/work/klao/error.h
==============================================================================
--- hugo/trunk/src/work/klao/error.h	(original)
+++ hugo/trunk/src/work/klao/error.h	Mon Jan 10 00:28:18 2005
@@ -19,23 +19,29 @@
 
 //! \ingroup misc
 //! \file
-//! \brief Basic error handling (signaling) routines.
+//! \brief Basic exception classes and error handling.
 
 #include <exception>
 #include <string>
 #include <sstream>
+#include <iostream>
+#include <cstdlib>
 
 #include <boost/shared_ptr.hpp>
 
 namespace lemon {
 
   /// 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 
+    ///\e 
     boost::shared_ptr<std::ostringstream> buf;
     
-  ///\e 
+    ///\e 
     bool init() throw() {
       try {
 	buf.reset(new std::ostringstream);
@@ -48,22 +54,22 @@
 
   public:
 
-  ///\e 
+    ///\e 
     ErrorMessage() throw() { init(); }
 
-  ///\e 
+    ///\e 
     ErrorMessage(const char *message) throw() {
       init();
       *this << message;
     }
 
-  ///\e 
+    ///\e 
     ErrorMessage(const std::string &message) throw() {
       init();
       *this << message;
     }
 
-  ///\e 
+    ///\e 
     template <typename T>
     ErrorMessage& operator<<(const T &t) throw() {
       if( !buf ) return *this;
@@ -76,7 +82,7 @@
       }
     }
 
-  ///\e 
+    ///\e 
     const char* message() throw() {
       if( !buf ) return 0;
 
@@ -95,65 +101,81 @@
    *
    * Base class for exceptions used in LEMON.
    */
-  class Exception : public std::exception, public ErrorMessage {
+  class Exception : public std::exception {
+  protected:
+    ///\e
+    const char *message;
+
   public:
-  ///\e 
-    Exception() throw() {}
-  ///\e 
-    explicit Exception(const std::string &s) throw()
-      : ErrorMessage(s) {}
-  ///\e 
+    ///\e 
+    Exception() throw() : message(0) {}
+    ///\e 
+    explicit Exception(const char *msg) throw()
+      : message(msg) {}
+    ///\e 
     virtual ~Exception() throw() {}
     
-  ///\e 
+    ///\e 
     virtual const char* what() const throw() {
-      const char *mes = message();
-      if( mes ) return mes;
+      if( message ) return message;
       return "lemon::Exception";
     }
   };
 
   ///\e 
   class LogicError : public Exception {
-  ///\e 
-    explicit LogicError(const std::string &s)
+  public:
+    ///\e 
+    explicit LogicError() {}
+    ///\e 
+    explicit LogicError(const char *s)
       : Exception(s) {}
   };
 
   ///\e 
   class RuntimeError : public Exception {
-  ///\e 
-    explicit RuntimeError(const std::string &s)
+  public:
+    ///\e
+    explicit RuntimeError() {}
+    ///\e
+    explicit RuntimeError(const char *s)
       : Exception(s) {}
   };
 
-  ///\e 
+  ///\e
   class RangeError : public RuntimeError {
-  ///\e 
-    explicit RangeError(const std::string &s)
+  public:
+    ///\e 
+    explicit RangeError(const char *s)
       : RuntimeError(s) {}
   };
 
   ///\e 
   class IOError : public RuntimeError {
-  ///\e 
-    explicit IOError(const std::string &s)
+  public:
+    ///\e 
+    explicit IOError(const char *s)
       : RuntimeError(s) {}
   };
 
   ///\e 
   class DataFormatError : public IOError {
-  ///\e 
-    explicit DataFormatError(const std::string &message)
-      : IOError(message) : line(0) {}
-  ///\e 
+  protected:
+    int line;
+    boost::shared_ptr<std::string> file;
+
+  public:
+    ///\e 
+    explicit DataFormatError(const char *message)
+      : IOError(message), line(0) {}
+    ///\e 
     DataFormatError(const std::string &file_name, int line_num,
-		    const std::string &message)
+		    const char *message)
       : IOError(message), line(line_num) { set_file(file_name); }
 
-  ///\e 
+    ///\e 
     void set_line(int line_num) { line=line_num; }
-  ///\e 
+    ///\e 
     void set_file(const std::string &file_name) {
       try {
 	file.reset(new std::string);
@@ -164,16 +186,31 @@
       }
     }
 
-  ///\e 
-    virtual const char* what() const {
+    ///\e
+    int get_line() const { return line; }
+
+    /// \brief Returns the filename.
+    ///
+    /// Returns "(unknown)" if the filename was not specified.
+    const char* get_file() const {
+      if( file )
+	return file->c_str();
+      else
+	return "(unknown)";
+    }
+
+    ///\e 
+    virtual const char* what() const throw() {
       const char *mes = 0;
       try {
 	std::ostringstream ostr;
 	ostr << IOError::what();
 	if( file || line ) {
 	  ostr << " (";
-	  if( file ) ostr << "in file" << *file;
-	  if( line ) ostr << " at line" << line;
+	  if( file ) ostr << "in file '" << *file << "'";
+	  if( file && line ) ostr << " ";
+	  if( line ) ostr << "at line " << line;
+	  ostr << ")";
 	}
 	mes = ostr.str().c_str();
       }
@@ -181,32 +218,132 @@
       if( mes ) return mes;
       return "lemon::DataFormatError";
     }
+
+    virtual ~DataFormatError() throw() {}
   };
 
 
+  class AssertionFailedError : public LogicError {
+  protected:
+    const char *assertion;
+    const char *file;
+    int line;
+    const char *function;
+    const char *message;
+  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; }
 
-  /****************  Macros  ****************/
 
+    virtual const char* what() const throw() {
+      const char *mes = 0;
+      try {
+	std::ostringstream ostr;
+	ostr << file << ":" << line << ": ";
+	if( function )
+	  ostr << function << ": ";
+	ostr << message;
+	if( assertion )
+	  ostr << " (assertion '" << assertion << "' failed)";
+	mes = ostr.str().c_str();
+      }
+      catch(...) {}
+      if( mes ) return mes;
+      return "lemon::AssertionFailedError";
+    }
+
+    virtual ~AssertionFailedError() throw() {}
+  };
 
-  /**
-   * \brief Macro for assertions with customizable message
-   */
 
-# define lemon_assert(exp, msg) \
-    if(!(exp)) { \
-      std::cerr << __FILE__ ":" << __LINE__ << ": " << (msg) << std::endl; \
-      abort; \
-    }
+  /****************  Macros  ****************/
 
 
-  /**
-   * \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.
-   */
+  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);
+  }
 
-# define FIXME(msg) lemon_assert(0, "FIXME: " msg)
 
 }
 #endif // LEMON_ERROR_H
+
+#undef LEMON_ASSERT
+#undef LEMON_FIXME
+
+#ifndef LEMON_ASSERT_ABORT
+#  define LEMON_ASSERT_ABORT 1
+#endif
+
+#ifndef LEMON_ASSERT_HANDLER
+#  define LEMON_ASSERT_HANDLER ::lemon::assert_fail
+#endif
+
+#if defined(NDEBUG) || defined(LEMON_DISABLE_ASSERTS)
+
+#  define LEMON_ASSERT(exp, msg)  (static_cast<void> (0))
+
+#else
+
+/**
+ * \brief Macro for assertions with customizable message
+ *
+ * \todo __PRETTY_FUNCTION__ should be replaced by something
+ * compiler-independant, like BOOST_CURRENT_FUNCTION
+ */
+
+#  define LEMON_ASSERT(exp, msg)                 \
+     (static_cast<void> (!!(exp) ? 0 : (         \
+       LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \
+                            __PRETTY_FUNCTION__, \
+			    (msg), #exp, LEMON_ASSERT_ABORT), 0)))
+
+# endif // NDEBUG
+
+/**
+ * \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-independant, like BOOST_CURRENT_FUNCTION
+ */
+
+# define LEMON_FIXME(msg) \
+    (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, __PRETTY_FUNCTION__, \
+			  "FIXME: " msg))

Added: hugo/trunk/src/work/klao/error_test.cc
==============================================================================
--- (empty file)
+++ hugo/trunk/src/work/klao/error_test.cc	Mon Jan 10 00:28:18 2005
@@ -0,0 +1,57 @@
+#include <iostream>
+#include <string>
+
+#define LEMON_ASSERT_ABORT 0
+#include <error.h>
+
+using namespace std;
+
+void parse_line() {
+  throw lemon::DataFormatError("Syntax error");
+}
+
+void parse_file(string fn) {
+  try {
+    parse_line();
+  }
+  catch(lemon::DataFormatError &e) {
+    e.set_file(fn);
+    e.set_line(5);
+    throw;
+  }
+}
+
+void fail_assert();
+
+int main() {
+  try {
+    parse_file("input.txt");
+  }
+  catch(exception &e) {
+    cerr << "Exception caught: " << endl;
+    cerr << e.what() << endl;
+  }
+
+  try {
+    fail_assert();
+  }
+  catch(exception &e) {
+    cerr << "Exception caught: " << endl;
+    cerr << e.what() << endl;
+  }
+
+  // assert(1==0);
+  LEMON_ASSERT(1==0, "Ellentmondas");
+  LEMON_FIXME("Nincs kesz");
+}
+
+#undef LEMON_ASSERT_HANDLER
+#define LEMON_ASSERT_HANDLER ::lemon::assert_fail_throw
+
+#include <error.h>
+
+void fail_assert() {
+  LEMON_ASSERT(2*2==5, "Marson vagyunk");
+}
+
+

Modified: hugo/trunk/src/work/makefile
==============================================================================
--- hugo/trunk/src/work/makefile	(original)
+++ hugo/trunk/src/work/makefile	Mon Jan 10 00:28:18 2005
@@ -1,5 +1,5 @@
 INCLUDEDIRS ?= -I.. -I. -I./{marci,jacint,alpar,klao,akos}
-CXXFLAGS = -g -O3 -W -Wall $(INCLUDEDIRS) -ansi -pedantic
+CXXFLAGS += -g -O2 -W -Wall $(INCLUDEDIRS) -ansi -pedantic
 
 BINARIES ?= bin_heap_demo
 



More information about the Lemon-commits mailing list