src/lemon/error.h
changeset 1207 8117169c9049
parent 1164 80bb73097736
child 1209 dc9fdf77007f
equal deleted inserted replaced
5:5a7d00cb4438 6:902c2e406ae2
    30 #include <cstdlib>
    30 #include <cstdlib>
    31 #include <memory>
    31 #include <memory>
    32 
    32 
    33 namespace lemon {
    33 namespace lemon {
    34 
    34 
    35 /// \addtogroup exceptions
    35   /// \addtogroup exceptions
    36 /// @{
    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   };
    37 
    95 
    38   /// Exception-safe convenient "error message" class.
    96   /// Exception-safe convenient "error message" class.
    39 
    97 
    40   /// Helper class which provides a convenient ostream-like (operator <<
    98   /// Helper class which provides a convenient ostream-like (operator <<
    41   /// based) interface to create a string message. Mostly useful in
    99   /// based) interface to create a string message. Mostly useful in
    86 	*buf << t;
   144 	*buf << t;
    87       }
   145       }
    88       catch(...) {
   146       catch(...) {
    89 	buf.reset();
   147 	buf.reset();
    90       }
   148       }
       
   149       return *this;
    91     }
   150     }
    92 
   151 
    93     ///\e 
   152     ///\e 
    94     const char* message() throw() {
   153     const char* message() throw() {
    95       if( ! buf.get() ) return 0;
   154       if( ! buf.get() ) return 0;
   188   };
   247   };
   189 
   248 
   190   ///\e 
   249   ///\e 
   191   class DataFormatError : public IOError {
   250   class DataFormatError : public IOError {
   192   protected:
   251   protected:
   193     const char *_message;
   252     ExceptionMember<std::string> _message;
       
   253     ExceptionMember<std::string> _file;
   194     int _line;
   254     int _line;
   195 
   255 
   196     ///\todo Much better solution is boost::shared_ptr
   256     mutable ExceptionMember<std::string> _message_holder;
   197     mutable
       
   198     std::auto_ptr<std::string> _file;
       
   199 
       
   200   public:
   257   public:
   201 
   258 
   202     DataFormatError(const DataFormatError &dfe) : 
   259     DataFormatError(const DataFormatError &dfe) : 
   203       IOError(dfe), _message(dfe._message), _line(dfe._line),
   260       IOError(dfe), _message(dfe._message), _file(dfe._file),
   204       _file(dfe._file) {}
   261       _line(dfe._line) {}
   205 
   262 
   206     ///\e 
   263     ///\e 
   207     explicit DataFormatError(const char *the_message)
   264     explicit DataFormatError(const char *the_message)
   208       : _message(the_message), _line(0) {}
   265       : _message(the_message), _line(0) {}
       
   266 
   209     ///\e 
   267     ///\e 
   210     DataFormatError(const std::string &file_name, int line_num,
   268     DataFormatError(const std::string &file_name, int line_num,
   211 		    const char *the_message)
   269 		    const char *the_message)
   212       : _message(the_message), _line(line_num) { file(file_name); }
   270       : _message(the_message), _line(line_num) { file(file_name); }
   213 
   271 
   214     ///\e 
   272     ///\e 
   215     void line(int line_num) { _line=line_num; }
   273     void line(int line) { _line = line; }
   216     ///\e 
   274     ///\e 
   217     void message(char *the_message) { _message=the_message; }
   275     void message(const std::string& message) { _message.set(message); }
   218     ///\e 
   276     ///\e 
   219     void file(const std::string &file_name) {
   277     void file(const std::string &file) { _file.set(file); }
   220       try {
   278  
   221 	_file.reset(new std::string);
       
   222 	*_file = file_name;
       
   223       }
       
   224       catch(...) {
       
   225 	_file.reset();
       
   226       }
       
   227     }
       
   228 
       
   229     ///\e
   279     ///\e
   230     int line() const { return _line; }
   280     int line() const { return _line; }
   231     ///\e
   281     ///\e
   232     const char* message() const { return _message; }
   282     const char* message() const { 
       
   283       if (_message.valid() && !_message.get().empty()) {
       
   284 	return _message.get().c_str();
       
   285       } else {
       
   286 	return 0;
       
   287       }
       
   288     }
   233 
   289 
   234     /// \brief Returns the filename.
   290     /// \brief Returns the filename.
   235     ///
   291     ///
   236     /// Returns \e "(unknown)" if the filename was not specified.
   292     /// Returns \e null if the filename was not specified.
   237     const char* file() const {
   293     const char* file() const {
   238       if( _file.get() )
   294       if (_file.valid() && !_file.get().empty()) {
   239 	return _file->c_str();
   295 	return _file.get().c_str();
   240       else
   296       } else {
   241 	return "(unknown)";
   297 	return 0;
       
   298       }
   242     }
   299     }
   243 
   300 
   244     ///\e 
   301     ///\e 
   245     virtual const char* what() const throw() {
   302     virtual const char* what() const throw() {
   246       const char *mes = 0;
       
   247       try {
   303       try {
   248 	std::ostringstream ostr;
   304 	std::ostringstream ostr;
   249 	ostr << _message;
   305 	if (message()) ostr << message();
   250 	if( _file.get() || _line ) {
   306 	if( file() || line() != 0 ) {
   251 	  ostr << " (";
   307 	  ostr << " (";
   252 	  if( _file.get() ) ostr << "in file '" << *_file << "'";
   308 	  if( file() ) ostr << "in file '" << file() << "'";
   253 	  if( _file.get() && _line ) ostr << " ";
   309 	  if( file() && line() != 0 ) ostr << " ";
   254 	  if( _line ) ostr << "at line " << _line;
   310 	  if( line() != 0 ) ostr << "at line " << line();
   255 	  ostr << ")";
   311 	  ostr << ")";
   256 	}
   312 	}
   257 	mes = ostr.str().c_str();
   313 	_message_holder.set(ostr.str());
   258       }
   314       }
   259       catch(...) {}
   315       catch (...) {}
   260       if( mes ) return mes;
   316       if( _message_holder.valid()) return _message_holder.get().c_str();
   261       return exceptionName();
   317       return exceptionName();
   262     }
   318     }
   263 
   319 
   264     virtual const char* exceptionName() const {
   320     virtual const char* exceptionName() const {
   265       return "lemon::DataFormatError";
   321       return "lemon::DataFormatError";
   266     }
   322     }
   267 
   323 
   268     virtual ~DataFormatError() throw() {}
   324     virtual ~DataFormatError() throw() {}
       
   325   };
       
   326 
       
   327   class IOLogicError : public IOError, public LogicError {
       
   328   protected:
       
   329     ExceptionMember<std::string> _message;
       
   330     ExceptionMember<std::string> _file;
       
   331     int _line;
       
   332 
       
   333     mutable ExceptionMember<std::string> _message_holder;
       
   334   public:
       
   335 
       
   336     IOLogicError(const IOLogicError &ile) : 
       
   337       IOError(ile), LogicError(ile), 
       
   338       _message(ile._message), _file(ile._file) {}
       
   339 
       
   340     ///\e 
       
   341     explicit IOLogicError(const char *the_message)
       
   342       : _message(the_message), _line(0) {}
       
   343 
       
   344     ///\e 
       
   345     IOLogicError(const char *file_name, const char *the_message)
       
   346       : _message(file_name), _file(file_name) {}
       
   347 
       
   348      ///\e 
       
   349     void message(const std::string& message) { _message.set(message); }
       
   350     ///\e 
       
   351     void file(const std::string &file) { _file.set(file); }
       
   352  
       
   353      ///\e
       
   354     const char* message() const { 
       
   355       if (_message.valid()) {
       
   356 	return _message.get().c_str();
       
   357       } else {
       
   358 	return 0;
       
   359       }
       
   360     }
       
   361 
       
   362     /// \brief Returns the filename.
       
   363     ///
       
   364     /// Returns \e null if the filename was not specified.
       
   365     const char* file() const {
       
   366       if (_file.valid()) {
       
   367 	return _file.get().c_str();
       
   368       } else {
       
   369 	return 0;
       
   370       }
       
   371     }
       
   372 
       
   373     ///\e 
       
   374     virtual const char* what() const throw() {
       
   375       try {
       
   376 	std::ostringstream ostr;
       
   377 	if (message()) ostr << message();
       
   378 	if (file()) ostr << "(when reading file '" << file() << "')";
       
   379 	_message_holder.set(ostr.str());
       
   380       }
       
   381       catch (...) {}
       
   382       if( _message_holder.valid() ) return _message_holder.get().c_str();
       
   383       return exceptionName();
       
   384     }
       
   385 
       
   386     virtual const char* exceptionName() const {
       
   387       return "lemon::IOLogicError";
       
   388     }
       
   389 
       
   390     virtual ~IOLogicError() throw() {}
   269   };
   391   };
   270 
   392 
   271 
   393 
   272   ///\e
   394   ///\e
   273   class AssertionFailedError : public LogicError {
   395   class AssertionFailedError : public LogicError {
   305 	  ostr << function << ": ";
   427 	  ostr << function << ": ";
   306 	ostr << message;
   428 	ostr << message;
   307 	if( assertion )
   429 	if( assertion )
   308 	  ostr << " (assertion '" << assertion << "' failed)";
   430 	  ostr << " (assertion '" << assertion << "' failed)";
   309 	mes = ostr.str().c_str();
   431 	mes = ostr.str().c_str();
       
   432 	/// \bug Szerintem a 'mes'-re nem szabad hivatkozni, mert
       
   433 	/// az elobb felszabadul. 
   310       }
   434       }
   311       catch(...) {}
   435       catch(...) {}
   312       if( mes ) return mes;
   436       if( mes ) return mes;
   313       return exceptionName();
   437       return exceptionName();
   314     }
   438     }