lemon/error.h
author deba
Wed, 01 Mar 2006 10:25:30 +0000
changeset 1991 d7442141d9ef
parent 1875 98698b69a902
child 2150 cce8ac91c08c
permissions -rw-r--r--
The graph adadptors can be alteration observed.
In most cases it uses the adapted graph alteration notifiers.
Only special case is now the UndirGraphAdaptor, where
we have to proxy the signals from the graph.

The SubBidirGraphAdaptor is removed, because it doest not
gives more feature than the EdgeSubGraphAdaptor<UndirGraphAdaptor<Graph>>.

The ResGraphAdaptor is based on this composition.
     1 /* -*- C++ -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library
     4  *
     5  * Copyright (C) 2003-2006
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     8  *
     9  * Permission to use, modify and distribute this software is granted
    10  * provided that this copyright notice appears in all copies. For
    11  * precise terms see the accompanying LICENSE file.
    12  *
    13  * This software is provided "AS IS" with no warranty of any kind,
    14  * express or implied, and with no claim as to its suitability for any
    15  * purpose.
    16  *
    17  */
    18 
    19 #ifndef LEMON_ERROR_H
    20 #define LEMON_ERROR_H
    21 
    22 //! \ingroup exceptions
    23 //! \file
    24 //! \brief Basic exception classes and error handling.
    25 
    26 #include <exception>
    27 #include <string>
    28 #include <sstream>
    29 #include <iostream>
    30 #include <cstdlib>
    31 #include <memory>
    32 
    33 namespace lemon {
    34 
    35   /// \addtogroup exceptions
    36   /// @{
    37   
    38   /// \brief Exception safe wrapper class.
    39   ///
    40   /// Exception safe wrapper class to implement the members of exceptions.
    41   template <typename _Type>
    42   class ExceptionMember {
    43   public:
    44     typedef _Type Type;
    45 
    46     ExceptionMember() throw () {
    47       try {
    48 	ptr.reset(new Type());
    49       } catch (...) {}
    50     }
    51 
    52     ExceptionMember(const Type& type) throw () {
    53       try {
    54 	ptr.reset(new Type());
    55 	if (ptr.get() == 0) return;
    56 	*ptr = type;
    57       } catch (...) {}
    58     }
    59 
    60     ExceptionMember(const ExceptionMember& copy) throw() {
    61       try {
    62 	if (!copy.valid()) return;
    63 	ptr.reset(new Type());
    64 	if (ptr.get() == 0) return;
    65 	*ptr = copy.get();
    66       } catch (...) {}
    67     }
    68 
    69     ExceptionMember& operator=(const ExceptionMember& copy) {
    70       if (ptr.get() == 0) return;
    71       try {
    72 	if (!copy.valid()) return;
    73  	*ptr = copy.get();
    74       } catch (...) {}
    75     }
    76 
    77     void set(const Type& type) {
    78       if (ptr.get() == 0) return;
    79       try {
    80 	*ptr = type;
    81       } catch (...) {}
    82     }
    83 
    84     const Type& get() const {
    85       return *ptr;
    86     }
    87 
    88     bool valid() const {
    89       return ptr.get() != 0;
    90     }
    91     
    92   private:
    93     std::auto_ptr<_Type> ptr;
    94   };
    95 
    96   /// Exception-safe convenient "error message" class.
    97 
    98   /// Helper class which provides a convenient ostream-like (operator <<
    99   /// based) interface to create a string message. Mostly useful in
   100   /// exception classes (therefore the name).
   101   class ErrorMessage {
   102   protected:
   103     ///\e 
   104 
   105     ///\todo The good solution is boost::shared_ptr...
   106     ///
   107     mutable
   108     std::auto_ptr<std::ostringstream> buf;
   109     
   110     ///\e 
   111     bool init() throw() {
   112       try {
   113 	buf.reset(new std::ostringstream);
   114       }
   115       catch(...) {
   116 	buf.reset();
   117       }
   118       return buf.get();
   119     }
   120 
   121   public:
   122 
   123     ///\e 
   124     ErrorMessage() throw() { init(); }
   125 
   126     ErrorMessage(const ErrorMessage& em) throw() : buf(em.buf) { }
   127 
   128     ///\e 
   129     ErrorMessage(const char *message) throw() {
   130       init();
   131       *this << message;
   132     }
   133 
   134     ///\e 
   135     ErrorMessage(const std::string &message) throw() {
   136       init();
   137       *this << message;
   138     }
   139 
   140     ///\e 
   141     template <typename T>
   142     ErrorMessage& operator<<(const T &t) throw() {
   143       if( ! buf.get() ) return *this;
   144 
   145       try {
   146 	*buf << t;
   147       }
   148       catch(...) {
   149 	buf.reset();
   150       }
   151       return *this;
   152     }
   153 
   154     ///\e 
   155     const char* message() throw() {
   156       if( ! buf.get() ) return 0;
   157 
   158       const char* mes = 0;
   159       try {
   160 	mes = buf->str().c_str();
   161       }
   162       catch(...) {}
   163       return mes;
   164     }
   165     
   166   };
   167 
   168   /**
   169    * \brief Generic exception class.
   170    *
   171    * Base class for exceptions used in LEMON.
   172    */
   173   class Exception : public std::exception {
   174   public:
   175     ///\e 
   176     Exception() {}
   177     ///\e 
   178     virtual ~Exception() throw() {}
   179 
   180     ///\e
   181     virtual const char* exceptionName() const {
   182       return "lemon::Exception";
   183     }
   184     
   185     ///\e 
   186     virtual const char* what() const throw() {
   187       return exceptionName();
   188     }
   189   };
   190 
   191   /**
   192    * \brief One of the two main subclasses of \ref Exception.
   193    *
   194    * Logic errors represent problems in the internal logic of a program;
   195    * in theory, these are preventable, and even detectable before the
   196    * program runs (e.g., violations of class invariants).
   197    *
   198    * A typical example for this is \ref UninitializedParameter.
   199    */
   200   class LogicError : public Exception {
   201   public:
   202     virtual const char* exceptionName() const {
   203       return "lemon::LogicError";
   204     }
   205   };
   206 
   207   /**
   208    * \brief \ref Exception for uninitialized parameters.
   209    *
   210    * This error represents problems in the initialization
   211    * of the parameters of the algorithms.
   212    */
   213   class UninitializedParameter : public LogicError {
   214   public:
   215     virtual const char* exceptionName() const {
   216       return "lemon::UninitializedParameter";
   217     }
   218   };
   219 
   220   
   221   /**
   222    * \brief One of the two main subclasses of \ref Exception.
   223    *
   224    * Runtime errors represent problems outside the scope of a program;
   225    * they cannot be easily predicted and can generally only be caught as
   226    * the program executes.
   227    */
   228   class RuntimeError : public Exception {
   229   public:
   230     virtual const char* exceptionName() const {
   231       return "lemon::RuntimeError";
   232     }
   233   };
   234 
   235   ///\e
   236   class RangeError : public RuntimeError {
   237   public:
   238     virtual const char* exceptionName() const {
   239       return "lemon::RangeError";
   240     }
   241   };
   242 
   243   ///\e 
   244   class IOError : public RuntimeError {
   245   public:
   246     virtual const char* exceptionName() const {
   247       return "lemon::IOError";
   248     }
   249   };
   250 
   251   ///\e 
   252   class DataFormatError : public IOError {
   253   protected:
   254     ExceptionMember<std::string> _message;
   255     ExceptionMember<std::string> _file;
   256     int _line;
   257 
   258     mutable ExceptionMember<std::string> _message_holder;
   259   public:
   260 
   261     DataFormatError(const DataFormatError &dfe) : 
   262       IOError(dfe), _message(dfe._message), _file(dfe._file),
   263       _line(dfe._line) {}
   264 
   265     ///\e 
   266     explicit DataFormatError(const char *the_message)
   267       : _message(the_message), _line(0) {}
   268 
   269     ///\e 
   270     DataFormatError(const std::string &file_name, int line_num,
   271 		    const char *the_message)
   272       : _message(the_message), _line(line_num) { file(file_name); }
   273 
   274     ///\e 
   275     void line(int line) { _line = line; }
   276     ///\e 
   277     void message(const std::string& message) { _message.set(message); }
   278     ///\e 
   279     void file(const std::string &file) { _file.set(file); }
   280  
   281     ///\e
   282     int line() const { return _line; }
   283     ///\e
   284     const char* message() const { 
   285       if (_message.valid() && !_message.get().empty()) {
   286 	return _message.get().c_str();
   287       } else {
   288 	return 0;
   289       }
   290     }
   291 
   292     /// \brief Returns the filename.
   293     ///
   294     /// Returns \e null if the filename was not specified.
   295     const char* file() const {
   296       if (_file.valid() && !_file.get().empty()) {
   297 	return _file.get().c_str();
   298       } else {
   299 	return 0;
   300       }
   301     }
   302 
   303     ///\e 
   304     virtual const char* what() const throw() {
   305       try {
   306 	std::ostringstream ostr;
   307 	ostr << exceptionName() << ": ";
   308 	if (message()) ostr << message();
   309 	if( file() || line() != 0 ) {
   310 	  ostr << " (";
   311 	  if( file() ) ostr << "in file '" << file() << "'";
   312 	  if( file() && line() != 0 ) ostr << " ";
   313 	  if( line() != 0 ) ostr << "at line " << line();
   314 	  ostr << ")";
   315 	}
   316 	_message_holder.set(ostr.str());
   317       }
   318       catch (...) {}
   319       if( _message_holder.valid()) return _message_holder.get().c_str();
   320       return exceptionName();
   321     }
   322 
   323     virtual const char* exceptionName() const {
   324       return "lemon::DataFormatError";
   325     }
   326 
   327     virtual ~DataFormatError() throw() {}
   328   };
   329 
   330   ///\e 
   331   class FileOpenError : public IOError {
   332   protected:
   333     ExceptionMember<std::string> _file;
   334 
   335     mutable ExceptionMember<std::string> _message_holder;
   336   public:
   337 
   338     FileOpenError(const FileOpenError &foe) : 
   339       IOError(foe), _file(foe._file) {}
   340 
   341     ///\e 
   342     explicit FileOpenError(const std::string& file)
   343       : _file(file) {}
   344 
   345 
   346     ///\e 
   347     void file(const std::string &file) { _file.set(file); }
   348  
   349     /// \brief Returns the filename.
   350     ///
   351     /// Returns \e null if the filename was not specified.
   352     const char* file() const {
   353       if (_file.valid() && !_file.get().empty()) {
   354 	return _file.get().c_str();
   355       } else {
   356 	return 0;
   357       }
   358     }
   359 
   360     ///\e 
   361     virtual const char* what() const throw() {
   362       try {
   363 	std::ostringstream ostr;
   364 	ostr << exceptionName() << ": ";
   365 	ostr << "Cannot open file - " << file();
   366 	_message_holder.set(ostr.str());
   367       }
   368       catch (...) {}
   369       if( _message_holder.valid()) return _message_holder.get().c_str();
   370       return exceptionName();
   371     }
   372 
   373     virtual const char* exceptionName() const {
   374       return "lemon::FileOpenError";
   375     }
   376 
   377     virtual ~FileOpenError() throw() {}
   378   };
   379 
   380   class IOParameterError : public IOError {
   381   protected:
   382     ExceptionMember<std::string> _message;
   383     ExceptionMember<std::string> _file;
   384 
   385     mutable ExceptionMember<std::string> _message_holder;
   386   public:
   387 
   388     IOParameterError(const IOParameterError &ile) : 
   389       IOError(ile), _message(ile._message), _file(ile._file) {}
   390 
   391     ///\e 
   392     explicit IOParameterError(const char *the_message)
   393       : _message(the_message) {}
   394 
   395     ///\e 
   396     IOParameterError(const char *file_name, const char *the_message)
   397       : _message(the_message), _file(file_name) {}
   398 
   399      ///\e 
   400     void message(const std::string& message) { _message.set(message); }
   401     ///\e 
   402     void file(const std::string &file) { _file.set(file); }
   403  
   404      ///\e
   405     const char* message() const { 
   406       if (_message.valid()) {
   407 	return _message.get().c_str();
   408       } else {
   409 	return 0;
   410       }
   411     }
   412 
   413     /// \brief Returns the filename.
   414     ///
   415     /// Returns \e null if the filename was not specified.
   416     const char* file() const {
   417       if (_file.valid()) {
   418 	return _file.get().c_str();
   419       } else {
   420 	return 0;
   421       }
   422     }
   423 
   424     ///\e 
   425     virtual const char* what() const throw() {
   426       try {
   427 	std::ostringstream ostr;
   428 	if (message()) ostr << message();
   429 	if (file()) ostr << "(when reading file '" << file() << "')";
   430 	_message_holder.set(ostr.str());
   431       }
   432       catch (...) {}
   433       if( _message_holder.valid() ) return _message_holder.get().c_str();
   434       return exceptionName();
   435     }
   436 
   437     virtual const char* exceptionName() const {
   438       return "lemon::IOParameterError";
   439     }
   440 
   441     virtual ~IOParameterError() throw() {}
   442   };
   443 
   444 
   445   ///\e
   446   class AssertionFailedError : public LogicError {
   447   protected:
   448     const char *assertion;
   449     const char *file;
   450     int line;
   451     const char *function;
   452     const char *message;
   453 
   454     mutable ExceptionMember<std::string> _message_holder;
   455   public:
   456     ///\e
   457     AssertionFailedError(const char *_file, int _line, const char *func,
   458 			 const char *msg, const char *_assertion = 0) :
   459       assertion(_assertion), file(_file), line(_line), function(func),
   460       message(msg) {}
   461 
   462     ///\e
   463     const char* get_assertion() const { return assertion; }
   464     ///\e
   465     const char* get_message() const { return message; }
   466     ///\e
   467     const char* get_file() const { return file; }
   468     ///\e
   469     const char* get_function() const { return function; }
   470     ///\e
   471     int get_line() const { return line; }
   472 
   473 
   474     virtual const char* what() const throw() {
   475       try {
   476 	std::ostringstream ostr;
   477 	ostr << file << ":" << line << ": ";
   478 	if( function )
   479 	  ostr << function << ": ";
   480 	ostr << message;
   481 	if( assertion )
   482 	   ostr << " (assertion '" << assertion << "' failed)";
   483 	_message_holder.set(ostr.str());
   484 	return ostr.str().c_str();
   485       }
   486       catch(...) {}
   487       if( _message_holder.valid() ) return _message_holder.get().c_str();
   488       return exceptionName();
   489     }
   490 
   491     virtual const char* exceptionName() const {
   492       return "lemon::AssertionFailedError";
   493     }
   494 
   495     virtual ~AssertionFailedError() throw() {}
   496   };
   497 
   498 
   499   /****************  Macros  ****************/
   500 
   501 
   502   template <typename Exception>
   503   inline void assert_fail(const char *file, int line, const char *func,
   504 		   Exception exception, const char *assertion = 0,
   505 		   bool do_abort=true)
   506   {
   507     using namespace std;
   508     cerr << file << ":" << line << ": ";
   509     if( func )
   510       cerr << func << ": ";
   511     cerr << exception.what();
   512     if( assertion )
   513       cerr << " (assertion '" << assertion << "' failed)";
   514     cerr << endl;
   515     if(do_abort)
   516       abort();
   517   }
   518 
   519   template <>
   520   inline void assert_fail<const char *>(const char *file, int line, const char *func,
   521 				 const char *message, 
   522 				 const char *assertion,
   523 				 bool do_abort)
   524   {
   525     using namespace std;
   526     cerr << file << ":" << line << ": ";
   527     if( func )
   528       cerr << func << ": ";
   529     cerr << message;
   530     if( assertion )
   531       cerr << " (assertion '" << assertion << "' failed)";
   532     cerr << endl;
   533     if(do_abort)
   534       abort();
   535   }
   536 
   537   template <typename Exception>
   538   inline void assert_fail_failure(const char *file, int line, const char *func,
   539 			   Exception exception, 
   540 			   const char *assertion = 0,
   541 			   bool = true)
   542   {
   543     throw AssertionFailedError(file, line, func, exception.what(), assertion);
   544   }
   545 
   546   template <>
   547   inline void assert_fail_failure<const char *>(const char *file, int line, 
   548 					 const char *func,
   549 					 const char *message, 
   550 					 const char *assertion,
   551 					 bool)
   552   {
   553     throw AssertionFailedError(file, line, func, message, assertion);
   554   }
   555 
   556   template <typename Exception> 
   557   inline void assert_fail_exception(const char *file, int line, const char *func,
   558 			     Exception exception, 
   559 			     const char *assertion = 0, bool = true)
   560   {
   561     throw exception;
   562   }
   563 
   564   template <> 
   565   inline void assert_fail_exception<const char *>(const char *file, int line, 
   566 					   const char *func,
   567 					   const char *message, 
   568 					   const char *assertion,
   569 					   bool)
   570   {
   571     throw AssertionFailedError(file, line, func, message, assertion);
   572   }
   573 
   574 /// @}
   575 
   576 }
   577 #endif // LEMON_ERROR_H
   578 
   579 #undef LEMON_ASSERT
   580 #undef LEMON_FIXME
   581 
   582 #ifndef LEMON_ASSERT_ABORT
   583 #  define LEMON_ASSERT_ABORT 1
   584 #endif
   585 
   586 #ifndef LEMON_ASSERT_HANDLER
   587 #  if defined LEMON_ASSERT_EXCEPTION
   588 #    define LEMON_ASSERT_HANDLER ::lemon::assert_fail_exception
   589 #  elif defined LEMON_ASSERT_FAILURE
   590 #    define LEMON_ASSERT_HANDLER ::lemon::assert_fail_failure
   591 #  else
   592 #    define LEMON_ASSERT_HANDLER ::lemon::assert_fail
   593 #  endif
   594 #endif
   595 
   596 #if defined(NDEBUG) || defined(LEMON_DISABLE_ASSERTS)
   597 
   598 #  define LEMON_ASSERT(exp, msg)  (static_cast<void> (0))
   599 
   600 #else
   601 
   602 /**
   603  * \brief Macro for assertions with customizable message
   604  *
   605  * Macro for assertions with customizable message.
   606  *
   607  * The behaviour can be customized with LEMON_ASSERT_HANDLER,
   608  * LEMON_ASSERT_EXCEPTION and LEMON_ASSERT_ABORT defines. Asserts can be
   609  * disabled by defining either NDEBUG or LEMON_DISABLE_ASSERTS macros.
   610  *
   611  * \todo We should provide some way to reset to the default behaviour,
   612  * shouldn't we?
   613  *
   614  * \todo This whole 'assert' business should be placed in a separate
   615  * include file. The boost assert is not guarded by header sentries
   616  * which may help to change the behaviour of the assertions in 
   617  * the files.
   618  *
   619  * \todo __PRETTY_FUNCTION__ should be replaced by something
   620  * compiler-independent, like BOOST_CURRENT_FUNCTION
   621  */
   622 
   623 #  define LEMON_ASSERT(exp, msg)                 \
   624      (static_cast<void> (!!(exp) ? 0 : (         \
   625        LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \
   626                             __PRETTY_FUNCTION__, \
   627 			    msg, #exp, LEMON_ASSERT_ABORT), 0)))
   628 
   629 #endif // NDEBUG || LEMON_DISABLE_ASSERTS
   630 
   631 /**
   632  * \brief Macro for mark not yet implemented features.
   633  *
   634  * \todo Is this the right place for this? It should be used only in
   635  * modules under development.
   636  *
   637  * \todo __PRETTY_FUNCTION__ should be replaced by something
   638  * compiler-independent, like BOOST_CURRENT_FUNCTION
   639  */
   640 
   641 # define LEMON_FIXME(msg) \
   642     (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, __PRETTY_FUNCTION__, \
   643 			  "FIXME: " msg))