Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

error.h

Go to the documentation of this file.
00001 /* -*- C++ -*-
00002  * lemon/error.h - Part of LEMON, a generic C++ optimization library
00003  *
00004  * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi
00005  * Kutatocsoport (Egervary Research Group on Combinatorial Optimization,
00006  * EGRES).
00007  *
00008  * Permission to use, modify and distribute this software is granted
00009  * provided that this copyright notice appears in all copies. For
00010  * precise terms see the accompanying LICENSE file.
00011  *
00012  * This software is provided "AS IS" with no warranty of any kind,
00013  * express or implied, and with no claim as to its suitability for any
00014  * purpose.
00015  *
00016  */
00017 
00018 #ifndef LEMON_ERROR_H
00019 #define LEMON_ERROR_H
00020 
00024 
00025 #include <exception>
00026 #include <string>
00027 #include <sstream>
00028 #include <iostream>
00029 #include <cstdlib>
00030 #include <memory>
00031 
00032 namespace lemon {
00033 
00036   
00040   template <typename _Type>
00041   class ExceptionMember {
00042   public:
00043     typedef _Type Type;
00044 
00045     ExceptionMember() throw () {
00046       try {
00047         ptr.reset(new Type());
00048       } catch (...) {}
00049     }
00050 
00051     ExceptionMember(const Type& type) throw () {
00052       try {
00053         ptr.reset(new Type());
00054         if (ptr.get() == 0) return;
00055         *ptr = type;
00056       } catch (...) {}
00057     }
00058 
00059     ExceptionMember(const ExceptionMember& copy) throw() {
00060       try {
00061         if (!copy.valid()) return;
00062         ptr.reset(new Type());
00063         if (ptr.get() == 0) return;
00064         *ptr = copy.get();
00065       } catch (...) {}
00066     }
00067 
00068     ExceptionMember& operator=(const ExceptionMember& copy) {
00069       if (ptr.get() == 0) return;
00070       try {
00071         if (!copy.valid()) return;
00072         *ptr = copy.get();
00073       } catch (...) {}
00074     }
00075 
00076     void set(const Type& type) {
00077       if (ptr.get() == 0) return;
00078       try {
00079         *ptr = type;
00080       } catch (...) {}
00081     }
00082 
00083     const Type& get() const {
00084       return *ptr;
00085     }
00086 
00087     bool valid() const {
00088       return ptr.get() != 0;
00089     }
00090     
00091   private:
00092     std::auto_ptr<_Type> ptr;
00093   };
00094 
00096 
00100   class ErrorMessage {
00101   protected:
00103 
00106     mutable
00107     std::auto_ptr<std::ostringstream> buf;
00108     
00110     bool init() throw() {
00111       try {
00112         buf.reset(new std::ostringstream);
00113       }
00114       catch(...) {
00115         buf.reset();
00116       }
00117       return buf.get();
00118     }
00119 
00120   public:
00121 
00123     ErrorMessage() throw() { init(); }
00124 
00125     ErrorMessage(const ErrorMessage& em) throw() : buf(em.buf) { }
00126 
00128     ErrorMessage(const char *message) throw() {
00129       init();
00130       *this << message;
00131     }
00132 
00134     ErrorMessage(const std::string &message) throw() {
00135       init();
00136       *this << message;
00137     }
00138 
00140     template <typename T>
00141     ErrorMessage& operator<<(const T &t) throw() {
00142       if( ! buf.get() ) return *this;
00143 
00144       try {
00145         *buf << t;
00146       }
00147       catch(...) {
00148         buf.reset();
00149       }
00150       return *this;
00151     }
00152 
00154     const char* message() throw() {
00155       if( ! buf.get() ) return 0;
00156 
00157       const char* mes = 0;
00158       try {
00159         mes = buf->str().c_str();
00160       }
00161       catch(...) {}
00162       return mes;
00163     }
00164     
00165   };
00166 
00172   class Exception : public std::exception {
00173   public:
00175     Exception() {}
00177     virtual ~Exception() throw() {}
00178 
00180     virtual const char* exceptionName() const {
00181       return "lemon::Exception";
00182     }
00183     
00185     virtual const char* what() const throw() {
00186       return exceptionName();
00187     }
00188   };
00189 
00199   class LogicError : public Exception {
00200   public:
00201     virtual const char* exceptionName() const {
00202       return "lemon::LogicError";
00203     }
00204   };
00205 
00212   class UninitializedParameter : public LogicError {
00213   public:
00214     virtual const char* exceptionName() const {
00215       return "lemon::UninitializedParameter";
00216     }
00217   };
00218 
00219   
00227   class RuntimeError : public Exception {
00228   public:
00229     virtual const char* exceptionName() const {
00230       return "lemon::RuntimeError";
00231     }
00232   };
00233 
00235   class RangeError : public RuntimeError {
00236   public:
00237     virtual const char* exceptionName() const {
00238       return "lemon::RangeError";
00239     }
00240   };
00241 
00243   class IOError : public RuntimeError {
00244   public:
00245     virtual const char* exceptionName() const {
00246       return "lemon::IOError";
00247     }
00248   };
00249 
00251   class DataFormatError : public IOError {
00252   protected:
00253     ExceptionMember<std::string> _message;
00254     ExceptionMember<std::string> _file;
00255     int _line;
00256 
00257     mutable ExceptionMember<std::string> _message_holder;
00258   public:
00259 
00260     DataFormatError(const DataFormatError &dfe) : 
00261       IOError(dfe), _message(dfe._message), _file(dfe._file),
00262       _line(dfe._line) {}
00263 
00265     explicit DataFormatError(const char *the_message)
00266       : _message(the_message), _line(0) {}
00267 
00269     DataFormatError(const std::string &file_name, int line_num,
00270                     const char *the_message)
00271       : _message(the_message), _line(line_num) { file(file_name); }
00272 
00274     void line(int line) { _line = line; }
00276     void message(const std::string& message) { _message.set(message); }
00278     void file(const std::string &file) { _file.set(file); }
00279  
00281     int line() const { return _line; }
00283     const char* message() const { 
00284       if (_message.valid() && !_message.get().empty()) {
00285         return _message.get().c_str();
00286       } else {
00287         return 0;
00288       }
00289     }
00290 
00294     const char* file() const {
00295       if (_file.valid() && !_file.get().empty()) {
00296         return _file.get().c_str();
00297       } else {
00298         return 0;
00299       }
00300     }
00301 
00303     virtual const char* what() const throw() {
00304       try {
00305         std::ostringstream ostr;
00306         ostr << exceptionName() << ": ";
00307         if (message()) ostr << message();
00308         if( file() || line() != 0 ) {
00309           ostr << " (";
00310           if( file() ) ostr << "in file '" << file() << "'";
00311           if( file() && line() != 0 ) ostr << " ";
00312           if( line() != 0 ) ostr << "at line " << line();
00313           ostr << ")";
00314         }
00315         _message_holder.set(ostr.str());
00316       }
00317       catch (...) {}
00318       if( _message_holder.valid()) return _message_holder.get().c_str();
00319       return exceptionName();
00320     }
00321 
00322     virtual const char* exceptionName() const {
00323       return "lemon::DataFormatError";
00324     }
00325 
00326     virtual ~DataFormatError() throw() {}
00327   };
00328 
00329   class IOParameterError : public LogicError {
00330   protected:
00331     ExceptionMember<std::string> _message;
00332     ExceptionMember<std::string> _file;
00333 
00334     mutable ExceptionMember<std::string> _message_holder;
00335   public:
00336 
00337     IOParameterError(const IOParameterError &ile) : 
00338       LogicError(ile), _message(ile._message), _file(ile._file) {}
00339 
00341     explicit IOParameterError(const char *the_message)
00342       : _message(the_message) {}
00343 
00345     IOParameterError(const char *file_name, const char *the_message)
00346       : _message(the_message), _file(file_name) {}
00347 
00349     void message(const std::string& message) { _message.set(message); }
00351     void file(const std::string &file) { _file.set(file); }
00352  
00354     const char* message() const { 
00355       if (_message.valid()) {
00356         return _message.get().c_str();
00357       } else {
00358         return 0;
00359       }
00360     }
00361 
00365     const char* file() const {
00366       if (_file.valid()) {
00367         return _file.get().c_str();
00368       } else {
00369         return 0;
00370       }
00371     }
00372 
00374     virtual const char* what() const throw() {
00375       try {
00376         std::ostringstream ostr;
00377         if (message()) ostr << message();
00378         if (file()) ostr << "(when reading file '" << file() << "')";
00379         _message_holder.set(ostr.str());
00380       }
00381       catch (...) {}
00382       if( _message_holder.valid() ) return _message_holder.get().c_str();
00383       return exceptionName();
00384     }
00385 
00386     virtual const char* exceptionName() const {
00387       return "lemon::IOParameterError";
00388     }
00389 
00390     virtual ~IOParameterError() throw() {}
00391   };
00392 
00393 
00395   class AssertionFailedError : public LogicError {
00396   protected:
00397     const char *assertion;
00398     const char *file;
00399     int line;
00400     const char *function;
00401     const char *message;
00402 
00403     mutable ExceptionMember<std::string> _message_holder;
00404   public:
00406     AssertionFailedError(const char *_file, int _line, const char *func,
00407                          const char *msg, const char *_assertion = 0) :
00408       assertion(_assertion), file(_file), line(_line), function(func),
00409       message(msg) {}
00410 
00412     const char* get_assertion() const { return assertion; }
00414     const char* get_message() const { return message; }
00416     const char* get_file() const { return file; }
00418     const char* get_function() const { return function; }
00420     int get_line() const { return line; }
00421 
00422 
00423     virtual const char* what() const throw() {
00424       try {
00425         std::ostringstream ostr;
00426         ostr << file << ":" << line << ": ";
00427         if( function )
00428           ostr << function << ": ";
00429         ostr << message;
00430         if( assertion )
00431            ostr << " (assertion '" << assertion << "' failed)";
00432         _message_holder.set(ostr.str());
00433         return ostr.str().c_str();
00434       }
00435       catch(...) {}
00436       if( _message_holder.valid() ) return _message_holder.get().c_str();
00437       return exceptionName();
00438     }
00439 
00440     virtual const char* exceptionName() const {
00441       return "lemon::AssertionFailedError";
00442     }
00443 
00444     virtual ~AssertionFailedError() throw() {}
00445   };
00446 
00447 
00448   /****************  Macros  ****************/
00449 
00450 
00451   inline
00452   void assert_fail(const char *file, int line, const char *func,
00453                    const char *message, const char *assertion = 0,
00454                    bool do_abort=true)
00455   {
00456     using namespace std;
00457     cerr << file << ":" << line << ": ";
00458     if( func )
00459       cerr << func << ": ";
00460     cerr << message;
00461     if( assertion )
00462       cerr << " (assertion '" << assertion << "' failed)";
00463     cerr << endl;
00464     if(do_abort)
00465       abort();
00466   }
00467 
00468   inline
00469   void assert_fail_throw(const char *file, int line, const char *func,
00470                    const char *message, const char *assertion = 0,
00471                    bool = true)
00472   {
00473     throw AssertionFailedError(file, line, func, message, assertion);
00474   }
00475 
00477 
00478 }
00479 #endif // LEMON_ERROR_H
00480 
00481 #undef LEMON_ASSERT
00482 #undef LEMON_FIXME
00483 
00484 #ifndef LEMON_ASSERT_ABORT
00485 #  define LEMON_ASSERT_ABORT 1
00486 #endif
00487 
00488 #ifndef LEMON_ASSERT_HANDLER
00489 #  ifdef LEMON_ASSERT_EXCEPTION
00490 #    define LEMON_ASSERT_HANDLER ::lemon::assert_fail_throw
00491 #  else
00492 #    define LEMON_ASSERT_HANDLER ::lemon::assert_fail
00493 #  endif
00494 #endif
00495 
00496 #if defined(NDEBUG) || defined(LEMON_DISABLE_ASSERTS)
00497 
00498 #  define LEMON_ASSERT(exp, msg)  (static_cast<void> (0))
00499 
00500 #else
00501 
00521 #  define LEMON_ASSERT(exp, msg)                 \
00522      (static_cast<void> (!!(exp) ? 0 : (         \
00523        LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \
00524                             __PRETTY_FUNCTION__, \
00525                             (msg), #exp, LEMON_ASSERT_ABORT), 0)))
00526 
00527 #endif // NDEBUG || LEMON_DISABLE_ASSERTS
00528 
00539 # define LEMON_FIXME(msg) \
00540     (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, __PRETTY_FUNCTION__, \
00541                           "FIXME: " msg))

Generated on Sat Aug 27 14:14:51 2005 for LEMON by  doxygen 1.4.4