Simplifying exceptions
authorBalazs Dezso <deba@inf.elte.hu>
Tue, 30 Sep 2008 20:53:18 +0200
changeset 290f6899946c1ac
parent 287 bb40b6db0a58
child 291 d901321d6555
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
demo/lgf_demo.cc
lemon/arg_parser.h
lemon/assert.h
lemon/bfs.h
lemon/concepts/heap.h
lemon/dfs.h
lemon/dijkstra.h
lemon/error.h
lemon/graph_to_eps.h
lemon/lgf_reader.h
lemon/lgf_writer.h
     1.1 --- a/demo/lgf_demo.cc	Sat Sep 27 14:33:28 2008 +0200
     1.2 +++ b/demo/lgf_demo.cc	Tue Sep 30 20:53:18 2008 +0200
     1.3 @@ -49,7 +49,7 @@
     1.4        node("source", s).             // read 'source' node to s
     1.5        node("target", t).             // read 'target' node to t
     1.6        run();
     1.7 -  } catch (DataFormatError& error) { // check if there was any error
     1.8 +  } catch (Exception& error) { // check if there was any error
     1.9      std::cerr << "Error: " << error.what() << std::endl;
    1.10      return -1;
    1.11    }
     2.1 --- a/lemon/arg_parser.h	Sat Sep 27 14:33:28 2008 +0200
     2.2 +++ b/lemon/arg_parser.h	Tue Sep 30 20:53:18 2008 +0200
     2.3 @@ -310,8 +310,9 @@
     2.4  
     2.5      ///This is the type of the return value of ArgParser::operator[]().
     2.6      ///It automatically converts to \c int, \c double, \c bool or
     2.7 -    ///\c std::string if the type of the option matches, otherwise it
     2.8 -    ///throws an exception (i.e. it performs runtime type checking).
     2.9 +    ///\c std::string if the type of the option matches, which is checked
    2.10 +    ///with an \ref LEMON_ASSERT "assertion" (i.e. it performs runtime
    2.11 +    ///type checking).
    2.12      class RefType
    2.13      {
    2.14        const ArgParser &_parser;
     3.1 --- a/lemon/assert.h	Sat Sep 27 14:33:28 2008 +0200
     3.2 +++ b/lemon/assert.h	Tue Sep 30 20:53:18 2008 +0200
     3.3 @@ -108,7 +108,7 @@
     3.4  ///
     3.5  /// \brief Macro for assertion with customizable message
     3.6  ///
     3.7 -/// Macro for assertion with customizable message.  
     3.8 +/// Macro for assertion with customizable message.
     3.9  /// \param exp An expression that must be convertible to \c bool.  If it is \c
    3.10  /// false, then an assertion is raised. The concrete behaviour depends on the
    3.11  /// settings of the assertion system.
     4.1 --- a/lemon/bfs.h	Sat Sep 27 14:33:28 2008 +0200
     4.2 +++ b/lemon/bfs.h	Tue Sep 30 20:53:18 2008 +0200
     4.3 @@ -135,16 +135,6 @@
     4.4  #endif
     4.5    class Bfs {
     4.6    public:
     4.7 -    ///\ref Exception for uninitialized parameters.
     4.8 -
     4.9 -    ///This error represents problems in the initialization of the
    4.10 -    ///parameters of the algorithm.
    4.11 -    class UninitializedParameter : public lemon::UninitializedParameter {
    4.12 -    public:
    4.13 -      virtual const char* what() const throw() {
    4.14 -        return "lemon::Bfs::UninitializedParameter";
    4.15 -      }
    4.16 -    };
    4.17  
    4.18      ///The type of the digraph the algorithm runs on.
    4.19      typedef typename TR::Digraph Digraph;
    4.20 @@ -232,7 +222,8 @@
    4.21        typedef T PredMap;
    4.22        static PredMap *createPredMap(const Digraph &)
    4.23        {
    4.24 -        throw UninitializedParameter();
    4.25 +        LEMON_ASSERT(false, "PredMap is not initialized");
    4.26 +        return 0; // ignore warnings
    4.27        }
    4.28      };
    4.29      ///\brief \ref named-templ-param "Named parameter" for setting
    4.30 @@ -250,7 +241,8 @@
    4.31        typedef T DistMap;
    4.32        static DistMap *createDistMap(const Digraph &)
    4.33        {
    4.34 -        throw UninitializedParameter();
    4.35 +        LEMON_ASSERT(false, "DistMap is not initialized");
    4.36 +        return 0; // ignore warnings
    4.37        }
    4.38      };
    4.39      ///\brief \ref named-templ-param "Named parameter" for setting
    4.40 @@ -268,7 +260,8 @@
    4.41        typedef T ReachedMap;
    4.42        static ReachedMap *createReachedMap(const Digraph &)
    4.43        {
    4.44 -        throw UninitializedParameter();
    4.45 +        LEMON_ASSERT(false, "ReachedMap is not initialized");
    4.46 +        return 0; // ignore warnings
    4.47        }
    4.48      };
    4.49      ///\brief \ref named-templ-param "Named parameter" for setting
    4.50 @@ -286,7 +279,8 @@
    4.51        typedef T ProcessedMap;
    4.52        static ProcessedMap *createProcessedMap(const Digraph &)
    4.53        {
    4.54 -        throw UninitializedParameter();
    4.55 +        LEMON_ASSERT(false, "ProcessedMap is not initialized");
    4.56 +        return 0; // ignore warnings
    4.57        }
    4.58      };
    4.59      ///\brief \ref named-templ-param "Named parameter" for setting
    4.60 @@ -304,6 +298,7 @@
    4.61        static ProcessedMap *createProcessedMap(const Digraph &g)
    4.62        {
    4.63          return new ProcessedMap(g);
    4.64 +        return 0; // ignore warnings
    4.65        }
    4.66      };
    4.67      ///\brief \ref named-templ-param "Named parameter" for setting
    4.68 @@ -1040,7 +1035,6 @@
    4.69      ///\return \c true if \c t is reachable form \c s.
    4.70      bool run(Node s, Node t)
    4.71      {
    4.72 -      if (s==INVALID || t==INVALID) throw UninitializedParameter();
    4.73        Bfs<Digraph,TR> alg(*reinterpret_cast<const Digraph*>(Base::_g));
    4.74        if (Base::_pred)
    4.75          alg.predMap(*reinterpret_cast<PredMap*>(Base::_pred));
    4.76 @@ -1323,18 +1317,6 @@
    4.77    class BfsVisit {
    4.78    public:
    4.79  
    4.80 -    /// \brief \ref Exception for uninitialized parameters.
    4.81 -    ///
    4.82 -    /// This error represents problems in the initialization
    4.83 -    /// of the parameters of the algorithm.
    4.84 -    class UninitializedParameter : public lemon::UninitializedParameter {
    4.85 -    public:
    4.86 -      virtual const char* what() const throw()
    4.87 -      {
    4.88 -        return "lemon::BfsVisit::UninitializedParameter";
    4.89 -      }
    4.90 -    };
    4.91 -
    4.92      ///The traits class.
    4.93      typedef _Traits Traits;
    4.94  
    4.95 @@ -1389,7 +1371,8 @@
    4.96      struct SetReachedMapTraits : public Traits {
    4.97        typedef T ReachedMap;
    4.98        static ReachedMap *createReachedMap(const Digraph &digraph) {
    4.99 -        throw UninitializedParameter();
   4.100 +        LEMON_ASSERT(false, "ReachedMap is not initialized");
   4.101 +        return 0; // ignore warnings
   4.102        }
   4.103      };
   4.104      /// \brief \ref named-templ-param "Named parameter" for setting
     5.1 --- a/lemon/concepts/heap.h	Sat Sep 27 14:33:28 2008 +0200
     5.2 +++ b/lemon/concepts/heap.h	Tue Sep 30 20:53:18 2008 +0200
     5.3 @@ -129,7 +129,6 @@
     5.4        /// already stored in the heap.
     5.5        /// Otherwise it inserts the given item with the given priority.
     5.6        ///
     5.7 -      /// It may throw an \ref UnderflowPriorityException.
     5.8        /// \param i The item.
     5.9        /// \param p The priority.
    5.10        void set(const Item &i, const Prio &p) {}
     6.1 --- a/lemon/dfs.h	Sat Sep 27 14:33:28 2008 +0200
     6.2 +++ b/lemon/dfs.h	Tue Sep 30 20:53:18 2008 +0200
     6.3 @@ -136,16 +136,6 @@
     6.4  #endif
     6.5    class Dfs {
     6.6    public:
     6.7 -    ///\ref Exception for uninitialized parameters.
     6.8 -
     6.9 -    ///This error represents problems in the initialization of the
    6.10 -    ///parameters of the algorithm.
    6.11 -    class UninitializedParameter : public lemon::UninitializedParameter {
    6.12 -    public:
    6.13 -      virtual const char* what() const throw() {
    6.14 -        return "lemon::Dfs::UninitializedParameter";
    6.15 -      }
    6.16 -    };
    6.17  
    6.18      ///The type of the digraph the algorithm runs on.
    6.19      typedef typename TR::Digraph Digraph;
    6.20 @@ -232,7 +222,8 @@
    6.21        typedef T PredMap;
    6.22        static PredMap *createPredMap(const Digraph &)
    6.23        {
    6.24 -        throw UninitializedParameter();
    6.25 +        LEMON_ASSERT(false, "PredMap is not initialized");
    6.26 +        return 0; // ignore warnings
    6.27        }
    6.28      };
    6.29      ///\brief \ref named-templ-param "Named parameter" for setting
    6.30 @@ -250,7 +241,8 @@
    6.31        typedef T DistMap;
    6.32        static DistMap *createDistMap(const Digraph &)
    6.33        {
    6.34 -        throw UninitializedParameter();
    6.35 +        LEMON_ASSERT(false, "DistMap is not initialized");
    6.36 +        return 0; // ignore warnings
    6.37        }
    6.38      };
    6.39      ///\brief \ref named-templ-param "Named parameter" for setting
    6.40 @@ -268,7 +260,8 @@
    6.41        typedef T ReachedMap;
    6.42        static ReachedMap *createReachedMap(const Digraph &)
    6.43        {
    6.44 -        throw UninitializedParameter();
    6.45 +        LEMON_ASSERT(false, "ReachedMap is not initialized");
    6.46 +        return 0; // ignore warnings
    6.47        }
    6.48      };
    6.49      ///\brief \ref named-templ-param "Named parameter" for setting
    6.50 @@ -286,7 +279,8 @@
    6.51        typedef T ProcessedMap;
    6.52        static ProcessedMap *createProcessedMap(const Digraph &)
    6.53        {
    6.54 -        throw UninitializedParameter();
    6.55 +        LEMON_ASSERT(false, "ProcessedMap is not initialized");
    6.56 +        return 0; // ignore warnings
    6.57        }
    6.58      };
    6.59      ///\brief \ref named-templ-param "Named parameter" for setting
    6.60 @@ -974,7 +968,6 @@
    6.61      ///\return \c true if \c t is reachable form \c s.
    6.62      bool run(Node s, Node t)
    6.63      {
    6.64 -      if (s==INVALID || t==INVALID) throw UninitializedParameter();
    6.65        Dfs<Digraph,TR> alg(*reinterpret_cast<const Digraph*>(Base::_g));
    6.66        if (Base::_pred)
    6.67          alg.predMap(*reinterpret_cast<PredMap*>(Base::_pred));
    6.68 @@ -1270,18 +1263,6 @@
    6.69    class DfsVisit {
    6.70    public:
    6.71  
    6.72 -    /// \brief \ref Exception for uninitialized parameters.
    6.73 -    ///
    6.74 -    /// This error represents problems in the initialization
    6.75 -    /// of the parameters of the algorithm.
    6.76 -    class UninitializedParameter : public lemon::UninitializedParameter {
    6.77 -    public:
    6.78 -      virtual const char* what() const throw()
    6.79 -      {
    6.80 -        return "lemon::DfsVisit::UninitializedParameter";
    6.81 -      }
    6.82 -    };
    6.83 -
    6.84      ///The traits class.
    6.85      typedef _Traits Traits;
    6.86  
    6.87 @@ -1336,7 +1317,8 @@
    6.88      struct SetReachedMapTraits : public Traits {
    6.89        typedef T ReachedMap;
    6.90        static ReachedMap *createReachedMap(const Digraph &digraph) {
    6.91 -        throw UninitializedParameter();
    6.92 +        LEMON_ASSERT(false, "ReachedMap is not initialized");
    6.93 +        return 0; // ignore warnings
    6.94        }
    6.95      };
    6.96      /// \brief \ref named-templ-param "Named parameter" for setting
     7.1 --- a/lemon/dijkstra.h	Sat Sep 27 14:33:28 2008 +0200
     7.2 +++ b/lemon/dijkstra.h	Tue Sep 30 20:53:18 2008 +0200
     7.3 @@ -225,16 +225,6 @@
     7.4  #endif
     7.5    class Dijkstra {
     7.6    public:
     7.7 -    ///\ref Exception for uninitialized parameters.
     7.8 -
     7.9 -    ///This error represents problems in the initialization of the
    7.10 -    ///parameters of the algorithm.
    7.11 -    class UninitializedParameter : public lemon::UninitializedParameter {
    7.12 -    public:
    7.13 -      virtual const char* what() const throw() {
    7.14 -        return "lemon::Dijkstra::UninitializedParameter";
    7.15 -      }
    7.16 -    };
    7.17  
    7.18      ///The type of the digraph the algorithm runs on.
    7.19      typedef typename TR::Digraph Digraph;
    7.20 @@ -332,7 +322,8 @@
    7.21        typedef T PredMap;
    7.22        static PredMap *createPredMap(const Digraph &)
    7.23        {
    7.24 -        throw UninitializedParameter();
    7.25 +        LEMON_ASSERT(false, "PredMap is not initialized");
    7.26 +        return 0; // ignore warnings
    7.27        }
    7.28      };
    7.29      ///\brief \ref named-templ-param "Named parameter" for setting
    7.30 @@ -351,7 +342,8 @@
    7.31        typedef T DistMap;
    7.32        static DistMap *createDistMap(const Digraph &)
    7.33        {
    7.34 -        throw UninitializedParameter();
    7.35 +        LEMON_ASSERT(false, "DistMap is not initialized");
    7.36 +        return 0; // ignore warnings
    7.37        }
    7.38      };
    7.39      ///\brief \ref named-templ-param "Named parameter" for setting
    7.40 @@ -370,7 +362,8 @@
    7.41        typedef T ProcessedMap;
    7.42        static ProcessedMap *createProcessedMap(const Digraph &)
    7.43        {
    7.44 -        throw UninitializedParameter();
    7.45 +        LEMON_ASSERT(false, "ProcessedMap is not initialized");
    7.46 +        return 0; // ignore warnings
    7.47        }
    7.48      };
    7.49      ///\brief \ref named-templ-param "Named parameter" for setting
    7.50 @@ -408,11 +401,13 @@
    7.51        typedef CR HeapCrossRef;
    7.52        typedef H Heap;
    7.53        static HeapCrossRef *createHeapCrossRef(const Digraph &) {
    7.54 -        throw UninitializedParameter();
    7.55 +        LEMON_ASSERT(false, "HeapCrossRef is not initialized");
    7.56 +        return 0; // ignore warnings
    7.57        }
    7.58        static Heap *createHeap(HeapCrossRef &)
    7.59        {
    7.60 -        throw UninitializedParameter();
    7.61 +        LEMON_ASSERT(false, "Heap is not initialized");
    7.62 +        return 0; // ignore warnings
    7.63        }
    7.64      };
    7.65      ///\brief \ref named-templ-param "Named parameter" for setting
    7.66 @@ -1158,7 +1153,6 @@
    7.67      ///in order to compute the shortest path to each node.
    7.68      void run(Node s)
    7.69      {
    7.70 -      if (s==INVALID) throw UninitializedParameter();
    7.71        Dijkstra<Digraph,LengthMap,TR>
    7.72          dijk(*reinterpret_cast<const Digraph*>(Base::_g),
    7.73               *reinterpret_cast<const LengthMap*>(Base::_length));
    7.74 @@ -1180,7 +1174,6 @@
    7.75      ///\return \c true if \c t is reachable form \c s.
    7.76      bool run(Node s, Node t)
    7.77      {
    7.78 -      if (s==INVALID || t==INVALID) throw UninitializedParameter();
    7.79        Dijkstra<Digraph,LengthMap,TR>
    7.80          dijk(*reinterpret_cast<const Digraph*>(Base::_g),
    7.81               *reinterpret_cast<const LengthMap*>(Base::_length));
     8.1 --- a/lemon/error.h	Sat Sep 27 14:33:28 2008 +0200
     8.2 +++ b/lemon/error.h	Tue Sep 30 20:53:18 2008 +0200
     8.3 @@ -35,380 +35,238 @@
     8.4    /// \addtogroup exceptions
     8.5    /// @{
     8.6  
     8.7 -  /// \brief Exception safe wrapper class.
     8.8 +  /// \brief Generic exception class.
     8.9    ///
    8.10 -  /// Exception safe wrapper class to implement the members of exceptions.
    8.11 -  template <typename _Type>
    8.12 -  class ExceptionMember {
    8.13 -  public:
    8.14 -    typedef _Type Type;
    8.15 -
    8.16 -    ExceptionMember() throw() {
    8.17 -      try {
    8.18 -        ptr.reset(new Type());
    8.19 -      } catch (...) {}
    8.20 -    }
    8.21 -
    8.22 -    ExceptionMember(const Type& type) throw() {
    8.23 -      try {
    8.24 -        ptr.reset(new Type());
    8.25 -        if (ptr.get() == 0) return;
    8.26 -        *ptr = type;
    8.27 -      } catch (...) {}
    8.28 -    }
    8.29 -
    8.30 -    ExceptionMember(const ExceptionMember& copy) throw() {
    8.31 -      try {
    8.32 -        if (!copy.valid()) return;
    8.33 -        ptr.reset(new Type());
    8.34 -        if (ptr.get() == 0) return;
    8.35 -        *ptr = copy.get();
    8.36 -      } catch (...) {}
    8.37 -    }
    8.38 -
    8.39 -    ExceptionMember& operator=(const ExceptionMember& copy) throw() {
    8.40 -      if (ptr.get() == 0) return;
    8.41 -      try {
    8.42 -        if (!copy.valid()) return;
    8.43 -        *ptr = copy.get();
    8.44 -      } catch (...) {}
    8.45 -    }
    8.46 -
    8.47 -    void set(const Type& type) throw() {
    8.48 -      if (ptr.get() == 0) return;
    8.49 -      try {
    8.50 -        *ptr = type;
    8.51 -      } catch (...) {}
    8.52 -    }
    8.53 -
    8.54 -    const Type& get() const {
    8.55 -      return *ptr;
    8.56 -    }
    8.57 -
    8.58 -    bool valid() const throw() {
    8.59 -      return ptr.get() != 0;
    8.60 -    }
    8.61 -
    8.62 -  private:
    8.63 -    std::auto_ptr<_Type> ptr;
    8.64 -  };
    8.65 -
    8.66 -  /// Exception-safe convenient error message builder class.
    8.67 -
    8.68 -  /// Helper class which provides a convenient ostream-like (operator <<
    8.69 -  /// based) interface to create a string message. Mostly useful in
    8.70 -  /// exception classes (therefore the name).
    8.71 -  class ErrorMessage {
    8.72 -  protected:
    8.73 -    ///\e
    8.74 -
    8.75 -    mutable std::auto_ptr<std::ostringstream> buf;
    8.76 -
    8.77 -    ///\e
    8.78 -    bool init() throw() {
    8.79 -      try {
    8.80 -        buf.reset(new std::ostringstream);
    8.81 -      }
    8.82 -      catch(...) {
    8.83 -        buf.reset();
    8.84 -      }
    8.85 -      return buf.get();
    8.86 -    }
    8.87 -
    8.88 -  public:
    8.89 -
    8.90 -    ///\e
    8.91 -    ErrorMessage() throw() { init(); }
    8.92 -
    8.93 -    ErrorMessage(const ErrorMessage& em) throw() : buf(em.buf) { }
    8.94 -
    8.95 -    ///\e
    8.96 -    ErrorMessage(const char *msg) throw() {
    8.97 -      init();
    8.98 -      *this << msg;
    8.99 -    }
   8.100 -
   8.101 -    ///\e
   8.102 -    ErrorMessage(const std::string &msg) throw() {
   8.103 -      init();
   8.104 -      *this << msg;
   8.105 -    }
   8.106 -
   8.107 -    ///\e
   8.108 -    template <typename T>
   8.109 -    ErrorMessage& operator<<(const T &t) throw() {
   8.110 -      if( ! buf.get() ) return *this;
   8.111 -
   8.112 -      try {
   8.113 -        *buf << t;
   8.114 -      }
   8.115 -      catch(...) {
   8.116 -        buf.reset();
   8.117 -      }
   8.118 -      return *this;
   8.119 -    }
   8.120 -
   8.121 -    ///\e
   8.122 -    const char* message() throw() {
   8.123 -      if( ! buf.get() ) return 0;
   8.124 -
   8.125 -      const char* mes = 0;
   8.126 -      try {
   8.127 -        mes = buf->str().c_str();
   8.128 -      }
   8.129 -      catch(...) {}
   8.130 -      return mes;
   8.131 -    }
   8.132 -
   8.133 -  };
   8.134 -
   8.135 -  /// Generic exception class.
   8.136 -
   8.137    /// Base class for exceptions used in LEMON.
   8.138    ///
   8.139    class Exception : public std::exception {
   8.140    public:
   8.141 -    ///\e
   8.142 +    ///\e Constructor
   8.143      Exception() {}
   8.144 -    ///\e
   8.145 +    ///\e Virtual destructor
   8.146      virtual ~Exception() throw() {}
   8.147 -    ///\e
   8.148 +    ///\e A short description of the exception
   8.149      virtual const char* what() const throw() {
   8.150        return "lemon::Exception";
   8.151      }
   8.152    };
   8.153  
   8.154 -  /// One of the two main subclasses of \ref Exception.
   8.155 +  /// \brief Input-Output error
   8.156 +  ///
   8.157 +  /// This exception is thrown when a file operation cannot be
   8.158 +  /// succeeded.
   8.159 +  class IoError : public Exception {
   8.160 +  protected:
   8.161 +    std::string _message;
   8.162 +    std::string _file;
   8.163  
   8.164 -  /// Logic errors represent problems in the internal logic of a program;
   8.165 -  /// in theory, these are preventable, and even detectable before the
   8.166 -  /// program runs (e.g. violations of class invariants).
   8.167 -  ///
   8.168 -  /// A typical example for this is \ref UninitializedParameter.
   8.169 -  class LogicError : public Exception {
   8.170 +    mutable std::string _what;
   8.171    public:
   8.172 +
   8.173 +    /// Copy constructor
   8.174 +    IoError(const IoError &error) {
   8.175 +      message(error._message);
   8.176 +      file(error._file);
   8.177 +    }
   8.178 +
   8.179 +    /// Constructor
   8.180 +    explicit IoError(const char *message) {
   8.181 +      IoError::message(message);
   8.182 +    }
   8.183 +
   8.184 +    /// Constructor
   8.185 +    explicit IoError(const std::string &message) {
   8.186 +      IoError::message(message);
   8.187 +    }
   8.188 +
   8.189 +    /// Constructor
   8.190 +    IoError(const std::string &file, const char *message) {
   8.191 +      IoError::message(message);
   8.192 +      IoError::file(file);
   8.193 +    }
   8.194 +
   8.195 +    /// Constructor
   8.196 +    IoError(const std::string &file, const std::string &message) {
   8.197 +      IoError::message(message);
   8.198 +      IoError::file(file);
   8.199 +    }
   8.200 +
   8.201 +    /// Virtual destructor
   8.202 +    virtual ~IoError() throw() {}
   8.203 +
   8.204 +    /// Set the error message
   8.205 +    void message(const char *message) {
   8.206 +      try {
   8.207 +        _message = message;
   8.208 +      } catch (...) {}
   8.209 +    }
   8.210 +
   8.211 +    /// Set the error message
   8.212 +    void message(const std::string& message) {
   8.213 +      try {
   8.214 +        _message = message;
   8.215 +      } catch (...) {}
   8.216 +    }
   8.217 +
   8.218 +    /// Set the file name
   8.219 +    void file(const std::string &file) {
   8.220 +      try {
   8.221 +        _file = file;
   8.222 +      } catch (...) {}
   8.223 +    }
   8.224 +
   8.225 +    /// Returns the error message
   8.226 +    const std::string& message() const {
   8.227 +      return _message;
   8.228 +    }
   8.229 +
   8.230 +    /// \brief Returns the filename
   8.231 +    ///
   8.232 +    /// Returns the filename or empty string if the filename was not
   8.233 +    /// specified.
   8.234 +    const std::string& file() const {
   8.235 +      return _file;
   8.236 +    }
   8.237 +
   8.238 +    /// \brief Returns a short error message
   8.239 +    ///
   8.240 +    /// Returns a short error message which contains the message, the
   8.241 +    /// file name and the line number.
   8.242      virtual const char* what() const throw() {
   8.243 -      return "lemon::LogicError";
   8.244 +      try {
   8.245 +        _what.clear();
   8.246 +        std::ostringstream oss;
   8.247 +        oss << "lemon:IoError" << ": ";
   8.248 +        oss << message();
   8.249 +        if (!file().empty()) {
   8.250 +          oss << " (";
   8.251 +          if (!file().empty()) oss << "with file '" << file() << "'";
   8.252 +          oss << ")";
   8.253 +        }
   8.254 +        _what = oss.str();
   8.255 +      }
   8.256 +      catch (...) {}
   8.257 +      if (!_what.empty()) return _what.c_str();
   8.258 +      else return "lemon:IoError";
   8.259      }
   8.260 +
   8.261    };
   8.262  
   8.263 -  /// \ref Exception for uninitialized parameters.
   8.264 -
   8.265 -  /// This error represents problems in the initialization
   8.266 -  /// of the parameters of the algorithms.
   8.267 -  class UninitializedParameter : public LogicError {
   8.268 -  public:
   8.269 -    virtual const char* what() const throw() {
   8.270 -      return "lemon::UninitializedParameter";
   8.271 -    }
   8.272 -  };
   8.273 -
   8.274 -
   8.275 -  /// One of the two main subclasses of \ref Exception.
   8.276 -
   8.277 -  /// Runtime errors represent problems outside the scope of a program;
   8.278 -  /// they cannot be easily predicted and can generally only be caught
   8.279 -  /// as the program executes.
   8.280 -  class RuntimeError : public Exception {
   8.281 -  public:
   8.282 -    virtual const char* what() const throw() {
   8.283 -      return "lemon::RuntimeError";
   8.284 -    }
   8.285 -  };
   8.286 -
   8.287 -  ///\e
   8.288 -  class RangeError : public RuntimeError {
   8.289 -  public:
   8.290 -    virtual const char* what() const throw() {
   8.291 -      return "lemon::RangeError";
   8.292 -    }
   8.293 -  };
   8.294 -
   8.295 -  ///\e
   8.296 -  class IoError : public RuntimeError {
   8.297 -  public:
   8.298 -    virtual const char* what() const throw() {
   8.299 -      return "lemon::IoError";
   8.300 -    }
   8.301 -  };
   8.302 -
   8.303 -  ///\e
   8.304 -  class DataFormatError : public IoError {
   8.305 +  /// \brief Format error
   8.306 +  ///
   8.307 +  /// This class is used to indicate if an input file has wrong
   8.308 +  /// formatting, or a data representation is not legal.
   8.309 +  class FormatError : public Exception {
   8.310    protected:
   8.311 -    ExceptionMember<std::string> _message;
   8.312 -    ExceptionMember<std::string> _file;
   8.313 +    std::string _message;
   8.314 +    std::string _file;
   8.315      int _line;
   8.316  
   8.317 -    mutable ExceptionMember<std::string> _message_holder;
   8.318 +    mutable std::string _what;
   8.319    public:
   8.320  
   8.321 -    DataFormatError(const DataFormatError &dfe) :
   8.322 -      IoError(dfe), _message(dfe._message), _file(dfe._file),
   8.323 -      _line(dfe._line) {}
   8.324 -
   8.325 -    ///\e
   8.326 -    explicit DataFormatError(const char *the_message)
   8.327 -      : _message(the_message), _line(0) {}
   8.328 -
   8.329 -    ///\e
   8.330 -    DataFormatError(const std::string &file_name, int line_num,
   8.331 -                    const char *the_message)
   8.332 -      : _message(the_message), _line(line_num) { file(file_name); }
   8.333 -
   8.334 -    ///\e
   8.335 -    void line(int ln) { _line = ln; }
   8.336 -    ///\e
   8.337 -    void message(const std::string& msg) { _message.set(msg); }
   8.338 -    ///\e
   8.339 -    void file(const std::string &fl) { _file.set(fl); }
   8.340 -
   8.341 -    ///\e
   8.342 -    int line() const { return _line; }
   8.343 -    ///\e
   8.344 -    const char* message() const {
   8.345 -      if (_message.valid() && !_message.get().empty()) {
   8.346 -        return _message.get().c_str();
   8.347 -      } else {
   8.348 -        return 0;
   8.349 -      }
   8.350 +    /// Copy constructor
   8.351 +    FormatError(const FormatError &error) {
   8.352 +      message(error._message);
   8.353 +      file(error._file);
   8.354 +      line(error._line);
   8.355      }
   8.356  
   8.357 -    /// \brief Returns the filename.
   8.358 -    ///
   8.359 -    /// Returns \e null if the filename was not specified.
   8.360 -    const char* file() const {
   8.361 -      if (_file.valid() && !_file.get().empty()) {
   8.362 -        return _file.get().c_str();
   8.363 -      } else {
   8.364 -        return 0;
   8.365 -      }
   8.366 +    /// Constructor
   8.367 +    explicit FormatError(const char *message) {
   8.368 +      FormatError::message(message);
   8.369 +      _line = 0;
   8.370      }
   8.371  
   8.372 -    ///\e
   8.373 +    /// Constructor
   8.374 +    explicit FormatError(const std::string &message) {
   8.375 +      FormatError::message(message);
   8.376 +      _line = 0;
   8.377 +    }
   8.378 +
   8.379 +    /// Constructor
   8.380 +    FormatError(const std::string &file, int line, const char *message) {
   8.381 +      FormatError::message(message);
   8.382 +      FormatError::file(file);
   8.383 +      FormatError::line(line);
   8.384 +    }
   8.385 +
   8.386 +    /// Constructor
   8.387 +    FormatError(const std::string &file, int line, const std::string &message) {
   8.388 +      FormatError::message(message);
   8.389 +      FormatError::file(file);
   8.390 +      FormatError::line(line);
   8.391 +    }
   8.392 +
   8.393 +    /// Virtual destructor
   8.394 +    virtual ~FormatError() throw() {}
   8.395 +
   8.396 +    /// Set the line number
   8.397 +    void line(int line) { _line = line; }
   8.398 +
   8.399 +    /// Set the error message
   8.400 +    void message(const char *message) {
   8.401 +      try {
   8.402 +        _message = message;
   8.403 +      } catch (...) {}
   8.404 +    }
   8.405 +
   8.406 +    /// Set the error message
   8.407 +    void message(const std::string& message) {
   8.408 +      try {
   8.409 +        _message = message;
   8.410 +      } catch (...) {}
   8.411 +    }
   8.412 +
   8.413 +    /// Set the file name
   8.414 +    void file(const std::string &file) {
   8.415 +      try {
   8.416 +        _file = file;
   8.417 +      } catch (...) {}
   8.418 +    }
   8.419 +
   8.420 +    /// \brief Returns the line number
   8.421 +    ///
   8.422 +    /// Returns the line number or zero if it was not specified.
   8.423 +    int line() const { return _line; }
   8.424 +
   8.425 +    /// Returns the error message
   8.426 +    const std::string& message() const {
   8.427 +      return _message;
   8.428 +    }
   8.429 +
   8.430 +    /// \brief Returns the filename
   8.431 +    ///
   8.432 +    /// Returns the filename or empty string if the filename was not
   8.433 +    /// specified.
   8.434 +    const std::string& file() const {
   8.435 +      return _file;
   8.436 +    }
   8.437 +
   8.438 +    /// \brief Returns a short error message
   8.439 +    ///
   8.440 +    /// Returns a short error message which contains the message, the
   8.441 +    /// file name and the line number.
   8.442      virtual const char* what() const throw() {
   8.443        try {
   8.444 -        std::ostringstream ostr;
   8.445 -        ostr << "lemon:DataFormatError" << ": ";
   8.446 -        if (message()) ostr << message();
   8.447 -        if( file() || line() != 0 ) {
   8.448 -          ostr << " (";
   8.449 -          if( file() ) ostr << "in file '" << file() << "'";
   8.450 -          if( file() && line() != 0 ) ostr << " ";
   8.451 -          if( line() != 0 ) ostr << "at line " << line();
   8.452 -          ostr << ")";
   8.453 +        _what.clear();
   8.454 +        std::ostringstream oss;
   8.455 +        oss << "lemon:FormatError" << ": ";
   8.456 +        oss << message();
   8.457 +        if (!file().empty() || line() != 0) {
   8.458 +          oss << " (";
   8.459 +          if (!file().empty()) oss << "in file '" << file() << "'";
   8.460 +          if (!file().empty() && line() != 0) oss << " ";
   8.461 +          if (line() != 0) oss << "at line " << line();
   8.462 +          oss << ")";
   8.463          }
   8.464 -        _message_holder.set(ostr.str());
   8.465 +        _what = oss.str();
   8.466        }
   8.467        catch (...) {}
   8.468 -      if( _message_holder.valid()) return _message_holder.get().c_str();
   8.469 -      return "lemon:DataFormatError";
   8.470 +      if (!_what.empty()) return _what.c_str();
   8.471 +      else return "lemon:FormatError";
   8.472      }
   8.473  
   8.474 -    virtual ~DataFormatError() throw() {}
   8.475 -  };
   8.476 -
   8.477 -  ///\e
   8.478 -  class FileOpenError : public IoError {
   8.479 -  protected:
   8.480 -    ExceptionMember<std::string> _file;
   8.481 -
   8.482 -    mutable ExceptionMember<std::string> _message_holder;
   8.483 -  public:
   8.484 -
   8.485 -    FileOpenError(const FileOpenError &foe) :
   8.486 -      IoError(foe), _file(foe._file) {}
   8.487 -
   8.488 -    ///\e
   8.489 -    explicit FileOpenError(const std::string& fl)
   8.490 -      : _file(fl) {}
   8.491 -
   8.492 -
   8.493 -    ///\e
   8.494 -    void file(const std::string &fl) { _file.set(fl); }
   8.495 -
   8.496 -    /// \brief Returns the filename.
   8.497 -    ///
   8.498 -    /// Returns \e null if the filename was not specified.
   8.499 -    const char* file() const {
   8.500 -      if (_file.valid() && !_file.get().empty()) {
   8.501 -        return _file.get().c_str();
   8.502 -      } else {
   8.503 -        return 0;
   8.504 -      }
   8.505 -    }
   8.506 -
   8.507 -    ///\e
   8.508 -    virtual const char* what() const throw() {
   8.509 -      try {
   8.510 -        std::ostringstream ostr;
   8.511 -        ostr << "lemon::FileOpenError" << ": ";
   8.512 -        ostr << "Cannot open file - " << file();
   8.513 -        _message_holder.set(ostr.str());
   8.514 -      }
   8.515 -      catch (...) {}
   8.516 -      if( _message_holder.valid()) return _message_holder.get().c_str();
   8.517 -      return "lemon::FileOpenError";
   8.518 -    }
   8.519 -    virtual ~FileOpenError() throw() {}
   8.520 -  };
   8.521 -
   8.522 -  class IoParameterError : public IoError {
   8.523 -  protected:
   8.524 -    ExceptionMember<std::string> _message;
   8.525 -    ExceptionMember<std::string> _file;
   8.526 -
   8.527 -    mutable ExceptionMember<std::string> _message_holder;
   8.528 -  public:
   8.529 -
   8.530 -    IoParameterError(const IoParameterError &ile) :
   8.531 -      IoError(ile), _message(ile._message), _file(ile._file) {}
   8.532 -
   8.533 -    ///\e
   8.534 -    explicit IoParameterError(const char *the_message)
   8.535 -      : _message(the_message) {}
   8.536 -
   8.537 -    ///\e
   8.538 -    IoParameterError(const char *file_name, const char *the_message)
   8.539 -      : _message(the_message), _file(file_name) {}
   8.540 -
   8.541 -     ///\e
   8.542 -    void message(const std::string& msg) { _message.set(msg); }
   8.543 -    ///\e
   8.544 -    void file(const std::string &fl) { _file.set(fl); }
   8.545 -
   8.546 -     ///\e
   8.547 -    const char* message() const {
   8.548 -      if (_message.valid()) {
   8.549 -        return _message.get().c_str();
   8.550 -      } else {
   8.551 -        return 0;
   8.552 -      }
   8.553 -    }
   8.554 -
   8.555 -    /// \brief Returns the filename.
   8.556 -    ///
   8.557 -    /// Returns \c 0 if the filename was not specified.
   8.558 -    const char* file() const {
   8.559 -      if (_file.valid()) {
   8.560 -        return _file.get().c_str();
   8.561 -      } else {
   8.562 -        return 0;
   8.563 -      }
   8.564 -    }
   8.565 -
   8.566 -    ///\e
   8.567 -    virtual const char* what() const throw() {
   8.568 -      try {
   8.569 -        std::ostringstream ostr;
   8.570 -        if (message()) ostr << message();
   8.571 -        if (file()) ostr << "(when reading file '" << file() << "')";
   8.572 -        _message_holder.set(ostr.str());
   8.573 -      }
   8.574 -      catch (...) {}
   8.575 -      if( _message_holder.valid() ) return _message_holder.get().c_str();
   8.576 -      return "lemon:IoParameterError";
   8.577 -    }
   8.578 -    virtual ~IoParameterError() throw() {}
   8.579    };
   8.580  
   8.581    /// @}
     9.1 --- a/lemon/graph_to_eps.h	Sat Sep 27 14:33:28 2008 +0200
     9.2 +++ b/lemon/graph_to_eps.h	Tue Sep 30 20:53:18 2008 +0200
     9.3 @@ -40,6 +40,7 @@
     9.4  #include<lemon/maps.h>
     9.5  #include<lemon/color.h>
     9.6  #include<lemon/bits/bezier.h>
     9.7 +#include<lemon/error.h>
     9.8  
     9.9  
    9.10  ///\ingroup eps_io
    9.11 @@ -1166,8 +1167,13 @@
    9.12  GraphToEps<DefaultGraphToEpsTraits<G> >
    9.13  graphToEps(G &g,const char *file_name)
    9.14  {
    9.15 +  std::ostream* os = new std::ofstream(file_name);
    9.16 +  if (!(*os)) {
    9.17 +    delete os;
    9.18 +    throw IoError(file_name, "Cannot write file");
    9.19 +  }
    9.20    return GraphToEps<DefaultGraphToEpsTraits<G> >
    9.21 -    (DefaultGraphToEpsTraits<G>(g,*new std::ofstream(file_name),true));
    9.22 +    (DefaultGraphToEpsTraits<G>(g,*os,true));
    9.23  }
    9.24  
    9.25  ///Generates an EPS file from a graph
    9.26 @@ -1182,8 +1188,13 @@
    9.27  GraphToEps<DefaultGraphToEpsTraits<G> >
    9.28  graphToEps(G &g,const std::string& file_name)
    9.29  {
    9.30 +  std::ostream* os = new std::ofstream(file_name.c_str());
    9.31 +  if (!(*os)) {
    9.32 +    delete os;
    9.33 +    throw IoError(file_name, "Cannot write file");
    9.34 +  }
    9.35    return GraphToEps<DefaultGraphToEpsTraits<G> >
    9.36 -    (DefaultGraphToEpsTraits<G>(g,*new std::ofstream(file_name.c_str()),true));
    9.37 +    (DefaultGraphToEpsTraits<G>(g,*os,true));
    9.38  }
    9.39  
    9.40  } //END OF NAMESPACE LEMON
    10.1 --- a/lemon/lgf_reader.h	Sat Sep 27 14:33:28 2008 +0200
    10.2 +++ b/lemon/lgf_reader.h	Tue Sep 30 20:53:18 2008 +0200
    10.3 @@ -48,11 +48,13 @@
    10.4        Value operator()(const std::string& str) {
    10.5          std::istringstream is(str);
    10.6          Value value;
    10.7 -        is >> value;
    10.8 +        if (!(is >> value)) {
    10.9 +          throw FormatError("Cannot read token");
   10.10 +        }
   10.11  
   10.12          char c;
   10.13          if (is >> std::ws >> c) {
   10.14 -          throw DataFormatError("Remaining characters in token");
   10.15 +          throw FormatError("Remaining characters in token");
   10.16          }
   10.17          return value;
   10.18        }
   10.19 @@ -166,7 +168,7 @@
   10.20          if (it == _map.end()) {
   10.21            std::ostringstream msg;
   10.22            msg << "Item not found: " << str;
   10.23 -          throw DataFormatError(msg.str().c_str());
   10.24 +          throw FormatError(msg.str());
   10.25          }
   10.26          return it->second;
   10.27        }
   10.28 @@ -184,12 +186,12 @@
   10.29  
   10.30        typename Graph::Arc operator()(const std::string& str) {
   10.31          if (str.empty() || (str[0] != '+' && str[0] != '-')) {
   10.32 -          throw DataFormatError("Item must start with '+' or '-'");
   10.33 +          throw FormatError("Item must start with '+' or '-'");
   10.34          }
   10.35          typename std::map<std::string, typename Graph::Edge>
   10.36            ::const_iterator it = _map.find(str.substr(1));
   10.37          if (it == _map.end()) {
   10.38 -          throw DataFormatError("Item not found");
   10.39 +          throw FormatError("Item not found");
   10.40          }
   10.41          return _graph.direct(it->second, str[0] == '+');
   10.42        }
   10.43 @@ -235,7 +237,7 @@
   10.44      inline char readEscape(std::istream& is) {
   10.45        char c;
   10.46        if (!is.get(c))
   10.47 -        throw DataFormatError("Escape format error");
   10.48 +        throw FormatError("Escape format error");
   10.49  
   10.50        switch (c) {
   10.51        case '\\':
   10.52 @@ -264,7 +266,7 @@
   10.53          {
   10.54            int code;
   10.55            if (!is.get(c) || !isHex(c))
   10.56 -            throw DataFormatError("Escape format error");
   10.57 +            throw FormatError("Escape format error");
   10.58            else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
   10.59            else code = code * 16 + valueHex(c);
   10.60            return code;
   10.61 @@ -273,7 +275,7 @@
   10.62          {
   10.63            int code;
   10.64            if (!isOct(c))
   10.65 -            throw DataFormatError("Escape format error");
   10.66 +            throw FormatError("Escape format error");
   10.67            else if (code = valueOct(c), !is.get(c) || !isOct(c))
   10.68              is.putback(c);
   10.69            else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c))
   10.70 @@ -300,7 +302,7 @@
   10.71            os << c;
   10.72          }
   10.73          if (!is)
   10.74 -          throw DataFormatError("Quoted format error");
   10.75 +          throw FormatError("Quoted format error");
   10.76        } else {
   10.77          is.putback(c);
   10.78          while (is.get(c) && !isWhiteSpace(c)) {
   10.79 @@ -460,6 +462,7 @@
   10.80  
   10.81      std::istream* _is;
   10.82      bool local_is;
   10.83 +    std::string _filename;
   10.84  
   10.85      Digraph& _digraph;
   10.86  
   10.87 @@ -509,18 +512,24 @@
   10.88      /// Construct a directed graph reader, which reads from the given
   10.89      /// file.
   10.90      DigraphReader(const std::string& fn, Digraph& digraph)
   10.91 -      : _is(new std::ifstream(fn.c_str())), local_is(true), _digraph(digraph),
   10.92 +      : _is(new std::ifstream(fn.c_str())), local_is(true),
   10.93 +        _filename(fn), _digraph(digraph),
   10.94          _use_nodes(false), _use_arcs(false),
   10.95 -        _skip_nodes(false), _skip_arcs(false) {}
   10.96 +        _skip_nodes(false), _skip_arcs(false) {
   10.97 +      if (!(*_is)) throw IoError(fn, "Cannot open file");
   10.98 +    }
   10.99  
  10.100      /// \brief Constructor
  10.101      ///
  10.102      /// Construct a directed graph reader, which reads from the given
  10.103      /// file.
  10.104      DigraphReader(const char* fn, Digraph& digraph)
  10.105 -      : _is(new std::ifstream(fn)), local_is(true), _digraph(digraph),
  10.106 +      : _is(new std::ifstream(fn)), local_is(true),
  10.107 +        _filename(fn), _digraph(digraph),
  10.108          _use_nodes(false), _use_arcs(false),
  10.109 -        _skip_nodes(false), _skip_arcs(false) {}
  10.110 +        _skip_nodes(false), _skip_arcs(false) {
  10.111 +      if (!(*_is)) throw IoError(fn, "Cannot open file");
  10.112 +    }
  10.113  
  10.114      /// \brief Destructor
  10.115      ~DigraphReader() {
  10.116 @@ -845,7 +854,7 @@
  10.117        if (!readLine() || !(line >> c) || c == '@') {
  10.118          if (readSuccess() && line) line.putback(c);
  10.119          if (!_node_maps.empty())
  10.120 -          throw DataFormatError("Cannot find map names");
  10.121 +          throw FormatError("Cannot find map names");
  10.122          return;
  10.123        }
  10.124        line.putback(c);
  10.125 @@ -859,7 +868,7 @@
  10.126            if (maps.find(map) != maps.end()) {
  10.127              std::ostringstream msg;
  10.128              msg << "Multiple occurence of node map: " << map;
  10.129 -            throw DataFormatError(msg.str().c_str());
  10.130 +            throw FormatError(msg.str());
  10.131            }
  10.132            maps.insert(std::make_pair(map, index));
  10.133            ++index;
  10.134 @@ -871,7 +880,7 @@
  10.135            if (jt == maps.end()) {
  10.136              std::ostringstream msg;
  10.137              msg << "Map not found in file: " << _node_maps[i].first;
  10.138 -            throw DataFormatError(msg.str().c_str());
  10.139 +            throw FormatError(msg.str());
  10.140            }
  10.141            map_index[i] = jt->second;
  10.142          }
  10.143 @@ -895,11 +904,11 @@
  10.144            if (!_reader_bits::readToken(line, tokens[i])) {
  10.145              std::ostringstream msg;
  10.146              msg << "Column not found (" << i + 1 << ")";
  10.147 -            throw DataFormatError(msg.str().c_str());
  10.148 +            throw FormatError(msg.str());
  10.149            }
  10.150          }
  10.151          if (line >> std::ws >> c)
  10.152 -          throw DataFormatError("Extra character on the end of line");
  10.153 +          throw FormatError("Extra character on the end of line");
  10.154  
  10.155          Node n;
  10.156          if (!_use_nodes) {
  10.157 @@ -908,13 +917,13 @@
  10.158              _node_index.insert(std::make_pair(tokens[label_index], n));
  10.159          } else {
  10.160            if (label_index == -1)
  10.161 -            throw DataFormatError("Label map not found in file");
  10.162 +            throw FormatError("Label map not found in file");
  10.163            typename std::map<std::string, Node>::iterator it =
  10.164              _node_index.find(tokens[label_index]);
  10.165            if (it == _node_index.end()) {
  10.166              std::ostringstream msg;
  10.167              msg << "Node with label not found: " << tokens[label_index];
  10.168 -            throw DataFormatError(msg.str().c_str());
  10.169 +            throw FormatError(msg.str());
  10.170            }
  10.171            n = it->second;
  10.172          }
  10.173 @@ -938,7 +947,7 @@
  10.174        if (!readLine() || !(line >> c) || c == '@') {
  10.175          if (readSuccess() && line) line.putback(c);
  10.176          if (!_arc_maps.empty())
  10.177 -          throw DataFormatError("Cannot find map names");
  10.178 +          throw FormatError("Cannot find map names");
  10.179          return;
  10.180        }
  10.181        line.putback(c);
  10.182 @@ -952,7 +961,7 @@
  10.183            if (maps.find(map) != maps.end()) {
  10.184              std::ostringstream msg;
  10.185              msg << "Multiple occurence of arc map: " << map;
  10.186 -            throw DataFormatError(msg.str().c_str());
  10.187 +            throw FormatError(msg.str());
  10.188            }
  10.189            maps.insert(std::make_pair(map, index));
  10.190            ++index;
  10.191 @@ -964,7 +973,7 @@
  10.192            if (jt == maps.end()) {
  10.193              std::ostringstream msg;
  10.194              msg << "Map not found in file: " << _arc_maps[i].first;
  10.195 -            throw DataFormatError(msg.str().c_str());
  10.196 +            throw FormatError(msg.str());
  10.197            }
  10.198            map_index[i] = jt->second;
  10.199          }
  10.200 @@ -987,21 +996,21 @@
  10.201          std::string target_token;
  10.202  
  10.203          if (!_reader_bits::readToken(line, source_token))
  10.204 -          throw DataFormatError("Source not found");
  10.205 +          throw FormatError("Source not found");
  10.206  
  10.207          if (!_reader_bits::readToken(line, target_token))
  10.208 -          throw DataFormatError("Target not found");
  10.209 +          throw FormatError("Target not found");
  10.210  
  10.211          std::vector<std::string> tokens(map_num);
  10.212          for (int i = 0; i < map_num; ++i) {
  10.213            if (!_reader_bits::readToken(line, tokens[i])) {
  10.214              std::ostringstream msg;
  10.215              msg << "Column not found (" << i + 1 << ")";
  10.216 -            throw DataFormatError(msg.str().c_str());
  10.217 +            throw FormatError(msg.str());
  10.218            }
  10.219          }
  10.220          if (line >> std::ws >> c)
  10.221 -          throw DataFormatError("Extra character on the end of line");
  10.222 +          throw FormatError("Extra character on the end of line");
  10.223  
  10.224          Arc a;
  10.225          if (!_use_arcs) {
  10.226 @@ -1012,7 +1021,7 @@
  10.227            if (it == _node_index.end()) {
  10.228              std::ostringstream msg;
  10.229              msg << "Item not found: " << source_token;
  10.230 -            throw DataFormatError(msg.str().c_str());
  10.231 +            throw FormatError(msg.str());
  10.232            }
  10.233            Node source = it->second;
  10.234  
  10.235 @@ -1020,7 +1029,7 @@
  10.236            if (it == _node_index.end()) {
  10.237              std::ostringstream msg;
  10.238              msg << "Item not found: " << target_token;
  10.239 -            throw DataFormatError(msg.str().c_str());
  10.240 +            throw FormatError(msg.str());
  10.241            }
  10.242            Node target = it->second;
  10.243  
  10.244 @@ -1029,13 +1038,13 @@
  10.245              _arc_index.insert(std::make_pair(tokens[label_index], a));
  10.246          } else {
  10.247            if (label_index == -1)
  10.248 -            throw DataFormatError("Label map not found in file");
  10.249 +            throw FormatError("Label map not found in file");
  10.250            typename std::map<std::string, Arc>::iterator it =
  10.251              _arc_index.find(tokens[label_index]);
  10.252            if (it == _arc_index.end()) {
  10.253              std::ostringstream msg;
  10.254              msg << "Arc with label not found: " << tokens[label_index];
  10.255 -            throw DataFormatError(msg.str().c_str());
  10.256 +            throw FormatError(msg.str());
  10.257            }
  10.258            a = it->second;
  10.259          }
  10.260 @@ -1060,18 +1069,18 @@
  10.261  
  10.262          std::string attr, token;
  10.263          if (!_reader_bits::readToken(line, attr))
  10.264 -          throw DataFormatError("Attribute name not found");
  10.265 +          throw FormatError("Attribute name not found");
  10.266          if (!_reader_bits::readToken(line, token))
  10.267 -          throw DataFormatError("Attribute value not found");
  10.268 +          throw FormatError("Attribute value not found");
  10.269          if (line >> c)
  10.270 -          throw DataFormatError("Extra character on the end of line");
  10.271 +          throw FormatError("Extra character on the end of line");
  10.272  
  10.273          {
  10.274            std::set<std::string>::iterator it = read_attr.find(attr);
  10.275            if (it != read_attr.end()) {
  10.276              std::ostringstream msg;
  10.277              msg << "Multiple occurence of attribute " << attr;
  10.278 -            throw DataFormatError(msg.str().c_str());
  10.279 +            throw FormatError(msg.str());
  10.280            }
  10.281            read_attr.insert(attr);
  10.282          }
  10.283 @@ -1093,7 +1102,7 @@
  10.284          if (read_attr.find(it->first) == read_attr.end()) {
  10.285            std::ostringstream msg;
  10.286            msg << "Attribute not found in file: " << it->first;
  10.287 -          throw DataFormatError(msg.str().c_str());
  10.288 +          throw FormatError(msg.str());
  10.289          }
  10.290        }
  10.291      }
  10.292 @@ -1109,7 +1118,7 @@
  10.293      void run() {
  10.294        LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
  10.295        if (!*_is) {
  10.296 -        throw DataFormatError("Cannot find file");
  10.297 +        throw FormatError("Cannot find file");
  10.298        }
  10.299  
  10.300        bool nodes_done = _skip_nodes;
  10.301 @@ -1129,7 +1138,7 @@
  10.302            _reader_bits::readToken(line, caption);
  10.303  
  10.304            if (line >> c)
  10.305 -            throw DataFormatError("Extra character on the end of line");
  10.306 +            throw FormatError("Extra character on the end of line");
  10.307  
  10.308            if (section == "nodes" && !nodes_done) {
  10.309              if (_nodes_caption.empty() || _nodes_caption == caption) {
  10.310 @@ -1151,22 +1160,23 @@
  10.311              readLine();
  10.312              skipSection();
  10.313            }
  10.314 -        } catch (DataFormatError& error) {
  10.315 +        } catch (FormatError& error) {
  10.316            error.line(line_num);
  10.317 +          error.file(_filename);
  10.318            throw;
  10.319          }
  10.320        }
  10.321  
  10.322        if (!nodes_done) {
  10.323 -        throw DataFormatError("Section @nodes not found");
  10.324 +        throw FormatError("Section @nodes not found");
  10.325        }
  10.326  
  10.327        if (!arcs_done) {
  10.328 -        throw DataFormatError("Section @arcs not found");
  10.329 +        throw FormatError("Section @arcs not found");
  10.330        }
  10.331  
  10.332        if (!attributes_done && !_attributes.empty()) {
  10.333 -        throw DataFormatError("Section @attributes not found");
  10.334 +        throw FormatError("Section @attributes not found");
  10.335        }
  10.336  
  10.337      }
  10.338 @@ -1244,6 +1254,7 @@
  10.339  
  10.340      std::istream* _is;
  10.341      bool local_is;
  10.342 +    std::string _filename;
  10.343  
  10.344      Graph& _graph;
  10.345  
  10.346 @@ -1293,18 +1304,24 @@
  10.347      /// Construct an undirected graph reader, which reads from the given
  10.348      /// file.
  10.349      GraphReader(const std::string& fn, Graph& graph)
  10.350 -      : _is(new std::ifstream(fn.c_str())), local_is(true), _graph(graph),
  10.351 +      : _is(new std::ifstream(fn.c_str())), local_is(true),
  10.352 +        _filename(fn), _graph(graph),
  10.353          _use_nodes(false), _use_edges(false),
  10.354 -        _skip_nodes(false), _skip_edges(false) {}
  10.355 +        _skip_nodes(false), _skip_edges(false) {
  10.356 +      if (!(*_is)) throw IoError(fn, "Cannot open file");
  10.357 +    }
  10.358  
  10.359      /// \brief Constructor
  10.360      ///
  10.361      /// Construct an undirected graph reader, which reads from the given
  10.362      /// file.
  10.363      GraphReader(const char* fn, Graph& graph)
  10.364 -      : _is(new std::ifstream(fn)), local_is(true), _graph(graph),
  10.365 +      : _is(new std::ifstream(fn)), local_is(true),
  10.366 +        _filename(fn), _graph(graph),
  10.367          _use_nodes(false), _use_edges(false),
  10.368 -        _skip_nodes(false), _skip_edges(false) {}
  10.369 +        _skip_nodes(false), _skip_edges(false) {
  10.370 +      if (!(*_is)) throw IoError(fn, "Cannot open file");
  10.371 +    }
  10.372  
  10.373      /// \brief Destructor
  10.374      ~GraphReader() {
  10.375 @@ -1673,7 +1690,7 @@
  10.376        if (!readLine() || !(line >> c) || c == '@') {
  10.377          if (readSuccess() && line) line.putback(c);
  10.378          if (!_node_maps.empty())
  10.379 -          throw DataFormatError("Cannot find map names");
  10.380 +          throw FormatError("Cannot find map names");
  10.381          return;
  10.382        }
  10.383        line.putback(c);
  10.384 @@ -1687,7 +1704,7 @@
  10.385            if (maps.find(map) != maps.end()) {
  10.386              std::ostringstream msg;
  10.387              msg << "Multiple occurence of node map: " << map;
  10.388 -            throw DataFormatError(msg.str().c_str());
  10.389 +            throw FormatError(msg.str());
  10.390            }
  10.391            maps.insert(std::make_pair(map, index));
  10.392            ++index;
  10.393 @@ -1699,7 +1716,7 @@
  10.394            if (jt == maps.end()) {
  10.395              std::ostringstream msg;
  10.396              msg << "Map not found in file: " << _node_maps[i].first;
  10.397 -            throw DataFormatError(msg.str().c_str());
  10.398 +            throw FormatError(msg.str());
  10.399            }
  10.400            map_index[i] = jt->second;
  10.401          }
  10.402 @@ -1723,11 +1740,11 @@
  10.403            if (!_reader_bits::readToken(line, tokens[i])) {
  10.404              std::ostringstream msg;
  10.405              msg << "Column not found (" << i + 1 << ")";
  10.406 -            throw DataFormatError(msg.str().c_str());
  10.407 +            throw FormatError(msg.str());
  10.408            }
  10.409          }
  10.410          if (line >> std::ws >> c)
  10.411 -          throw DataFormatError("Extra character on the end of line");
  10.412 +          throw FormatError("Extra character on the end of line");
  10.413  
  10.414          Node n;
  10.415          if (!_use_nodes) {
  10.416 @@ -1736,13 +1753,13 @@
  10.417              _node_index.insert(std::make_pair(tokens[label_index], n));
  10.418          } else {
  10.419            if (label_index == -1)
  10.420 -            throw DataFormatError("Label map not found in file");
  10.421 +            throw FormatError("Label map not found in file");
  10.422            typename std::map<std::string, Node>::iterator it =
  10.423              _node_index.find(tokens[label_index]);
  10.424            if (it == _node_index.end()) {
  10.425              std::ostringstream msg;
  10.426              msg << "Node with label not found: " << tokens[label_index];
  10.427 -            throw DataFormatError(msg.str().c_str());
  10.428 +            throw FormatError(msg.str());
  10.429            }
  10.430            n = it->second;
  10.431          }
  10.432 @@ -1766,7 +1783,7 @@
  10.433        if (!readLine() || !(line >> c) || c == '@') {
  10.434          if (readSuccess() && line) line.putback(c);
  10.435          if (!_edge_maps.empty())
  10.436 -          throw DataFormatError("Cannot find map names");
  10.437 +          throw FormatError("Cannot find map names");
  10.438          return;
  10.439        }
  10.440        line.putback(c);
  10.441 @@ -1780,7 +1797,7 @@
  10.442            if (maps.find(map) != maps.end()) {
  10.443              std::ostringstream msg;
  10.444              msg << "Multiple occurence of edge map: " << map;
  10.445 -            throw DataFormatError(msg.str().c_str());
  10.446 +            throw FormatError(msg.str());
  10.447            }
  10.448            maps.insert(std::make_pair(map, index));
  10.449            ++index;
  10.450 @@ -1792,7 +1809,7 @@
  10.451            if (jt == maps.end()) {
  10.452              std::ostringstream msg;
  10.453              msg << "Map not found in file: " << _edge_maps[i].first;
  10.454 -            throw DataFormatError(msg.str().c_str());
  10.455 +            throw FormatError(msg.str());
  10.456            }
  10.457            map_index[i] = jt->second;
  10.458          }
  10.459 @@ -1815,21 +1832,21 @@
  10.460          std::string target_token;
  10.461  
  10.462          if (!_reader_bits::readToken(line, source_token))
  10.463 -          throw DataFormatError("Node u not found");
  10.464 +          throw FormatError("Node u not found");
  10.465  
  10.466          if (!_reader_bits::readToken(line, target_token))
  10.467 -          throw DataFormatError("Node v not found");
  10.468 +          throw FormatError("Node v not found");
  10.469  
  10.470          std::vector<std::string> tokens(map_num);
  10.471          for (int i = 0; i < map_num; ++i) {
  10.472            if (!_reader_bits::readToken(line, tokens[i])) {
  10.473              std::ostringstream msg;
  10.474              msg << "Column not found (" << i + 1 << ")";
  10.475 -            throw DataFormatError(msg.str().c_str());
  10.476 +            throw FormatError(msg.str());
  10.477            }
  10.478          }
  10.479          if (line >> std::ws >> c)
  10.480 -          throw DataFormatError("Extra character on the end of line");
  10.481 +          throw FormatError("Extra character on the end of line");
  10.482  
  10.483          Edge e;
  10.484          if (!_use_edges) {
  10.485 @@ -1840,7 +1857,7 @@
  10.486            if (it == _node_index.end()) {
  10.487              std::ostringstream msg;
  10.488              msg << "Item not found: " << source_token;
  10.489 -            throw DataFormatError(msg.str().c_str());
  10.490 +            throw FormatError(msg.str());
  10.491            }
  10.492            Node source = it->second;
  10.493  
  10.494 @@ -1848,7 +1865,7 @@
  10.495            if (it == _node_index.end()) {
  10.496              std::ostringstream msg;
  10.497              msg << "Item not found: " << target_token;
  10.498 -            throw DataFormatError(msg.str().c_str());
  10.499 +            throw FormatError(msg.str());
  10.500            }
  10.501            Node target = it->second;
  10.502  
  10.503 @@ -1857,13 +1874,13 @@
  10.504              _edge_index.insert(std::make_pair(tokens[label_index], e));
  10.505          } else {
  10.506            if (label_index == -1)
  10.507 -            throw DataFormatError("Label map not found in file");
  10.508 +            throw FormatError("Label map not found in file");
  10.509            typename std::map<std::string, Edge>::iterator it =
  10.510              _edge_index.find(tokens[label_index]);
  10.511            if (it == _edge_index.end()) {
  10.512              std::ostringstream msg;
  10.513              msg << "Edge with label not found: " << tokens[label_index];
  10.514 -            throw DataFormatError(msg.str().c_str());
  10.515 +            throw FormatError(msg.str());
  10.516            }
  10.517            e = it->second;
  10.518          }
  10.519 @@ -1888,18 +1905,18 @@
  10.520  
  10.521          std::string attr, token;
  10.522          if (!_reader_bits::readToken(line, attr))
  10.523 -          throw DataFormatError("Attribute name not found");
  10.524 +          throw FormatError("Attribute name not found");
  10.525          if (!_reader_bits::readToken(line, token))
  10.526 -          throw DataFormatError("Attribute value not found");
  10.527 +          throw FormatError("Attribute value not found");
  10.528          if (line >> c)
  10.529 -          throw DataFormatError("Extra character on the end of line");
  10.530 +          throw FormatError("Extra character on the end of line");
  10.531  
  10.532          {
  10.533            std::set<std::string>::iterator it = read_attr.find(attr);
  10.534            if (it != read_attr.end()) {
  10.535              std::ostringstream msg;
  10.536              msg << "Multiple occurence of attribute " << attr;
  10.537 -            throw DataFormatError(msg.str().c_str());
  10.538 +            throw FormatError(msg.str());
  10.539            }
  10.540            read_attr.insert(attr);
  10.541          }
  10.542 @@ -1921,7 +1938,7 @@
  10.543          if (read_attr.find(it->first) == read_attr.end()) {
  10.544            std::ostringstream msg;
  10.545            msg << "Attribute not found in file: " << it->first;
  10.546 -          throw DataFormatError(msg.str().c_str());
  10.547 +          throw FormatError(msg.str());
  10.548          }
  10.549        }
  10.550      }
  10.551 @@ -1955,7 +1972,7 @@
  10.552            _reader_bits::readToken(line, caption);
  10.553  
  10.554            if (line >> c)
  10.555 -            throw DataFormatError("Extra character on the end of line");
  10.556 +            throw FormatError("Extra character on the end of line");
  10.557  
  10.558            if (section == "nodes" && !nodes_done) {
  10.559              if (_nodes_caption.empty() || _nodes_caption == caption) {
  10.560 @@ -1977,22 +1994,23 @@
  10.561              readLine();
  10.562              skipSection();
  10.563            }
  10.564 -        } catch (DataFormatError& error) {
  10.565 +        } catch (FormatError& error) {
  10.566            error.line(line_num);
  10.567 +          error.file(_filename);
  10.568            throw;
  10.569          }
  10.570        }
  10.571  
  10.572        if (!nodes_done) {
  10.573 -        throw DataFormatError("Section @nodes not found");
  10.574 +        throw FormatError("Section @nodes not found");
  10.575        }
  10.576  
  10.577        if (!edges_done) {
  10.578 -        throw DataFormatError("Section @edges not found");
  10.579 +        throw FormatError("Section @edges not found");
  10.580        }
  10.581  
  10.582        if (!attributes_done && !_attributes.empty()) {
  10.583 -        throw DataFormatError("Section @attributes not found");
  10.584 +        throw FormatError("Section @attributes not found");
  10.585        }
  10.586  
  10.587      }
  10.588 @@ -2054,6 +2072,7 @@
  10.589  
  10.590      std::istream* _is;
  10.591      bool local_is;
  10.592 +    std::string _filename;
  10.593  
  10.594      typedef std::map<std::string, _reader_bits::Section*> Sections;
  10.595      Sections _sections;
  10.596 @@ -2074,13 +2093,19 @@
  10.597      ///
  10.598      /// Construct a section reader, which reads from the given file.
  10.599      SectionReader(const std::string& fn)
  10.600 -      : _is(new std::ifstream(fn.c_str())), local_is(true) {}
  10.601 +      : _is(new std::ifstream(fn.c_str())), local_is(true),
  10.602 +        _filename(fn) {
  10.603 +      if (!(*_is)) throw IoError(fn, "Cannot open file");
  10.604 +    }
  10.605  
  10.606      /// \brief Constructor
  10.607      ///
  10.608      /// Construct a section reader, which reads from the given file.
  10.609      SectionReader(const char* fn)
  10.610 -      : _is(new std::ifstream(fn)), local_is(true) {}
  10.611 +      : _is(new std::ifstream(fn)), local_is(true),
  10.612 +        _filename(fn) {
  10.613 +      if (!(*_is)) throw IoError(fn, "Cannot open file");
  10.614 +    }
  10.615  
  10.616      /// \brief Destructor
  10.617      ~SectionReader() {
  10.618 @@ -2236,12 +2261,12 @@
  10.619            _reader_bits::readToken(line, caption);
  10.620  
  10.621            if (line >> c)
  10.622 -            throw DataFormatError("Extra character on the end of line");
  10.623 +            throw FormatError("Extra character on the end of line");
  10.624  
  10.625            if (extra_sections.find(section) != extra_sections.end()) {
  10.626              std::ostringstream msg;
  10.627              msg << "Multiple occurence of section " << section;
  10.628 -            throw DataFormatError(msg.str().c_str());
  10.629 +            throw FormatError(msg.str());
  10.630            }
  10.631            Sections::iterator it = _sections.find(section);
  10.632            if (it != _sections.end()) {
  10.633 @@ -2250,8 +2275,9 @@
  10.634            }
  10.635            readLine();
  10.636            skipSection();
  10.637 -        } catch (DataFormatError& error) {
  10.638 +        } catch (FormatError& error) {
  10.639            error.line(line_num);
  10.640 +          error.file(_filename);
  10.641            throw;
  10.642          }
  10.643        }
  10.644 @@ -2260,7 +2286,7 @@
  10.645          if (extra_sections.find(it->first) == extra_sections.end()) {
  10.646            std::ostringstream os;
  10.647            os << "Cannot find section: " << it->first;
  10.648 -          throw DataFormatError(os.str().c_str());
  10.649 +          throw FormatError(os.str());
  10.650          }
  10.651        }
  10.652      }
  10.653 @@ -2360,14 +2386,18 @@
  10.654      /// Construct an \e LGF contents reader, which reads from the given
  10.655      /// file.
  10.656      LgfContents(const std::string& fn)
  10.657 -      : _is(new std::ifstream(fn.c_str())), local_is(true) {}
  10.658 +      : _is(new std::ifstream(fn.c_str())), local_is(true) {
  10.659 +      if (!(*_is)) throw IoError(fn, "Cannot open file");
  10.660 +    }
  10.661  
  10.662      /// \brief Constructor
  10.663      ///
  10.664      /// Construct an \e LGF contents reader, which reads from the given
  10.665      /// file.
  10.666      LgfContents(const char* fn)
  10.667 -      : _is(new std::ifstream(fn)), local_is(true) {}
  10.668 +      : _is(new std::ifstream(fn)), local_is(true) {
  10.669 +      if (!(*_is)) throw IoError(fn, "Cannot open file");
  10.670 +    }
  10.671  
  10.672      /// \brief Destructor
  10.673      ~LgfContents() {
    11.1 --- a/lemon/lgf_writer.h	Sat Sep 27 14:33:28 2008 +0200
    11.2 +++ b/lemon/lgf_writer.h	Tue Sep 30 20:53:18 2008 +0200
    11.3 @@ -55,7 +55,7 @@
    11.4  
    11.5      template <typename T>
    11.6      bool operator<(const T&, const T&) {
    11.7 -      throw DataFormatError("Label map is not comparable");
    11.8 +      throw FormatError("Label map is not comparable");
    11.9      }
   11.10  
   11.11      template <typename _Map>
   11.12 @@ -203,7 +203,7 @@
   11.13          typename std::map<Value, std::string>::const_iterator it =
   11.14            _map.find(str);
   11.15          if (it == _map.end()) {
   11.16 -          throw DataFormatError("Item not found");
   11.17 +          throw FormatError("Item not found");
   11.18          }
   11.19          return it->second;
   11.20        }
   11.21 @@ -223,7 +223,7 @@
   11.22          typename std::map<typename Graph::Edge, std::string>
   11.23            ::const_iterator it = _map.find(val);
   11.24          if (it == _map.end()) {
   11.25 -          throw DataFormatError("Item not found");
   11.26 +          throw FormatError("Item not found");
   11.27          }
   11.28          return (_graph.direction(val) ? '+' : '-') + it->second;
   11.29        }
   11.30 @@ -462,7 +462,9 @@
   11.31      /// output file.
   11.32      DigraphWriter(const std::string& fn, const Digraph& digraph)
   11.33        : _os(new std::ofstream(fn.c_str())), local_os(true), _digraph(digraph),
   11.34 -        _skip_nodes(false), _skip_arcs(false) {}
   11.35 +        _skip_nodes(false), _skip_arcs(false) {
   11.36 +      if (!(*_os)) throw IoError(fn, "Cannot write file");
   11.37 +    }
   11.38  
   11.39      /// \brief Constructor
   11.40      ///
   11.41 @@ -470,7 +472,9 @@
   11.42      /// output file.
   11.43      DigraphWriter(const char* fn, const Digraph& digraph)
   11.44        : _os(new std::ofstream(fn)), local_os(true), _digraph(digraph),
   11.45 -        _skip_nodes(false), _skip_arcs(false) {}
   11.46 +        _skip_nodes(false), _skip_arcs(false) {
   11.47 +      if (!(*_os)) throw IoError(fn, "Cannot write file");
   11.48 +    }
   11.49  
   11.50      /// \brief Destructor
   11.51      ~DigraphWriter() {
   11.52 @@ -1018,7 +1022,9 @@
   11.53      /// output file.
   11.54      GraphWriter(const std::string& fn, const Graph& graph)
   11.55        : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
   11.56 -        _skip_nodes(false), _skip_edges(false) {}
   11.57 +        _skip_nodes(false), _skip_edges(false) {
   11.58 +      if (!(*_os)) throw IoError(fn, "Cannot write file");
   11.59 +    }
   11.60  
   11.61      /// \brief Constructor
   11.62      ///
   11.63 @@ -1026,7 +1032,9 @@
   11.64      /// output file.
   11.65      GraphWriter(const char* fn, const Graph& graph)
   11.66        : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
   11.67 -        _skip_nodes(false), _skip_edges(false) {}
   11.68 +        _skip_nodes(false), _skip_edges(false) {
   11.69 +      if (!(*_os)) throw IoError(fn, "Cannot write file");
   11.70 +    }
   11.71  
   11.72      /// \brief Destructor
   11.73      ~GraphWriter() {
   11.74 @@ -1576,13 +1584,17 @@
   11.75      ///
   11.76      /// Construct a section writer, which writes into the given file.
   11.77      SectionWriter(const std::string& fn)
   11.78 -      : _os(new std::ofstream(fn.c_str())), local_os(true) {}
   11.79 +      : _os(new std::ofstream(fn.c_str())), local_os(true) {
   11.80 +      if (!(*_os)) throw IoError(fn, "Cannot write file");
   11.81 +    }
   11.82  
   11.83      /// \brief Constructor
   11.84      ///
   11.85      /// Construct a section writer, which writes into the given file.
   11.86      SectionWriter(const char* fn)
   11.87 -      : _os(new std::ofstream(fn)), local_os(true) {}
   11.88 +      : _os(new std::ofstream(fn)), local_os(true) {
   11.89 +      if (!(*_os)) throw IoError(fn, "Cannot write file");
   11.90 +    }
   11.91  
   11.92      /// \brief Destructor
   11.93      ~SectionWriter() {