lemon/error.h
changeset 290 f6899946c1ac
parent 280 e7f8647ce760
child 291 d901321d6555
equal deleted inserted replaced
4:4deb4d8051f4 5:087d88504383
    33 namespace lemon {
    33 namespace lemon {
    34 
    34 
    35   /// \addtogroup exceptions
    35   /// \addtogroup exceptions
    36   /// @{
    36   /// @{
    37 
    37 
    38   /// \brief Exception safe wrapper class.
    38   /// \brief Generic exception class.
    39   ///
    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) throw() {
       
    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) throw() {
       
    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 throw() {
       
    89       return ptr.get() != 0;
       
    90     }
       
    91 
       
    92   private:
       
    93     std::auto_ptr<_Type> ptr;
       
    94   };
       
    95 
       
    96   /// Exception-safe convenient error message builder 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     mutable std::auto_ptr<std::ostringstream> buf;
       
   106 
       
   107     ///\e
       
   108     bool init() throw() {
       
   109       try {
       
   110         buf.reset(new std::ostringstream);
       
   111       }
       
   112       catch(...) {
       
   113         buf.reset();
       
   114       }
       
   115       return buf.get();
       
   116     }
       
   117 
       
   118   public:
       
   119 
       
   120     ///\e
       
   121     ErrorMessage() throw() { init(); }
       
   122 
       
   123     ErrorMessage(const ErrorMessage& em) throw() : buf(em.buf) { }
       
   124 
       
   125     ///\e
       
   126     ErrorMessage(const char *msg) throw() {
       
   127       init();
       
   128       *this << msg;
       
   129     }
       
   130 
       
   131     ///\e
       
   132     ErrorMessage(const std::string &msg) throw() {
       
   133       init();
       
   134       *this << msg;
       
   135     }
       
   136 
       
   137     ///\e
       
   138     template <typename T>
       
   139     ErrorMessage& operator<<(const T &t) throw() {
       
   140       if( ! buf.get() ) return *this;
       
   141 
       
   142       try {
       
   143         *buf << t;
       
   144       }
       
   145       catch(...) {
       
   146         buf.reset();
       
   147       }
       
   148       return *this;
       
   149     }
       
   150 
       
   151     ///\e
       
   152     const char* message() throw() {
       
   153       if( ! buf.get() ) return 0;
       
   154 
       
   155       const char* mes = 0;
       
   156       try {
       
   157         mes = buf->str().c_str();
       
   158       }
       
   159       catch(...) {}
       
   160       return mes;
       
   161     }
       
   162 
       
   163   };
       
   164 
       
   165   /// Generic exception class.
       
   166 
       
   167   /// Base class for exceptions used in LEMON.
    40   /// Base class for exceptions used in LEMON.
   168   ///
    41   ///
   169   class Exception : public std::exception {
    42   class Exception : public std::exception {
   170   public:
    43   public:
   171     ///\e
    44     ///\e Constructor
   172     Exception() {}
    45     Exception() {}
   173     ///\e
    46     ///\e Virtual destructor
   174     virtual ~Exception() throw() {}
    47     virtual ~Exception() throw() {}
   175     ///\e
    48     ///\e A short description of the exception
   176     virtual const char* what() const throw() {
    49     virtual const char* what() const throw() {
   177       return "lemon::Exception";
    50       return "lemon::Exception";
   178     }
    51     }
   179   };
    52   };
   180 
    53 
   181   /// One of the two main subclasses of \ref Exception.
    54   /// \brief Input-Output error
   182 
    55   ///
   183   /// Logic errors represent problems in the internal logic of a program;
    56   /// This exception is thrown when a file operation cannot be
   184   /// in theory, these are preventable, and even detectable before the
    57   /// succeeded.
   185   /// program runs (e.g. violations of class invariants).
    58   class IoError : public Exception {
   186   ///
    59   protected:
   187   /// A typical example for this is \ref UninitializedParameter.
    60     std::string _message;
   188   class LogicError : public Exception {
    61     std::string _file;
       
    62 
       
    63     mutable std::string _what;
   189   public:
    64   public:
       
    65 
       
    66     /// Copy constructor
       
    67     IoError(const IoError &error) {
       
    68       message(error._message);
       
    69       file(error._file);
       
    70     }
       
    71 
       
    72     /// Constructor
       
    73     explicit IoError(const char *message) {
       
    74       IoError::message(message);
       
    75     }
       
    76 
       
    77     /// Constructor
       
    78     explicit IoError(const std::string &message) {
       
    79       IoError::message(message);
       
    80     }
       
    81 
       
    82     /// Constructor
       
    83     IoError(const std::string &file, const char *message) {
       
    84       IoError::message(message);
       
    85       IoError::file(file);
       
    86     }
       
    87 
       
    88     /// Constructor
       
    89     IoError(const std::string &file, const std::string &message) {
       
    90       IoError::message(message);
       
    91       IoError::file(file);
       
    92     }
       
    93 
       
    94     /// Virtual destructor
       
    95     virtual ~IoError() throw() {}
       
    96 
       
    97     /// Set the error message
       
    98     void message(const char *message) {
       
    99       try {
       
   100         _message = message;
       
   101       } catch (...) {}
       
   102     }
       
   103 
       
   104     /// Set the error message
       
   105     void message(const std::string& message) {
       
   106       try {
       
   107         _message = message;
       
   108       } catch (...) {}
       
   109     }
       
   110 
       
   111     /// Set the file name
       
   112     void file(const std::string &file) {
       
   113       try {
       
   114         _file = file;
       
   115       } catch (...) {}
       
   116     }
       
   117 
       
   118     /// Returns the error message
       
   119     const std::string& message() const {
       
   120       return _message;
       
   121     }
       
   122 
       
   123     /// \brief Returns the filename
       
   124     ///
       
   125     /// Returns the filename or empty string if the filename was not
       
   126     /// specified.
       
   127     const std::string& file() const {
       
   128       return _file;
       
   129     }
       
   130 
       
   131     /// \brief Returns a short error message
       
   132     ///
       
   133     /// Returns a short error message which contains the message, the
       
   134     /// file name and the line number.
   190     virtual const char* what() const throw() {
   135     virtual const char* what() const throw() {
   191       return "lemon::LogicError";
   136       try {
   192     }
   137         _what.clear();
   193   };
   138         std::ostringstream oss;
   194 
   139         oss << "lemon:IoError" << ": ";
   195   /// \ref Exception for uninitialized parameters.
   140         oss << message();
   196 
   141         if (!file().empty()) {
   197   /// This error represents problems in the initialization
   142           oss << " (";
   198   /// of the parameters of the algorithms.
   143           if (!file().empty()) oss << "with file '" << file() << "'";
   199   class UninitializedParameter : public LogicError {
   144           oss << ")";
   200   public:
       
   201     virtual const char* what() const throw() {
       
   202       return "lemon::UninitializedParameter";
       
   203     }
       
   204   };
       
   205 
       
   206 
       
   207   /// One of the two main subclasses of \ref Exception.
       
   208 
       
   209   /// Runtime errors represent problems outside the scope of a program;
       
   210   /// they cannot be easily predicted and can generally only be caught
       
   211   /// as the program executes.
       
   212   class RuntimeError : public Exception {
       
   213   public:
       
   214     virtual const char* what() const throw() {
       
   215       return "lemon::RuntimeError";
       
   216     }
       
   217   };
       
   218 
       
   219   ///\e
       
   220   class RangeError : public RuntimeError {
       
   221   public:
       
   222     virtual const char* what() const throw() {
       
   223       return "lemon::RangeError";
       
   224     }
       
   225   };
       
   226 
       
   227   ///\e
       
   228   class IoError : public RuntimeError {
       
   229   public:
       
   230     virtual const char* what() const throw() {
       
   231       return "lemon::IoError";
       
   232     }
       
   233   };
       
   234 
       
   235   ///\e
       
   236   class DataFormatError : public IoError {
       
   237   protected:
       
   238     ExceptionMember<std::string> _message;
       
   239     ExceptionMember<std::string> _file;
       
   240     int _line;
       
   241 
       
   242     mutable ExceptionMember<std::string> _message_holder;
       
   243   public:
       
   244 
       
   245     DataFormatError(const DataFormatError &dfe) :
       
   246       IoError(dfe), _message(dfe._message), _file(dfe._file),
       
   247       _line(dfe._line) {}
       
   248 
       
   249     ///\e
       
   250     explicit DataFormatError(const char *the_message)
       
   251       : _message(the_message), _line(0) {}
       
   252 
       
   253     ///\e
       
   254     DataFormatError(const std::string &file_name, int line_num,
       
   255                     const char *the_message)
       
   256       : _message(the_message), _line(line_num) { file(file_name); }
       
   257 
       
   258     ///\e
       
   259     void line(int ln) { _line = ln; }
       
   260     ///\e
       
   261     void message(const std::string& msg) { _message.set(msg); }
       
   262     ///\e
       
   263     void file(const std::string &fl) { _file.set(fl); }
       
   264 
       
   265     ///\e
       
   266     int line() const { return _line; }
       
   267     ///\e
       
   268     const char* message() const {
       
   269       if (_message.valid() && !_message.get().empty()) {
       
   270         return _message.get().c_str();
       
   271       } else {
       
   272         return 0;
       
   273       }
       
   274     }
       
   275 
       
   276     /// \brief Returns the filename.
       
   277     ///
       
   278     /// Returns \e null if the filename was not specified.
       
   279     const char* file() const {
       
   280       if (_file.valid() && !_file.get().empty()) {
       
   281         return _file.get().c_str();
       
   282       } else {
       
   283         return 0;
       
   284       }
       
   285     }
       
   286 
       
   287     ///\e
       
   288     virtual const char* what() const throw() {
       
   289       try {
       
   290         std::ostringstream ostr;
       
   291         ostr << "lemon:DataFormatError" << ": ";
       
   292         if (message()) ostr << message();
       
   293         if( file() || line() != 0 ) {
       
   294           ostr << " (";
       
   295           if( file() ) ostr << "in file '" << file() << "'";
       
   296           if( file() && line() != 0 ) ostr << " ";
       
   297           if( line() != 0 ) ostr << "at line " << line();
       
   298           ostr << ")";
       
   299         }
   145         }
   300         _message_holder.set(ostr.str());
   146         _what = oss.str();
   301       }
   147       }
   302       catch (...) {}
   148       catch (...) {}
   303       if( _message_holder.valid()) return _message_holder.get().c_str();
   149       if (!_what.empty()) return _what.c_str();
   304       return "lemon:DataFormatError";
   150       else return "lemon:IoError";
   305     }
   151     }
   306 
   152 
   307     virtual ~DataFormatError() throw() {}
       
   308   };
   153   };
   309 
   154 
   310   ///\e
   155   /// \brief Format error
   311   class FileOpenError : public IoError {
   156   ///
       
   157   /// This class is used to indicate if an input file has wrong
       
   158   /// formatting, or a data representation is not legal.
       
   159   class FormatError : public Exception {
   312   protected:
   160   protected:
   313     ExceptionMember<std::string> _file;
   161     std::string _message;
   314 
   162     std::string _file;
   315     mutable ExceptionMember<std::string> _message_holder;
   163     int _line;
       
   164 
       
   165     mutable std::string _what;
   316   public:
   166   public:
   317 
   167 
   318     FileOpenError(const FileOpenError &foe) :
   168     /// Copy constructor
   319       IoError(foe), _file(foe._file) {}
   169     FormatError(const FormatError &error) {
   320 
   170       message(error._message);
   321     ///\e
   171       file(error._file);
   322     explicit FileOpenError(const std::string& fl)
   172       line(error._line);
   323       : _file(fl) {}
   173     }
   324 
   174 
   325 
   175     /// Constructor
   326     ///\e
   176     explicit FormatError(const char *message) {
   327     void file(const std::string &fl) { _file.set(fl); }
   177       FormatError::message(message);
   328 
   178       _line = 0;
   329     /// \brief Returns the filename.
   179     }
   330     ///
   180 
   331     /// Returns \e null if the filename was not specified.
   181     /// Constructor
   332     const char* file() const {
   182     explicit FormatError(const std::string &message) {
   333       if (_file.valid() && !_file.get().empty()) {
   183       FormatError::message(message);
   334         return _file.get().c_str();
   184       _line = 0;
   335       } else {
   185     }
   336         return 0;
   186 
   337       }
   187     /// Constructor
   338     }
   188     FormatError(const std::string &file, int line, const char *message) {
   339 
   189       FormatError::message(message);
   340     ///\e
   190       FormatError::file(file);
       
   191       FormatError::line(line);
       
   192     }
       
   193 
       
   194     /// Constructor
       
   195     FormatError(const std::string &file, int line, const std::string &message) {
       
   196       FormatError::message(message);
       
   197       FormatError::file(file);
       
   198       FormatError::line(line);
       
   199     }
       
   200 
       
   201     /// Virtual destructor
       
   202     virtual ~FormatError() throw() {}
       
   203 
       
   204     /// Set the line number
       
   205     void line(int line) { _line = line; }
       
   206 
       
   207     /// Set the error message
       
   208     void message(const char *message) {
       
   209       try {
       
   210         _message = message;
       
   211       } catch (...) {}
       
   212     }
       
   213 
       
   214     /// Set the error message
       
   215     void message(const std::string& message) {
       
   216       try {
       
   217         _message = message;
       
   218       } catch (...) {}
       
   219     }
       
   220 
       
   221     /// Set the file name
       
   222     void file(const std::string &file) {
       
   223       try {
       
   224         _file = file;
       
   225       } catch (...) {}
       
   226     }
       
   227 
       
   228     /// \brief Returns the line number
       
   229     ///
       
   230     /// Returns the line number or zero if it was not specified.
       
   231     int line() const { return _line; }
       
   232 
       
   233     /// Returns the error message
       
   234     const std::string& message() const {
       
   235       return _message;
       
   236     }
       
   237 
       
   238     /// \brief Returns the filename
       
   239     ///
       
   240     /// Returns the filename or empty string if the filename was not
       
   241     /// specified.
       
   242     const std::string& file() const {
       
   243       return _file;
       
   244     }
       
   245 
       
   246     /// \brief Returns a short error message
       
   247     ///
       
   248     /// Returns a short error message which contains the message, the
       
   249     /// file name and the line number.
   341     virtual const char* what() const throw() {
   250     virtual const char* what() const throw() {
   342       try {
   251       try {
   343         std::ostringstream ostr;
   252         _what.clear();
   344         ostr << "lemon::FileOpenError" << ": ";
   253         std::ostringstream oss;
   345         ostr << "Cannot open file - " << file();
   254         oss << "lemon:FormatError" << ": ";
   346         _message_holder.set(ostr.str());
   255         oss << message();
       
   256         if (!file().empty() || line() != 0) {
       
   257           oss << " (";
       
   258           if (!file().empty()) oss << "in file '" << file() << "'";
       
   259           if (!file().empty() && line() != 0) oss << " ";
       
   260           if (line() != 0) oss << "at line " << line();
       
   261           oss << ")";
       
   262         }
       
   263         _what = oss.str();
   347       }
   264       }
   348       catch (...) {}
   265       catch (...) {}
   349       if( _message_holder.valid()) return _message_holder.get().c_str();
   266       if (!_what.empty()) return _what.c_str();
   350       return "lemon::FileOpenError";
   267       else return "lemon:FormatError";
   351     }
   268     }
   352     virtual ~FileOpenError() throw() {}
   269 
   353   };
   270   };
   354 
   271 
   355   class IoParameterError : public IoError {
       
   356   protected:
       
   357     ExceptionMember<std::string> _message;
       
   358     ExceptionMember<std::string> _file;
       
   359 
       
   360     mutable ExceptionMember<std::string> _message_holder;
       
   361   public:
       
   362 
       
   363     IoParameterError(const IoParameterError &ile) :
       
   364       IoError(ile), _message(ile._message), _file(ile._file) {}
       
   365 
       
   366     ///\e
       
   367     explicit IoParameterError(const char *the_message)
       
   368       : _message(the_message) {}
       
   369 
       
   370     ///\e
       
   371     IoParameterError(const char *file_name, const char *the_message)
       
   372       : _message(the_message), _file(file_name) {}
       
   373 
       
   374      ///\e
       
   375     void message(const std::string& msg) { _message.set(msg); }
       
   376     ///\e
       
   377     void file(const std::string &fl) { _file.set(fl); }
       
   378 
       
   379      ///\e
       
   380     const char* message() const {
       
   381       if (_message.valid()) {
       
   382         return _message.get().c_str();
       
   383       } else {
       
   384         return 0;
       
   385       }
       
   386     }
       
   387 
       
   388     /// \brief Returns the filename.
       
   389     ///
       
   390     /// Returns \c 0 if the filename was not specified.
       
   391     const char* file() const {
       
   392       if (_file.valid()) {
       
   393         return _file.get().c_str();
       
   394       } else {
       
   395         return 0;
       
   396       }
       
   397     }
       
   398 
       
   399     ///\e
       
   400     virtual const char* what() const throw() {
       
   401       try {
       
   402         std::ostringstream ostr;
       
   403         if (message()) ostr << message();
       
   404         if (file()) ostr << "(when reading file '" << file() << "')";
       
   405         _message_holder.set(ostr.str());
       
   406       }
       
   407       catch (...) {}
       
   408       if( _message_holder.valid() ) return _message_holder.get().c_str();
       
   409       return "lemon:IoParameterError";
       
   410     }
       
   411     virtual ~IoParameterError() throw() {}
       
   412   };
       
   413 
       
   414   /// @}
   272   /// @}
   415 
   273 
   416 }
   274 }
   417 
   275 
   418 #endif // LEMON_ERROR_H
   276 #endif // LEMON_ERROR_H