error.h

Go to the documentation of this file.
00001 /* -*- C++ -*-
00002  *
00003  * This file is a part of LEMON, a generic C++ optimization library
00004  *
00005  * Copyright (C) 2003-2006
00006  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
00007  * (Egervary Research Group on Combinatorial Optimization, EGRES).
00008  *
00009  * Permission to use, modify and distribute this software is granted
00010  * provided that this copyright notice appears in all copies. For
00011  * precise terms see the accompanying LICENSE file.
00012  *
00013  * This software is provided "AS IS" with no warranty of any kind,
00014  * express or implied, and with no claim as to its suitability for any
00015  * purpose.
00016  *
00017  */
00018 
00019 #ifndef LEMON_ERROR_H
00020 #define LEMON_ERROR_H
00021 
00025 
00026 #include <exception>
00027 #include <string>
00028 #include <sstream>
00029 #include <iostream>
00030 #include <cstdlib>
00031 #include <memory>
00032 
00033 namespace lemon {
00034 
00037   
00041   template <typename _Type>
00042   class ExceptionMember {
00043   public:
00044     typedef _Type Type;
00045 
00046     ExceptionMember() throw () {
00047       try {
00048         ptr.reset(new Type());
00049       } catch (...) {}
00050     }
00051 
00052     ExceptionMember(const Type& type) throw () {
00053       try {
00054         ptr.reset(new Type());
00055         if (ptr.get() == 0) return;
00056         *ptr = type;
00057       } catch (...) {}
00058     }
00059 
00060     ExceptionMember(const ExceptionMember& copy) throw() {
00061       try {
00062         if (!copy.valid()) return;
00063         ptr.reset(new Type());
00064         if (ptr.get() == 0) return;
00065         *ptr = copy.get();
00066       } catch (...) {}
00067     }
00068 
00069     ExceptionMember& operator=(const ExceptionMember& copy) {
00070       if (ptr.get() == 0) return;
00071       try {
00072         if (!copy.valid()) return;
00073         *ptr = copy.get();
00074       } catch (...) {}
00075     }
00076 
00077     void set(const Type& type) {
00078       if (ptr.get() == 0) return;
00079       try {
00080         *ptr = type;
00081       } catch (...) {}
00082     }
00083 
00084     const Type& get() const {
00085       return *ptr;
00086     }
00087 
00088     bool valid() const {
00089       return ptr.get() != 0;
00090     }
00091     
00092   private:
00093     std::auto_ptr<_Type> ptr;
00094   };
00095 
00097 
00101   class ErrorMessage {
00102   protected:
00104 
00107     mutable
00108     std::auto_ptr<std::ostringstream> buf;
00109     
00111     bool init() throw() {
00112       try {
00113         buf.reset(new std::ostringstream);
00114       }
00115       catch(...) {
00116         buf.reset();
00117       }
00118       return buf.get();
00119     }
00120 
00121   public:
00122 
00124     ErrorMessage() throw() { init(); }
00125 
00126     ErrorMessage(const ErrorMessage& em) throw() : buf(em.buf) { }
00127 
00129     ErrorMessage(const char *message) throw() {
00130       init();
00131       *this << message;
00132     }
00133 
00135     ErrorMessage(const std::string &message) throw() {
00136       init();
00137       *this << message;
00138     }
00139 
00141     template <typename T>
00142     ErrorMessage& operator<<(const T &t) throw() {
00143       if( ! buf.get() ) return *this;
00144 
00145       try {
00146         *buf << t;
00147       }
00148       catch(...) {
00149         buf.reset();
00150       }
00151       return *this;
00152     }
00153 
00155     const char* message() throw() {
00156       if( ! buf.get() ) return 0;
00157 
00158       const char* mes = 0;
00159       try {
00160         mes = buf->str().c_str();
00161       }
00162       catch(...) {}
00163       return mes;
00164     }
00165     
00166   };
00167 
00173   class Exception : public std::exception {
00174   public:
00176     Exception() {}
00178     virtual ~Exception() throw() {}
00179 
00181     virtual const char* exceptionName() const {
00182       return "lemon::Exception";
00183     }
00184     
00186     virtual const char* what() const throw() {
00187       return exceptionName();
00188     }
00189   };
00190 
00200   class LogicError : public Exception {
00201   public:
00202     virtual const char* exceptionName() const {
00203       return "lemon::LogicError";
00204     }
00205   };
00206 
00213   class UninitializedParameter : public LogicError {
00214   public:
00215     virtual const char* exceptionName() const {
00216       return "lemon::UninitializedParameter";
00217     }
00218   };
00219 
00220   
00228   class RuntimeError : public Exception {
00229   public:
00230     virtual const char* exceptionName() const {
00231       return "lemon::RuntimeError";
00232     }
00233   };
00234 
00236   class RangeError : public RuntimeError {
00237   public:
00238     virtual const char* exceptionName() const {
00239       return "lemon::RangeError";
00240     }
00241   };
00242 
00244   class IOError : public RuntimeError {
00245   public:
00246     virtual const char* exceptionName() const {
00247       return "lemon::IOError";
00248     }
00249   };
00250 
00252   class DataFormatError : public IOError {
00253   protected:
00254     ExceptionMember<std::string> _message;
00255     ExceptionMember<std::string> _file;
00256     int _line;
00257 
00258     mutable ExceptionMember<std::string> _message_holder;
00259   public:
00260 
00261     DataFormatError(const DataFormatError &dfe) : 
00262       IOError(dfe), _message(dfe._message), _file(dfe._file),
00263       _line(dfe._line) {}
00264 
00266     explicit DataFormatError(const char *the_message)
00267       : _message(the_message), _line(0) {}
00268 
00270     DataFormatError(const std::string &file_name, int line_num,
00271                     const char *the_message)
00272       : _message(the_message), _line(line_num) { file(file_name); }
00273 
00275     void line(int line) { _line = line; }
00277     void message(const std::string& message) { _message.set(message); }
00279     void file(const std::string &file) { _file.set(file); }
00280  
00282     int line() const { return _line; }
00284     const char* message() const { 
00285       if (_message.valid() && !_message.get().empty()) {
00286         return _message.get().c_str();
00287       } else {
00288         return 0;
00289       }
00290     }
00291 
00295     const char* file() const {
00296       if (_file.valid() && !_file.get().empty()) {
00297         return _file.get().c_str();
00298       } else {
00299         return 0;
00300       }
00301     }
00302 
00304     virtual const char* what() const throw() {
00305       try {
00306         std::ostringstream ostr;
00307         ostr << exceptionName() << ": ";
00308         if (message()) ostr << message();
00309         if( file() || line() != 0 ) {
00310           ostr << " (";
00311           if( file() ) ostr << "in file '" << file() << "'";
00312           if( file() && line() != 0 ) ostr << " ";
00313           if( line() != 0 ) ostr << "at line " << line();
00314           ostr << ")";
00315         }
00316         _message_holder.set(ostr.str());
00317       }
00318       catch (...) {}
00319       if( _message_holder.valid()) return _message_holder.get().c_str();
00320       return exceptionName();
00321     }
00322 
00323     virtual const char* exceptionName() const {
00324       return "lemon::DataFormatError";
00325     }
00326 
00327     virtual ~DataFormatError() throw() {}
00328   };
00329 
00331   class FileOpenError : public IOError {
00332   protected:
00333     ExceptionMember<std::string> _file;
00334 
00335     mutable ExceptionMember<std::string> _message_holder;
00336   public:
00337 
00338     FileOpenError(const FileOpenError &foe) : 
00339       IOError(foe), _file(foe._file) {}
00340 
00342     explicit FileOpenError(const std::string& file)
00343       : _file(file) {}
00344 
00345 
00347     void file(const std::string &file) { _file.set(file); }
00348  
00352     const char* file() const {
00353       if (_file.valid() && !_file.get().empty()) {
00354         return _file.get().c_str();
00355       } else {
00356         return 0;
00357       }
00358     }
00359 
00361     virtual const char* what() const throw() {
00362       try {
00363         std::ostringstream ostr;
00364         ostr << exceptionName() << ": ";
00365         ostr << "Cannot open file - " << file();
00366         _message_holder.set(ostr.str());
00367       }
00368       catch (...) {}
00369       if( _message_holder.valid()) return _message_holder.get().c_str();
00370       return exceptionName();
00371     }
00372 
00373     virtual const char* exceptionName() const {
00374       return "lemon::FileOpenError";
00375     }
00376 
00377     virtual ~FileOpenError() throw() {}
00378   };
00379 
00380   class IOParameterError : public IOError {
00381   protected:
00382     ExceptionMember<std::string> _message;
00383     ExceptionMember<std::string> _file;
00384 
00385     mutable ExceptionMember<std::string> _message_holder;
00386   public:
00387 
00388     IOParameterError(const IOParameterError &ile) : 
00389       IOError(ile), _message(ile._message), _file(ile._file) {}
00390 
00392     explicit IOParameterError(const char *the_message)
00393       : _message(the_message) {}
00394 
00396     IOParameterError(const char *file_name, const char *the_message)
00397       : _message(the_message), _file(file_name) {}
00398 
00400     void message(const std::string& message) { _message.set(message); }
00402     void file(const std::string &file) { _file.set(file); }
00403  
00405     const char* message() const { 
00406       if (_message.valid()) {
00407         return _message.get().c_str();
00408       } else {
00409         return 0;
00410       }
00411     }
00412 
00416     const char* file() const {
00417       if (_file.valid()) {
00418         return _file.get().c_str();
00419       } else {
00420         return 0;
00421       }
00422     }
00423 
00425     virtual const char* what() const throw() {
00426       try {
00427         std::ostringstream ostr;
00428         if (message()) ostr << message();
00429         if (file()) ostr << "(when reading file '" << file() << "')";
00430         _message_holder.set(ostr.str());
00431       }
00432       catch (...) {}
00433       if( _message_holder.valid() ) return _message_holder.get().c_str();
00434       return exceptionName();
00435     }
00436 
00437     virtual const char* exceptionName() const {
00438       return "lemon::IOParameterError";
00439     }
00440 
00441     virtual ~IOParameterError() throw() {}
00442   };
00443 
00444 
00446   class AssertionFailedError : public LogicError {
00447   protected:
00448     const char *assertion;
00449     const char *file;
00450     int line;
00451     const char *function;
00452     const char *message;
00453 
00454     mutable ExceptionMember<std::string> _message_holder;
00455   public:
00457     AssertionFailedError(const char *_file, int _line, const char *func,
00458                          const char *msg, const char *_assertion = 0) :
00459       assertion(_assertion), file(_file), line(_line), function(func),
00460       message(msg) {}
00461 
00463     const char* get_assertion() const { return assertion; }
00465     const char* get_message() const { return message; }
00467     const char* get_file() const { return file; }
00469     const char* get_function() const { return function; }
00471     int get_line() const { return line; }
00472 
00473 
00474     virtual const char* what() const throw() {
00475       try {
00476         std::ostringstream ostr;
00477         ostr << file << ":" << line << ": ";
00478         if( function )
00479           ostr << function << ": ";
00480         ostr << message;
00481         if( assertion )
00482            ostr << " (assertion '" << assertion << "' failed)";
00483         _message_holder.set(ostr.str());
00484         return ostr.str().c_str();
00485       }
00486       catch(...) {}
00487       if( _message_holder.valid() ) return _message_holder.get().c_str();
00488       return exceptionName();
00489     }
00490 
00491     virtual const char* exceptionName() const {
00492       return "lemon::AssertionFailedError";
00493     }
00494 
00495     virtual ~AssertionFailedError() throw() {}
00496   };
00497 
00498 
00499   /****************  Macros  ****************/
00500 
00501 
00502   template <typename Exception>
00503   inline void assert_fail(const char *file, int line, const char *func,
00504                    Exception exception, const char *assertion = 0,
00505                    bool do_abort=true)
00506   {
00507     using namespace std;
00508     cerr << file << ":" << line << ": ";
00509     if( func )
00510       cerr << func << ": ";
00511     cerr << exception.what();
00512     if( assertion )
00513       cerr << " (assertion '" << assertion << "' failed)";
00514     cerr << endl;
00515     if(do_abort)
00516       abort();
00517   }
00518 
00519   template <>
00520   inline void assert_fail<const char *>(const char *file, int line, const char *func,
00521                                  const char *message, 
00522                                  const char *assertion,
00523                                  bool do_abort)
00524   {
00525     using namespace std;
00526     cerr << file << ":" << line << ": ";
00527     if( func )
00528       cerr << func << ": ";
00529     cerr << message;
00530     if( assertion )
00531       cerr << " (assertion '" << assertion << "' failed)";
00532     cerr << endl;
00533     if(do_abort)
00534       abort();
00535   }
00536 
00537   template <typename Exception>
00538   inline void assert_fail_failure(const char *file, int line, const char *func,
00539                            Exception exception, 
00540                            const char *assertion = 0,
00541                            bool = true)
00542   {
00543     throw AssertionFailedError(file, line, func, exception.what(), assertion);
00544   }
00545 
00546   template <>
00547   inline void assert_fail_failure<const char *>(const char *file, int line, 
00548                                          const char *func,
00549                                          const char *message, 
00550                                          const char *assertion,
00551                                          bool)
00552   {
00553     throw AssertionFailedError(file, line, func, message, assertion);
00554   }
00555 
00556   template <typename Exception> 
00557   inline void assert_fail_exception(const char *file, int line, const char *func,
00558                              Exception exception, 
00559                              const char *assertion = 0, bool = true)
00560   {
00561     throw exception;
00562   }
00563 
00564   template <> 
00565   inline void assert_fail_exception<const char *>(const char *file, int line, 
00566                                            const char *func,
00567                                            const char *message, 
00568                                            const char *assertion,
00569                                            bool)
00570   {
00571     throw AssertionFailedError(file, line, func, message, assertion);
00572   }
00573 
00575 
00576 }
00577 #endif // LEMON_ERROR_H
00578 
00579 #undef LEMON_ASSERT
00580 #undef LEMON_FIXME
00581 
00582 #ifndef LEMON_ASSERT_ABORT
00583 #  define LEMON_ASSERT_ABORT 1
00584 #endif
00585 
00586 #ifndef LEMON_ASSERT_HANDLER
00587 #  if defined LEMON_ASSERT_EXCEPTION
00588 #    define LEMON_ASSERT_HANDLER ::lemon::assert_fail_exception
00589 #  elif defined LEMON_ASSERT_FAILURE
00590 #    define LEMON_ASSERT_HANDLER ::lemon::assert_fail_failure
00591 #  else
00592 #    define LEMON_ASSERT_HANDLER ::lemon::assert_fail
00593 #  endif
00594 #endif
00595 
00596 #if defined(NDEBUG) || defined(LEMON_DISABLE_ASSERTS)
00597 
00598 #  define LEMON_ASSERT(exp, msg)  (static_cast<void> (0))
00599 
00600 #else
00601 
00623 #  define LEMON_ASSERT(exp, msg)                 \
00624      (static_cast<void> (!!(exp) ? 0 : (         \
00625        LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \
00626                             __PRETTY_FUNCTION__, \
00627                             msg, #exp, LEMON_ASSERT_ABORT), 0)))
00628 
00629 #endif // NDEBUG || LEMON_DISABLE_ASSERTS
00630 
00641 # define LEMON_FIXME(msg) \
00642     (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, __PRETTY_FUNCTION__, \
00643                           "FIXME: " msg))

Generated on Fri Feb 3 18:36:41 2006 for LEMON by  doxygen 1.4.6