# HG changeset patch # User Balazs Dezso # Date 2008-09-30 20:53:18 # Node ID f6899946c1ac6f8e8a52d278b915afec7ad4568c # Parent bb40b6db0a587e98535e84eb2b9c92f3df972b6a Simplifying exceptions - Using asserts instead of exceptions for unitialized parameters - Only the IO exceptions are used in the lemon - DataFormatError is renamed to FormatError - The IoError is used for file access errors diff --git a/demo/lgf_demo.cc b/demo/lgf_demo.cc --- a/demo/lgf_demo.cc +++ b/demo/lgf_demo.cc @@ -49,7 +49,7 @@ node("source", s). // read 'source' node to s node("target", t). // read 'target' node to t run(); - } catch (DataFormatError& error) { // check if there was any error + } catch (Exception& error) { // check if there was any error std::cerr << "Error: " << error.what() << std::endl; return -1; } diff --git a/lemon/arg_parser.h b/lemon/arg_parser.h --- a/lemon/arg_parser.h +++ b/lemon/arg_parser.h @@ -310,8 +310,9 @@ ///This is the type of the return value of ArgParser::operator[](). ///It automatically converts to \c int, \c double, \c bool or - ///\c std::string if the type of the option matches, otherwise it - ///throws an exception (i.e. it performs runtime type checking). + ///\c std::string if the type of the option matches, which is checked + ///with an \ref LEMON_ASSERT "assertion" (i.e. it performs runtime + ///type checking). class RefType { const ArgParser &_parser; diff --git a/lemon/assert.h b/lemon/assert.h --- a/lemon/assert.h +++ b/lemon/assert.h @@ -108,7 +108,7 @@ /// /// \brief Macro for assertion with customizable message /// -/// Macro for assertion with customizable message. +/// Macro for assertion with customizable message. /// \param exp An expression that must be convertible to \c bool. If it is \c /// false, then an assertion is raised. The concrete behaviour depends on the /// settings of the assertion system. diff --git a/lemon/bfs.h b/lemon/bfs.h --- a/lemon/bfs.h +++ b/lemon/bfs.h @@ -135,16 +135,6 @@ #endif class Bfs { public: - ///\ref Exception for uninitialized parameters. - - ///This error represents problems in the initialization of the - ///parameters of the algorithm. - class UninitializedParameter : public lemon::UninitializedParameter { - public: - virtual const char* what() const throw() { - return "lemon::Bfs::UninitializedParameter"; - } - }; ///The type of the digraph the algorithm runs on. typedef typename TR::Digraph Digraph; @@ -232,7 +222,8 @@ typedef T PredMap; static PredMap *createPredMap(const Digraph &) { - throw UninitializedParameter(); + LEMON_ASSERT(false, "PredMap is not initialized"); + return 0; // ignore warnings } }; ///\brief \ref named-templ-param "Named parameter" for setting @@ -250,7 +241,8 @@ typedef T DistMap; static DistMap *createDistMap(const Digraph &) { - throw UninitializedParameter(); + LEMON_ASSERT(false, "DistMap is not initialized"); + return 0; // ignore warnings } }; ///\brief \ref named-templ-param "Named parameter" for setting @@ -268,7 +260,8 @@ typedef T ReachedMap; static ReachedMap *createReachedMap(const Digraph &) { - throw UninitializedParameter(); + LEMON_ASSERT(false, "ReachedMap is not initialized"); + return 0; // ignore warnings } }; ///\brief \ref named-templ-param "Named parameter" for setting @@ -286,7 +279,8 @@ typedef T ProcessedMap; static ProcessedMap *createProcessedMap(const Digraph &) { - throw UninitializedParameter(); + LEMON_ASSERT(false, "ProcessedMap is not initialized"); + return 0; // ignore warnings } }; ///\brief \ref named-templ-param "Named parameter" for setting @@ -304,6 +298,7 @@ static ProcessedMap *createProcessedMap(const Digraph &g) { return new ProcessedMap(g); + return 0; // ignore warnings } }; ///\brief \ref named-templ-param "Named parameter" for setting @@ -1040,7 +1035,6 @@ ///\return \c true if \c t is reachable form \c s. bool run(Node s, Node t) { - if (s==INVALID || t==INVALID) throw UninitializedParameter(); Bfs alg(*reinterpret_cast(Base::_g)); if (Base::_pred) alg.predMap(*reinterpret_cast(Base::_pred)); @@ -1323,18 +1317,6 @@ class BfsVisit { public: - /// \brief \ref Exception for uninitialized parameters. - /// - /// This error represents problems in the initialization - /// of the parameters of the algorithm. - class UninitializedParameter : public lemon::UninitializedParameter { - public: - virtual const char* what() const throw() - { - return "lemon::BfsVisit::UninitializedParameter"; - } - }; - ///The traits class. typedef _Traits Traits; @@ -1389,7 +1371,8 @@ struct SetReachedMapTraits : public Traits { typedef T ReachedMap; static ReachedMap *createReachedMap(const Digraph &digraph) { - throw UninitializedParameter(); + LEMON_ASSERT(false, "ReachedMap is not initialized"); + return 0; // ignore warnings } }; /// \brief \ref named-templ-param "Named parameter" for setting diff --git a/lemon/concepts/heap.h b/lemon/concepts/heap.h --- a/lemon/concepts/heap.h +++ b/lemon/concepts/heap.h @@ -129,7 +129,6 @@ /// already stored in the heap. /// Otherwise it inserts the given item with the given priority. /// - /// It may throw an \ref UnderflowPriorityException. /// \param i The item. /// \param p The priority. void set(const Item &i, const Prio &p) {} diff --git a/lemon/dfs.h b/lemon/dfs.h --- a/lemon/dfs.h +++ b/lemon/dfs.h @@ -136,16 +136,6 @@ #endif class Dfs { public: - ///\ref Exception for uninitialized parameters. - - ///This error represents problems in the initialization of the - ///parameters of the algorithm. - class UninitializedParameter : public lemon::UninitializedParameter { - public: - virtual const char* what() const throw() { - return "lemon::Dfs::UninitializedParameter"; - } - }; ///The type of the digraph the algorithm runs on. typedef typename TR::Digraph Digraph; @@ -232,7 +222,8 @@ typedef T PredMap; static PredMap *createPredMap(const Digraph &) { - throw UninitializedParameter(); + LEMON_ASSERT(false, "PredMap is not initialized"); + return 0; // ignore warnings } }; ///\brief \ref named-templ-param "Named parameter" for setting @@ -250,7 +241,8 @@ typedef T DistMap; static DistMap *createDistMap(const Digraph &) { - throw UninitializedParameter(); + LEMON_ASSERT(false, "DistMap is not initialized"); + return 0; // ignore warnings } }; ///\brief \ref named-templ-param "Named parameter" for setting @@ -268,7 +260,8 @@ typedef T ReachedMap; static ReachedMap *createReachedMap(const Digraph &) { - throw UninitializedParameter(); + LEMON_ASSERT(false, "ReachedMap is not initialized"); + return 0; // ignore warnings } }; ///\brief \ref named-templ-param "Named parameter" for setting @@ -286,7 +279,8 @@ typedef T ProcessedMap; static ProcessedMap *createProcessedMap(const Digraph &) { - throw UninitializedParameter(); + LEMON_ASSERT(false, "ProcessedMap is not initialized"); + return 0; // ignore warnings } }; ///\brief \ref named-templ-param "Named parameter" for setting @@ -974,7 +968,6 @@ ///\return \c true if \c t is reachable form \c s. bool run(Node s, Node t) { - if (s==INVALID || t==INVALID) throw UninitializedParameter(); Dfs alg(*reinterpret_cast(Base::_g)); if (Base::_pred) alg.predMap(*reinterpret_cast(Base::_pred)); @@ -1270,18 +1263,6 @@ class DfsVisit { public: - /// \brief \ref Exception for uninitialized parameters. - /// - /// This error represents problems in the initialization - /// of the parameters of the algorithm. - class UninitializedParameter : public lemon::UninitializedParameter { - public: - virtual const char* what() const throw() - { - return "lemon::DfsVisit::UninitializedParameter"; - } - }; - ///The traits class. typedef _Traits Traits; @@ -1336,7 +1317,8 @@ struct SetReachedMapTraits : public Traits { typedef T ReachedMap; static ReachedMap *createReachedMap(const Digraph &digraph) { - throw UninitializedParameter(); + LEMON_ASSERT(false, "ReachedMap is not initialized"); + return 0; // ignore warnings } }; /// \brief \ref named-templ-param "Named parameter" for setting diff --git a/lemon/dijkstra.h b/lemon/dijkstra.h --- a/lemon/dijkstra.h +++ b/lemon/dijkstra.h @@ -225,16 +225,6 @@ #endif class Dijkstra { public: - ///\ref Exception for uninitialized parameters. - - ///This error represents problems in the initialization of the - ///parameters of the algorithm. - class UninitializedParameter : public lemon::UninitializedParameter { - public: - virtual const char* what() const throw() { - return "lemon::Dijkstra::UninitializedParameter"; - } - }; ///The type of the digraph the algorithm runs on. typedef typename TR::Digraph Digraph; @@ -332,7 +322,8 @@ typedef T PredMap; static PredMap *createPredMap(const Digraph &) { - throw UninitializedParameter(); + LEMON_ASSERT(false, "PredMap is not initialized"); + return 0; // ignore warnings } }; ///\brief \ref named-templ-param "Named parameter" for setting @@ -351,7 +342,8 @@ typedef T DistMap; static DistMap *createDistMap(const Digraph &) { - throw UninitializedParameter(); + LEMON_ASSERT(false, "DistMap is not initialized"); + return 0; // ignore warnings } }; ///\brief \ref named-templ-param "Named parameter" for setting @@ -370,7 +362,8 @@ typedef T ProcessedMap; static ProcessedMap *createProcessedMap(const Digraph &) { - throw UninitializedParameter(); + LEMON_ASSERT(false, "ProcessedMap is not initialized"); + return 0; // ignore warnings } }; ///\brief \ref named-templ-param "Named parameter" for setting @@ -408,11 +401,13 @@ typedef CR HeapCrossRef; typedef H Heap; static HeapCrossRef *createHeapCrossRef(const Digraph &) { - throw UninitializedParameter(); + LEMON_ASSERT(false, "HeapCrossRef is not initialized"); + return 0; // ignore warnings } static Heap *createHeap(HeapCrossRef &) { - throw UninitializedParameter(); + LEMON_ASSERT(false, "Heap is not initialized"); + return 0; // ignore warnings } }; ///\brief \ref named-templ-param "Named parameter" for setting @@ -1158,7 +1153,6 @@ ///in order to compute the shortest path to each node. void run(Node s) { - if (s==INVALID) throw UninitializedParameter(); Dijkstra dijk(*reinterpret_cast(Base::_g), *reinterpret_cast(Base::_length)); @@ -1180,7 +1174,6 @@ ///\return \c true if \c t is reachable form \c s. bool run(Node s, Node t) { - if (s==INVALID || t==INVALID) throw UninitializedParameter(); Dijkstra dijk(*reinterpret_cast(Base::_g), *reinterpret_cast(Base::_length)); diff --git a/lemon/error.h b/lemon/error.h --- a/lemon/error.h +++ b/lemon/error.h @@ -35,380 +35,238 @@ /// \addtogroup exceptions /// @{ - /// \brief Exception safe wrapper class. + /// \brief Generic exception class. /// - /// Exception safe wrapper class to implement the members of exceptions. - template - class ExceptionMember { - public: - typedef _Type Type; - - ExceptionMember() throw() { - try { - ptr.reset(new Type()); - } catch (...) {} - } - - ExceptionMember(const Type& type) throw() { - try { - ptr.reset(new Type()); - if (ptr.get() == 0) return; - *ptr = type; - } catch (...) {} - } - - ExceptionMember(const ExceptionMember& copy) throw() { - try { - if (!copy.valid()) return; - ptr.reset(new Type()); - if (ptr.get() == 0) return; - *ptr = copy.get(); - } catch (...) {} - } - - ExceptionMember& operator=(const ExceptionMember& copy) throw() { - if (ptr.get() == 0) return; - try { - if (!copy.valid()) return; - *ptr = copy.get(); - } catch (...) {} - } - - void set(const Type& type) throw() { - if (ptr.get() == 0) return; - try { - *ptr = type; - } catch (...) {} - } - - const Type& get() const { - return *ptr; - } - - bool valid() const throw() { - return ptr.get() != 0; - } - - private: - std::auto_ptr<_Type> ptr; - }; - - /// Exception-safe convenient error message builder class. - - /// Helper class which provides a convenient ostream-like (operator << - /// based) interface to create a string message. Mostly useful in - /// exception classes (therefore the name). - class ErrorMessage { - protected: - ///\e - - mutable std::auto_ptr buf; - - ///\e - bool init() throw() { - try { - buf.reset(new std::ostringstream); - } - catch(...) { - buf.reset(); - } - return buf.get(); - } - - public: - - ///\e - ErrorMessage() throw() { init(); } - - ErrorMessage(const ErrorMessage& em) throw() : buf(em.buf) { } - - ///\e - ErrorMessage(const char *msg) throw() { - init(); - *this << msg; - } - - ///\e - ErrorMessage(const std::string &msg) throw() { - init(); - *this << msg; - } - - ///\e - template - ErrorMessage& operator<<(const T &t) throw() { - if( ! buf.get() ) return *this; - - try { - *buf << t; - } - catch(...) { - buf.reset(); - } - return *this; - } - - ///\e - const char* message() throw() { - if( ! buf.get() ) return 0; - - const char* mes = 0; - try { - mes = buf->str().c_str(); - } - catch(...) {} - return mes; - } - - }; - - /// Generic exception class. - /// Base class for exceptions used in LEMON. /// class Exception : public std::exception { public: - ///\e + ///\e Constructor Exception() {} - ///\e + ///\e Virtual destructor virtual ~Exception() throw() {} - ///\e + ///\e A short description of the exception virtual const char* what() const throw() { return "lemon::Exception"; } }; - /// One of the two main subclasses of \ref Exception. + /// \brief Input-Output error + /// + /// This exception is thrown when a file operation cannot be + /// succeeded. + class IoError : public Exception { + protected: + std::string _message; + std::string _file; - /// Logic errors represent problems in the internal logic of a program; - /// in theory, these are preventable, and even detectable before the - /// program runs (e.g. violations of class invariants). - /// - /// A typical example for this is \ref UninitializedParameter. - class LogicError : public Exception { + mutable std::string _what; public: + + /// Copy constructor + IoError(const IoError &error) { + message(error._message); + file(error._file); + } + + /// Constructor + explicit IoError(const char *message) { + IoError::message(message); + } + + /// Constructor + explicit IoError(const std::string &message) { + IoError::message(message); + } + + /// Constructor + IoError(const std::string &file, const char *message) { + IoError::message(message); + IoError::file(file); + } + + /// Constructor + IoError(const std::string &file, const std::string &message) { + IoError::message(message); + IoError::file(file); + } + + /// Virtual destructor + virtual ~IoError() throw() {} + + /// Set the error message + void message(const char *message) { + try { + _message = message; + } catch (...) {} + } + + /// Set the error message + void message(const std::string& message) { + try { + _message = message; + } catch (...) {} + } + + /// Set the file name + void file(const std::string &file) { + try { + _file = file; + } catch (...) {} + } + + /// Returns the error message + const std::string& message() const { + return _message; + } + + /// \brief Returns the filename + /// + /// Returns the filename or empty string if the filename was not + /// specified. + const std::string& file() const { + return _file; + } + + /// \brief Returns a short error message + /// + /// Returns a short error message which contains the message, the + /// file name and the line number. virtual const char* what() const throw() { - return "lemon::LogicError"; + try { + _what.clear(); + std::ostringstream oss; + oss << "lemon:IoError" << ": "; + oss << message(); + if (!file().empty()) { + oss << " ("; + if (!file().empty()) oss << "with file '" << file() << "'"; + oss << ")"; + } + _what = oss.str(); + } + catch (...) {} + if (!_what.empty()) return _what.c_str(); + else return "lemon:IoError"; } + }; - /// \ref Exception for uninitialized parameters. - - /// This error represents problems in the initialization - /// of the parameters of the algorithms. - class UninitializedParameter : public LogicError { - public: - virtual const char* what() const throw() { - return "lemon::UninitializedParameter"; - } - }; - - - /// One of the two main subclasses of \ref Exception. - - /// Runtime errors represent problems outside the scope of a program; - /// they cannot be easily predicted and can generally only be caught - /// as the program executes. - class RuntimeError : public Exception { - public: - virtual const char* what() const throw() { - return "lemon::RuntimeError"; - } - }; - - ///\e - class RangeError : public RuntimeError { - public: - virtual const char* what() const throw() { - return "lemon::RangeError"; - } - }; - - ///\e - class IoError : public RuntimeError { - public: - virtual const char* what() const throw() { - return "lemon::IoError"; - } - }; - - ///\e - class DataFormatError : public IoError { + /// \brief Format error + /// + /// This class is used to indicate if an input file has wrong + /// formatting, or a data representation is not legal. + class FormatError : public Exception { protected: - ExceptionMember _message; - ExceptionMember _file; + std::string _message; + std::string _file; int _line; - mutable ExceptionMember _message_holder; + mutable std::string _what; public: - DataFormatError(const DataFormatError &dfe) : - IoError(dfe), _message(dfe._message), _file(dfe._file), - _line(dfe._line) {} - - ///\e - explicit DataFormatError(const char *the_message) - : _message(the_message), _line(0) {} - - ///\e - DataFormatError(const std::string &file_name, int line_num, - const char *the_message) - : _message(the_message), _line(line_num) { file(file_name); } - - ///\e - void line(int ln) { _line = ln; } - ///\e - void message(const std::string& msg) { _message.set(msg); } - ///\e - void file(const std::string &fl) { _file.set(fl); } - - ///\e - int line() const { return _line; } - ///\e - const char* message() const { - if (_message.valid() && !_message.get().empty()) { - return _message.get().c_str(); - } else { - return 0; - } + /// Copy constructor + FormatError(const FormatError &error) { + message(error._message); + file(error._file); + line(error._line); } - /// \brief Returns the filename. - /// - /// Returns \e null if the filename was not specified. - const char* file() const { - if (_file.valid() && !_file.get().empty()) { - return _file.get().c_str(); - } else { - return 0; - } + /// Constructor + explicit FormatError(const char *message) { + FormatError::message(message); + _line = 0; } - ///\e + /// Constructor + explicit FormatError(const std::string &message) { + FormatError::message(message); + _line = 0; + } + + /// Constructor + FormatError(const std::string &file, int line, const char *message) { + FormatError::message(message); + FormatError::file(file); + FormatError::line(line); + } + + /// Constructor + FormatError(const std::string &file, int line, const std::string &message) { + FormatError::message(message); + FormatError::file(file); + FormatError::line(line); + } + + /// Virtual destructor + virtual ~FormatError() throw() {} + + /// Set the line number + void line(int line) { _line = line; } + + /// Set the error message + void message(const char *message) { + try { + _message = message; + } catch (...) {} + } + + /// Set the error message + void message(const std::string& message) { + try { + _message = message; + } catch (...) {} + } + + /// Set the file name + void file(const std::string &file) { + try { + _file = file; + } catch (...) {} + } + + /// \brief Returns the line number + /// + /// Returns the line number or zero if it was not specified. + int line() const { return _line; } + + /// Returns the error message + const std::string& message() const { + return _message; + } + + /// \brief Returns the filename + /// + /// Returns the filename or empty string if the filename was not + /// specified. + const std::string& file() const { + return _file; + } + + /// \brief Returns a short error message + /// + /// Returns a short error message which contains the message, the + /// file name and the line number. virtual const char* what() const throw() { try { - std::ostringstream ostr; - ostr << "lemon:DataFormatError" << ": "; - if (message()) ostr << message(); - if( file() || line() != 0 ) { - ostr << " ("; - if( file() ) ostr << "in file '" << file() << "'"; - if( file() && line() != 0 ) ostr << " "; - if( line() != 0 ) ostr << "at line " << line(); - ostr << ")"; + _what.clear(); + std::ostringstream oss; + oss << "lemon:FormatError" << ": "; + oss << message(); + if (!file().empty() || line() != 0) { + oss << " ("; + if (!file().empty()) oss << "in file '" << file() << "'"; + if (!file().empty() && line() != 0) oss << " "; + if (line() != 0) oss << "at line " << line(); + oss << ")"; } - _message_holder.set(ostr.str()); + _what = oss.str(); } catch (...) {} - if( _message_holder.valid()) return _message_holder.get().c_str(); - return "lemon:DataFormatError"; + if (!_what.empty()) return _what.c_str(); + else return "lemon:FormatError"; } - virtual ~DataFormatError() throw() {} - }; - - ///\e - class FileOpenError : public IoError { - protected: - ExceptionMember _file; - - mutable ExceptionMember _message_holder; - public: - - FileOpenError(const FileOpenError &foe) : - IoError(foe), _file(foe._file) {} - - ///\e - explicit FileOpenError(const std::string& fl) - : _file(fl) {} - - - ///\e - void file(const std::string &fl) { _file.set(fl); } - - /// \brief Returns the filename. - /// - /// Returns \e null if the filename was not specified. - const char* file() const { - if (_file.valid() && !_file.get().empty()) { - return _file.get().c_str(); - } else { - return 0; - } - } - - ///\e - virtual const char* what() const throw() { - try { - std::ostringstream ostr; - ostr << "lemon::FileOpenError" << ": "; - ostr << "Cannot open file - " << file(); - _message_holder.set(ostr.str()); - } - catch (...) {} - if( _message_holder.valid()) return _message_holder.get().c_str(); - return "lemon::FileOpenError"; - } - virtual ~FileOpenError() throw() {} - }; - - class IoParameterError : public IoError { - protected: - ExceptionMember _message; - ExceptionMember _file; - - mutable ExceptionMember _message_holder; - public: - - IoParameterError(const IoParameterError &ile) : - IoError(ile), _message(ile._message), _file(ile._file) {} - - ///\e - explicit IoParameterError(const char *the_message) - : _message(the_message) {} - - ///\e - IoParameterError(const char *file_name, const char *the_message) - : _message(the_message), _file(file_name) {} - - ///\e - void message(const std::string& msg) { _message.set(msg); } - ///\e - void file(const std::string &fl) { _file.set(fl); } - - ///\e - const char* message() const { - if (_message.valid()) { - return _message.get().c_str(); - } else { - return 0; - } - } - - /// \brief Returns the filename. - /// - /// Returns \c 0 if the filename was not specified. - const char* file() const { - if (_file.valid()) { - return _file.get().c_str(); - } else { - return 0; - } - } - - ///\e - virtual const char* what() const throw() { - try { - std::ostringstream ostr; - if (message()) ostr << message(); - if (file()) ostr << "(when reading file '" << file() << "')"; - _message_holder.set(ostr.str()); - } - catch (...) {} - if( _message_holder.valid() ) return _message_holder.get().c_str(); - return "lemon:IoParameterError"; - } - virtual ~IoParameterError() throw() {} }; /// @} diff --git a/lemon/graph_to_eps.h b/lemon/graph_to_eps.h --- a/lemon/graph_to_eps.h +++ b/lemon/graph_to_eps.h @@ -40,6 +40,7 @@ #include #include #include +#include ///\ingroup eps_io @@ -1166,8 +1167,13 @@ GraphToEps > graphToEps(G &g,const char *file_name) { + std::ostream* os = new std::ofstream(file_name); + if (!(*os)) { + delete os; + throw IoError(file_name, "Cannot write file"); + } return GraphToEps > - (DefaultGraphToEpsTraits(g,*new std::ofstream(file_name),true)); + (DefaultGraphToEpsTraits(g,*os,true)); } ///Generates an EPS file from a graph @@ -1182,8 +1188,13 @@ GraphToEps > graphToEps(G &g,const std::string& file_name) { + std::ostream* os = new std::ofstream(file_name.c_str()); + if (!(*os)) { + delete os; + throw IoError(file_name, "Cannot write file"); + } return GraphToEps > - (DefaultGraphToEpsTraits(g,*new std::ofstream(file_name.c_str()),true)); + (DefaultGraphToEpsTraits(g,*os,true)); } } //END OF NAMESPACE LEMON diff --git a/lemon/lgf_reader.h b/lemon/lgf_reader.h --- a/lemon/lgf_reader.h +++ b/lemon/lgf_reader.h @@ -48,11 +48,13 @@ Value operator()(const std::string& str) { std::istringstream is(str); Value value; - is >> value; + if (!(is >> value)) { + throw FormatError("Cannot read token"); + } char c; if (is >> std::ws >> c) { - throw DataFormatError("Remaining characters in token"); + throw FormatError("Remaining characters in token"); } return value; } @@ -166,7 +168,7 @@ if (it == _map.end()) { std::ostringstream msg; msg << "Item not found: " << str; - throw DataFormatError(msg.str().c_str()); + throw FormatError(msg.str()); } return it->second; } @@ -184,12 +186,12 @@ typename Graph::Arc operator()(const std::string& str) { if (str.empty() || (str[0] != '+' && str[0] != '-')) { - throw DataFormatError("Item must start with '+' or '-'"); + throw FormatError("Item must start with '+' or '-'"); } typename std::map ::const_iterator it = _map.find(str.substr(1)); if (it == _map.end()) { - throw DataFormatError("Item not found"); + throw FormatError("Item not found"); } return _graph.direct(it->second, str[0] == '+'); } @@ -235,7 +237,7 @@ inline char readEscape(std::istream& is) { char c; if (!is.get(c)) - throw DataFormatError("Escape format error"); + throw FormatError("Escape format error"); switch (c) { case '\\': @@ -264,7 +266,7 @@ { int code; if (!is.get(c) || !isHex(c)) - throw DataFormatError("Escape format error"); + throw FormatError("Escape format error"); else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c); else code = code * 16 + valueHex(c); return code; @@ -273,7 +275,7 @@ { int code; if (!isOct(c)) - throw DataFormatError("Escape format error"); + throw FormatError("Escape format error"); else if (code = valueOct(c), !is.get(c) || !isOct(c)) is.putback(c); else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) @@ -300,7 +302,7 @@ os << c; } if (!is) - throw DataFormatError("Quoted format error"); + throw FormatError("Quoted format error"); } else { is.putback(c); while (is.get(c) && !isWhiteSpace(c)) { @@ -460,6 +462,7 @@ std::istream* _is; bool local_is; + std::string _filename; Digraph& _digraph; @@ -509,18 +512,24 @@ /// Construct a directed graph reader, which reads from the given /// file. DigraphReader(const std::string& fn, Digraph& digraph) - : _is(new std::ifstream(fn.c_str())), local_is(true), _digraph(digraph), + : _is(new std::ifstream(fn.c_str())), local_is(true), + _filename(fn), _digraph(digraph), _use_nodes(false), _use_arcs(false), - _skip_nodes(false), _skip_arcs(false) {} + _skip_nodes(false), _skip_arcs(false) { + if (!(*_is)) throw IoError(fn, "Cannot open file"); + } /// \brief Constructor /// /// Construct a directed graph reader, which reads from the given /// file. DigraphReader(const char* fn, Digraph& digraph) - : _is(new std::ifstream(fn)), local_is(true), _digraph(digraph), + : _is(new std::ifstream(fn)), local_is(true), + _filename(fn), _digraph(digraph), _use_nodes(false), _use_arcs(false), - _skip_nodes(false), _skip_arcs(false) {} + _skip_nodes(false), _skip_arcs(false) { + if (!(*_is)) throw IoError(fn, "Cannot open file"); + } /// \brief Destructor ~DigraphReader() { @@ -845,7 +854,7 @@ if (!readLine() || !(line >> c) || c == '@') { if (readSuccess() && line) line.putback(c); if (!_node_maps.empty()) - throw DataFormatError("Cannot find map names"); + throw FormatError("Cannot find map names"); return; } line.putback(c); @@ -859,7 +868,7 @@ if (maps.find(map) != maps.end()) { std::ostringstream msg; msg << "Multiple occurence of node map: " << map; - throw DataFormatError(msg.str().c_str()); + throw FormatError(msg.str()); } maps.insert(std::make_pair(map, index)); ++index; @@ -871,7 +880,7 @@ if (jt == maps.end()) { std::ostringstream msg; msg << "Map not found in file: " << _node_maps[i].first; - throw DataFormatError(msg.str().c_str()); + throw FormatError(msg.str()); } map_index[i] = jt->second; } @@ -895,11 +904,11 @@ if (!_reader_bits::readToken(line, tokens[i])) { std::ostringstream msg; msg << "Column not found (" << i + 1 << ")"; - throw DataFormatError(msg.str().c_str()); + throw FormatError(msg.str()); } } if (line >> std::ws >> c) - throw DataFormatError("Extra character on the end of line"); + throw FormatError("Extra character on the end of line"); Node n; if (!_use_nodes) { @@ -908,13 +917,13 @@ _node_index.insert(std::make_pair(tokens[label_index], n)); } else { if (label_index == -1) - throw DataFormatError("Label map not found in file"); + throw FormatError("Label map not found in file"); typename std::map::iterator it = _node_index.find(tokens[label_index]); if (it == _node_index.end()) { std::ostringstream msg; msg << "Node with label not found: " << tokens[label_index]; - throw DataFormatError(msg.str().c_str()); + throw FormatError(msg.str()); } n = it->second; } @@ -938,7 +947,7 @@ if (!readLine() || !(line >> c) || c == '@') { if (readSuccess() && line) line.putback(c); if (!_arc_maps.empty()) - throw DataFormatError("Cannot find map names"); + throw FormatError("Cannot find map names"); return; } line.putback(c); @@ -952,7 +961,7 @@ if (maps.find(map) != maps.end()) { std::ostringstream msg; msg << "Multiple occurence of arc map: " << map; - throw DataFormatError(msg.str().c_str()); + throw FormatError(msg.str()); } maps.insert(std::make_pair(map, index)); ++index; @@ -964,7 +973,7 @@ if (jt == maps.end()) { std::ostringstream msg; msg << "Map not found in file: " << _arc_maps[i].first; - throw DataFormatError(msg.str().c_str()); + throw FormatError(msg.str()); } map_index[i] = jt->second; } @@ -987,21 +996,21 @@ std::string target_token; if (!_reader_bits::readToken(line, source_token)) - throw DataFormatError("Source not found"); + throw FormatError("Source not found"); if (!_reader_bits::readToken(line, target_token)) - throw DataFormatError("Target not found"); + throw FormatError("Target not found"); std::vector tokens(map_num); for (int i = 0; i < map_num; ++i) { if (!_reader_bits::readToken(line, tokens[i])) { std::ostringstream msg; msg << "Column not found (" << i + 1 << ")"; - throw DataFormatError(msg.str().c_str()); + throw FormatError(msg.str()); } } if (line >> std::ws >> c) - throw DataFormatError("Extra character on the end of line"); + throw FormatError("Extra character on the end of line"); Arc a; if (!_use_arcs) { @@ -1012,7 +1021,7 @@ if (it == _node_index.end()) { std::ostringstream msg; msg << "Item not found: " << source_token; - throw DataFormatError(msg.str().c_str()); + throw FormatError(msg.str()); } Node source = it->second; @@ -1020,7 +1029,7 @@ if (it == _node_index.end()) { std::ostringstream msg; msg << "Item not found: " << target_token; - throw DataFormatError(msg.str().c_str()); + throw FormatError(msg.str()); } Node target = it->second; @@ -1029,13 +1038,13 @@ _arc_index.insert(std::make_pair(tokens[label_index], a)); } else { if (label_index == -1) - throw DataFormatError("Label map not found in file"); + throw FormatError("Label map not found in file"); typename std::map::iterator it = _arc_index.find(tokens[label_index]); if (it == _arc_index.end()) { std::ostringstream msg; msg << "Arc with label not found: " << tokens[label_index]; - throw DataFormatError(msg.str().c_str()); + throw FormatError(msg.str()); } a = it->second; } @@ -1060,18 +1069,18 @@ std::string attr, token; if (!_reader_bits::readToken(line, attr)) - throw DataFormatError("Attribute name not found"); + throw FormatError("Attribute name not found"); if (!_reader_bits::readToken(line, token)) - throw DataFormatError("Attribute value not found"); + throw FormatError("Attribute value not found"); if (line >> c) - throw DataFormatError("Extra character on the end of line"); + throw FormatError("Extra character on the end of line"); { std::set::iterator it = read_attr.find(attr); if (it != read_attr.end()) { std::ostringstream msg; msg << "Multiple occurence of attribute " << attr; - throw DataFormatError(msg.str().c_str()); + throw FormatError(msg.str()); } read_attr.insert(attr); } @@ -1093,7 +1102,7 @@ if (read_attr.find(it->first) == read_attr.end()) { std::ostringstream msg; msg << "Attribute not found in file: " << it->first; - throw DataFormatError(msg.str().c_str()); + throw FormatError(msg.str()); } } } @@ -1109,7 +1118,7 @@ void run() { LEMON_ASSERT(_is != 0, "This reader assigned to an other reader"); if (!*_is) { - throw DataFormatError("Cannot find file"); + throw FormatError("Cannot find file"); } bool nodes_done = _skip_nodes; @@ -1129,7 +1138,7 @@ _reader_bits::readToken(line, caption); if (line >> c) - throw DataFormatError("Extra character on the end of line"); + throw FormatError("Extra character on the end of line"); if (section == "nodes" && !nodes_done) { if (_nodes_caption.empty() || _nodes_caption == caption) { @@ -1151,22 +1160,23 @@ readLine(); skipSection(); } - } catch (DataFormatError& error) { + } catch (FormatError& error) { error.line(line_num); + error.file(_filename); throw; } } if (!nodes_done) { - throw DataFormatError("Section @nodes not found"); + throw FormatError("Section @nodes not found"); } if (!arcs_done) { - throw DataFormatError("Section @arcs not found"); + throw FormatError("Section @arcs not found"); } if (!attributes_done && !_attributes.empty()) { - throw DataFormatError("Section @attributes not found"); + throw FormatError("Section @attributes not found"); } } @@ -1244,6 +1254,7 @@ std::istream* _is; bool local_is; + std::string _filename; Graph& _graph; @@ -1293,18 +1304,24 @@ /// Construct an undirected graph reader, which reads from the given /// file. GraphReader(const std::string& fn, Graph& graph) - : _is(new std::ifstream(fn.c_str())), local_is(true), _graph(graph), + : _is(new std::ifstream(fn.c_str())), local_is(true), + _filename(fn), _graph(graph), _use_nodes(false), _use_edges(false), - _skip_nodes(false), _skip_edges(false) {} + _skip_nodes(false), _skip_edges(false) { + if (!(*_is)) throw IoError(fn, "Cannot open file"); + } /// \brief Constructor /// /// Construct an undirected graph reader, which reads from the given /// file. GraphReader(const char* fn, Graph& graph) - : _is(new std::ifstream(fn)), local_is(true), _graph(graph), + : _is(new std::ifstream(fn)), local_is(true), + _filename(fn), _graph(graph), _use_nodes(false), _use_edges(false), - _skip_nodes(false), _skip_edges(false) {} + _skip_nodes(false), _skip_edges(false) { + if (!(*_is)) throw IoError(fn, "Cannot open file"); + } /// \brief Destructor ~GraphReader() { @@ -1673,7 +1690,7 @@ if (!readLine() || !(line >> c) || c == '@') { if (readSuccess() && line) line.putback(c); if (!_node_maps.empty()) - throw DataFormatError("Cannot find map names"); + throw FormatError("Cannot find map names"); return; } line.putback(c); @@ -1687,7 +1704,7 @@ if (maps.find(map) != maps.end()) { std::ostringstream msg; msg << "Multiple occurence of node map: " << map; - throw DataFormatError(msg.str().c_str()); + throw FormatError(msg.str()); } maps.insert(std::make_pair(map, index)); ++index; @@ -1699,7 +1716,7 @@ if (jt == maps.end()) { std::ostringstream msg; msg << "Map not found in file: " << _node_maps[i].first; - throw DataFormatError(msg.str().c_str()); + throw FormatError(msg.str()); } map_index[i] = jt->second; } @@ -1723,11 +1740,11 @@ if (!_reader_bits::readToken(line, tokens[i])) { std::ostringstream msg; msg << "Column not found (" << i + 1 << ")"; - throw DataFormatError(msg.str().c_str()); + throw FormatError(msg.str()); } } if (line >> std::ws >> c) - throw DataFormatError("Extra character on the end of line"); + throw FormatError("Extra character on the end of line"); Node n; if (!_use_nodes) { @@ -1736,13 +1753,13 @@ _node_index.insert(std::make_pair(tokens[label_index], n)); } else { if (label_index == -1) - throw DataFormatError("Label map not found in file"); + throw FormatError("Label map not found in file"); typename std::map::iterator it = _node_index.find(tokens[label_index]); if (it == _node_index.end()) { std::ostringstream msg; msg << "Node with label not found: " << tokens[label_index]; - throw DataFormatError(msg.str().c_str()); + throw FormatError(msg.str()); } n = it->second; } @@ -1766,7 +1783,7 @@ if (!readLine() || !(line >> c) || c == '@') { if (readSuccess() && line) line.putback(c); if (!_edge_maps.empty()) - throw DataFormatError("Cannot find map names"); + throw FormatError("Cannot find map names"); return; } line.putback(c); @@ -1780,7 +1797,7 @@ if (maps.find(map) != maps.end()) { std::ostringstream msg; msg << "Multiple occurence of edge map: " << map; - throw DataFormatError(msg.str().c_str()); + throw FormatError(msg.str()); } maps.insert(std::make_pair(map, index)); ++index; @@ -1792,7 +1809,7 @@ if (jt == maps.end()) { std::ostringstream msg; msg << "Map not found in file: " << _edge_maps[i].first; - throw DataFormatError(msg.str().c_str()); + throw FormatError(msg.str()); } map_index[i] = jt->second; } @@ -1815,21 +1832,21 @@ std::string target_token; if (!_reader_bits::readToken(line, source_token)) - throw DataFormatError("Node u not found"); + throw FormatError("Node u not found"); if (!_reader_bits::readToken(line, target_token)) - throw DataFormatError("Node v not found"); + throw FormatError("Node v not found"); std::vector tokens(map_num); for (int i = 0; i < map_num; ++i) { if (!_reader_bits::readToken(line, tokens[i])) { std::ostringstream msg; msg << "Column not found (" << i + 1 << ")"; - throw DataFormatError(msg.str().c_str()); + throw FormatError(msg.str()); } } if (line >> std::ws >> c) - throw DataFormatError("Extra character on the end of line"); + throw FormatError("Extra character on the end of line"); Edge e; if (!_use_edges) { @@ -1840,7 +1857,7 @@ if (it == _node_index.end()) { std::ostringstream msg; msg << "Item not found: " << source_token; - throw DataFormatError(msg.str().c_str()); + throw FormatError(msg.str()); } Node source = it->second; @@ -1848,7 +1865,7 @@ if (it == _node_index.end()) { std::ostringstream msg; msg << "Item not found: " << target_token; - throw DataFormatError(msg.str().c_str()); + throw FormatError(msg.str()); } Node target = it->second; @@ -1857,13 +1874,13 @@ _edge_index.insert(std::make_pair(tokens[label_index], e)); } else { if (label_index == -1) - throw DataFormatError("Label map not found in file"); + throw FormatError("Label map not found in file"); typename std::map::iterator it = _edge_index.find(tokens[label_index]); if (it == _edge_index.end()) { std::ostringstream msg; msg << "Edge with label not found: " << tokens[label_index]; - throw DataFormatError(msg.str().c_str()); + throw FormatError(msg.str()); } e = it->second; } @@ -1888,18 +1905,18 @@ std::string attr, token; if (!_reader_bits::readToken(line, attr)) - throw DataFormatError("Attribute name not found"); + throw FormatError("Attribute name not found"); if (!_reader_bits::readToken(line, token)) - throw DataFormatError("Attribute value not found"); + throw FormatError("Attribute value not found"); if (line >> c) - throw DataFormatError("Extra character on the end of line"); + throw FormatError("Extra character on the end of line"); { std::set::iterator it = read_attr.find(attr); if (it != read_attr.end()) { std::ostringstream msg; msg << "Multiple occurence of attribute " << attr; - throw DataFormatError(msg.str().c_str()); + throw FormatError(msg.str()); } read_attr.insert(attr); } @@ -1921,7 +1938,7 @@ if (read_attr.find(it->first) == read_attr.end()) { std::ostringstream msg; msg << "Attribute not found in file: " << it->first; - throw DataFormatError(msg.str().c_str()); + throw FormatError(msg.str()); } } } @@ -1955,7 +1972,7 @@ _reader_bits::readToken(line, caption); if (line >> c) - throw DataFormatError("Extra character on the end of line"); + throw FormatError("Extra character on the end of line"); if (section == "nodes" && !nodes_done) { if (_nodes_caption.empty() || _nodes_caption == caption) { @@ -1977,22 +1994,23 @@ readLine(); skipSection(); } - } catch (DataFormatError& error) { + } catch (FormatError& error) { error.line(line_num); + error.file(_filename); throw; } } if (!nodes_done) { - throw DataFormatError("Section @nodes not found"); + throw FormatError("Section @nodes not found"); } if (!edges_done) { - throw DataFormatError("Section @edges not found"); + throw FormatError("Section @edges not found"); } if (!attributes_done && !_attributes.empty()) { - throw DataFormatError("Section @attributes not found"); + throw FormatError("Section @attributes not found"); } } @@ -2054,6 +2072,7 @@ std::istream* _is; bool local_is; + std::string _filename; typedef std::map Sections; Sections _sections; @@ -2074,13 +2093,19 @@ /// /// Construct a section reader, which reads from the given file. SectionReader(const std::string& fn) - : _is(new std::ifstream(fn.c_str())), local_is(true) {} + : _is(new std::ifstream(fn.c_str())), local_is(true), + _filename(fn) { + if (!(*_is)) throw IoError(fn, "Cannot open file"); + } /// \brief Constructor /// /// Construct a section reader, which reads from the given file. SectionReader(const char* fn) - : _is(new std::ifstream(fn)), local_is(true) {} + : _is(new std::ifstream(fn)), local_is(true), + _filename(fn) { + if (!(*_is)) throw IoError(fn, "Cannot open file"); + } /// \brief Destructor ~SectionReader() { @@ -2236,12 +2261,12 @@ _reader_bits::readToken(line, caption); if (line >> c) - throw DataFormatError("Extra character on the end of line"); + throw FormatError("Extra character on the end of line"); if (extra_sections.find(section) != extra_sections.end()) { std::ostringstream msg; msg << "Multiple occurence of section " << section; - throw DataFormatError(msg.str().c_str()); + throw FormatError(msg.str()); } Sections::iterator it = _sections.find(section); if (it != _sections.end()) { @@ -2250,8 +2275,9 @@ } readLine(); skipSection(); - } catch (DataFormatError& error) { + } catch (FormatError& error) { error.line(line_num); + error.file(_filename); throw; } } @@ -2260,7 +2286,7 @@ if (extra_sections.find(it->first) == extra_sections.end()) { std::ostringstream os; os << "Cannot find section: " << it->first; - throw DataFormatError(os.str().c_str()); + throw FormatError(os.str()); } } } @@ -2360,14 +2386,18 @@ /// Construct an \e LGF contents reader, which reads from the given /// file. LgfContents(const std::string& fn) - : _is(new std::ifstream(fn.c_str())), local_is(true) {} + : _is(new std::ifstream(fn.c_str())), local_is(true) { + if (!(*_is)) throw IoError(fn, "Cannot open file"); + } /// \brief Constructor /// /// Construct an \e LGF contents reader, which reads from the given /// file. LgfContents(const char* fn) - : _is(new std::ifstream(fn)), local_is(true) {} + : _is(new std::ifstream(fn)), local_is(true) { + if (!(*_is)) throw IoError(fn, "Cannot open file"); + } /// \brief Destructor ~LgfContents() { diff --git a/lemon/lgf_writer.h b/lemon/lgf_writer.h --- a/lemon/lgf_writer.h +++ b/lemon/lgf_writer.h @@ -55,7 +55,7 @@ template bool operator<(const T&, const T&) { - throw DataFormatError("Label map is not comparable"); + throw FormatError("Label map is not comparable"); } template @@ -203,7 +203,7 @@ typename std::map::const_iterator it = _map.find(str); if (it == _map.end()) { - throw DataFormatError("Item not found"); + throw FormatError("Item not found"); } return it->second; } @@ -223,7 +223,7 @@ typename std::map ::const_iterator it = _map.find(val); if (it == _map.end()) { - throw DataFormatError("Item not found"); + throw FormatError("Item not found"); } return (_graph.direction(val) ? '+' : '-') + it->second; } @@ -462,7 +462,9 @@ /// output file. DigraphWriter(const std::string& fn, const Digraph& digraph) : _os(new std::ofstream(fn.c_str())), local_os(true), _digraph(digraph), - _skip_nodes(false), _skip_arcs(false) {} + _skip_nodes(false), _skip_arcs(false) { + if (!(*_os)) throw IoError(fn, "Cannot write file"); + } /// \brief Constructor /// @@ -470,7 +472,9 @@ /// output file. DigraphWriter(const char* fn, const Digraph& digraph) : _os(new std::ofstream(fn)), local_os(true), _digraph(digraph), - _skip_nodes(false), _skip_arcs(false) {} + _skip_nodes(false), _skip_arcs(false) { + if (!(*_os)) throw IoError(fn, "Cannot write file"); + } /// \brief Destructor ~DigraphWriter() { @@ -1018,7 +1022,9 @@ /// output file. GraphWriter(const std::string& fn, const Graph& graph) : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph), - _skip_nodes(false), _skip_edges(false) {} + _skip_nodes(false), _skip_edges(false) { + if (!(*_os)) throw IoError(fn, "Cannot write file"); + } /// \brief Constructor /// @@ -1026,7 +1032,9 @@ /// output file. GraphWriter(const char* fn, const Graph& graph) : _os(new std::ofstream(fn)), local_os(true), _graph(graph), - _skip_nodes(false), _skip_edges(false) {} + _skip_nodes(false), _skip_edges(false) { + if (!(*_os)) throw IoError(fn, "Cannot write file"); + } /// \brief Destructor ~GraphWriter() { @@ -1576,13 +1584,17 @@ /// /// Construct a section writer, which writes into the given file. SectionWriter(const std::string& fn) - : _os(new std::ofstream(fn.c_str())), local_os(true) {} + : _os(new std::ofstream(fn.c_str())), local_os(true) { + if (!(*_os)) throw IoError(fn, "Cannot write file"); + } /// \brief Constructor /// /// Construct a section writer, which writes into the given file. SectionWriter(const char* fn) - : _os(new std::ofstream(fn)), local_os(true) {} + : _os(new std::ofstream(fn)), local_os(true) { + if (!(*_os)) throw IoError(fn, "Cannot write file"); + } /// \brief Destructor ~SectionWriter() {