src/work/klao/error.h
changeset 1059 bd97feae7d90
parent 993 21d1b4fa1b24
child 1061 e3433c024123
equal deleted inserted replaced
0:52e909f40c0b 0:76d4dc5cc9bd
    23 
    23 
    24 #include <exception>
    24 #include <exception>
    25 #include <string>
    25 #include <string>
    26 #include <sstream>
    26 #include <sstream>
    27 
    27 
       
    28 #include <boost/shared_ptr.hpp>
    28 
    29 
    29 namespace lemon {
    30 namespace lemon {
       
    31 
       
    32   /// Exception-safe convenient "error message" class.
       
    33   class ErrorMessage {
       
    34   protected:
       
    35     boost::shared_ptr<std::ostringstream> buf;
       
    36     
       
    37     bool init() throw() {
       
    38       try {
       
    39 	buf.reset(new std::ostringstream);
       
    40       }
       
    41       catch(...) {
       
    42 	buf.reset();
       
    43       }
       
    44       return buf;
       
    45     }
       
    46 
       
    47   public:
       
    48 
       
    49     ErrorMessage() throw() { init(); }
       
    50 
       
    51     ErrorMessage(const char *message) throw() {
       
    52       init();
       
    53       *this << message;
       
    54     }
       
    55 
       
    56     ErrorMessage(const std::string &message) throw() {
       
    57       init();
       
    58       *this << message;
       
    59     }
       
    60 
       
    61     template <typename T>
       
    62     ErrorMessage& operator<<(const T &t) throw() {
       
    63       if( !buf ) return *this;
       
    64 
       
    65       try {
       
    66 	*buf << t;
       
    67       }
       
    68       catch(...) {
       
    69 	buf.reset();
       
    70       }
       
    71     }
       
    72 
       
    73     const char* message() throw() {
       
    74       if( !buf ) return 0;
       
    75 
       
    76       const char* mes = 0;
       
    77       try {
       
    78 	mes = buf->str().c_str();
       
    79       }
       
    80       catch(...) {}
       
    81       return mes;
       
    82     }
       
    83     
       
    84   };
    30 
    85 
    31   /**
    86   /**
    32    * \brief Generic exception class.
    87    * \brief Generic exception class.
    33    *
    88    *
    34    * \todo Do we need this?
    89    * Base class for exceptions used in LEMON.
    35    *
       
    36    * \todo Don't we need different kind of exceptions for different kind
       
    37    * of errors?
       
    38    * Shouldn't we use \<stdexcept\> instead?
       
    39    */
    90    */
    40   class Exception : public std::exception {
    91   class Exception : public std::exception, public ErrorMessage {
    41   protected:
       
    42     std::ostringstream buf;
       
    43   public:
    92   public:
    44     Exception() {}
    93     Exception() throw() {}
    45     explicit Exception(const std::string &s) { buf << s; }
    94     explicit Exception(const std::string &s) throw()
    46     Exception(const Exception &e) : std::exception() {
    95       : ErrorMessage(s) {}
    47       buf << e.buf.str();
       
    48     }
       
    49     virtual ~Exception() throw() {}
    96     virtual ~Exception() throw() {}
    50     
    97     
    51     virtual const char* what() const throw() {
    98     virtual const char* what() const throw() {
    52       return buf.str().c_str();
    99       const char *mes = message();
       
   100       if( mes ) return mes;
       
   101       return "lemon::Exception";
       
   102     }
       
   103   };
       
   104 
       
   105 
       
   106   class LogicError : public Exception {
       
   107     explicit LogicError(const std::string &s)
       
   108       : Exception(s) {}
       
   109   };
       
   110 
       
   111   class RuntimeError : public Exception {
       
   112     explicit RuntimeError(const std::string &s)
       
   113       : Exception(s) {}
       
   114   };
       
   115 
       
   116   class RangeError : public RuntimeError {
       
   117     explicit RangeError(const std::string &s)
       
   118       : RuntimeError(s) {}
       
   119   };
       
   120 
       
   121   class IOError : public RuntimeError {
       
   122     explicit IOError(const std::string &s)
       
   123       : RuntimeError(s) {}
       
   124   };
       
   125 
       
   126   class DataFormatError : public IOError {
       
   127     explicit DataFormatError(const std::string &message)
       
   128       : IOError(message) : line(0) {}
       
   129     DataFormatError(const std::string &file_name, int line_num,
       
   130 		    sconst std::string &message)
       
   131       : IOError(message), line(line_num) { set_file(file_name); }
       
   132 
       
   133     void set_line(int line_num) { line=line_num; }
       
   134     void set_file(const std::string &file_name) {
       
   135       try {
       
   136 	file.reset(new std::string);
       
   137 	*file = file_name;
       
   138       }
       
   139       catch(...) {
       
   140 	file.reset();
       
   141       }
    53     }
   142     }
    54 
   143 
    55     template <typename T>
   144     virtual const char* what() const {
    56     Exception& operator<<(T const& t) { buf << t; return *this; }
   145       const char *mes = 0;
       
   146       try {
       
   147 	std::ostringstream ostr;
       
   148 	ostr << IOError::what();
       
   149 	if( file || line ) {
       
   150 	  ostr << " (";
       
   151 	  if( file ) ostr << "in file" << *file;
       
   152 	  if( line ) ostr << " at line" << line;
       
   153 	}
       
   154 	mes = ostr.str().c_str();
       
   155       }
       
   156       catch(...) {}
       
   157       if( mes ) return mes;
       
   158       return "lemon::DataFormatError";
       
   159     }
    57   };
   160   };
    58 
   161 
       
   162 
       
   163 
       
   164   /****************  Macros  ****************/
       
   165 
       
   166 
    59   /**
   167   /**
    60    * \brief Generic error signaling function.
   168    * \brief Macro for assertions with customizable message
    61    *
       
    62    * \todo Do we really need this? Is it helpful?
       
    63    */
   169    */
    64   inline void fault(const std::string &msg) {
   170 
    65     throw Exception(msg);
   171 # define lemon_assert(exp, msg) \
    66   }
   172     if(!(exp)) { \
       
   173       std::cerr << __FILE__ ":" << __LINE__ << ": " << (msg) << std::endl; \
       
   174       abort; \
       
   175     }
       
   176 
    67 
   177 
    68   /**
   178   /**
    69    * \brief Macro for mark not yet implemented features.
   179    * \brief Macro for mark not yet implemented features.
    70    *
   180    *
    71    * \todo Is this the right place for this? It should be used only in
   181    * \todo Is this the right place for this? It should be used only in
    72    * modules under development.
   182    * modules under development.
    73    */
   183    */
    74 
   184 
    75 # define FIXME(msg) \
   185 # define FIXME(msg) lemon_assert(0, "FIXME: " msg)
    76     do { throw ::lemon::Exception() << "FIXME: " msg " (in: "    \
       
    77       __FILE__ ", " << __LINE__ << ")";                          \
       
    78     } while(false)
       
    79 
   186 
    80 }
   187 }
    81 #endif // LEMON_ERROR_H
   188 #endif // LEMON_ERROR_H