COIN-OR::LEMON - Graph Library

source: lemon-1.0/lemon/error.h @ 142:8b703d177341

Last change on this file since 142:8b703d177341 was 108:889d0c289d19, checked in by Balazs Dezso <deba@…>, 16 years ago

Reworking assertions and moving to distinict file

File size: 9.5 KB
Line 
1/* -*- C++ -*-
2 *
3 * This file is a part of LEMON, a generic C++ optimization library
4 *
5 * Copyright (C) 2003-2008
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 *
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
12 *
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
15 * purpose.
16 *
17 */
18
19#ifndef LEMON_ERROR_H
20#define LEMON_ERROR_H
21
22/// \ingroup exceptions
23/// \file
24/// \brief Basic exception classes and error handling.
25
26#include <exception>
27#include <string>
28#include <sstream>
29#include <iostream>
30#include <cstdlib>
31#include <memory>
32
33namespace lemon {
34
35  /// \addtogroup exceptions
36  /// @{
37
38  /// \brief Exception safe wrapper class.
39  ///
40  /// Exception safe wrapper class to implement the members of exceptions.
41  template <typename _Type>
42  class ExceptionMember {
43  public:
44    typedef _Type Type;
45
46    ExceptionMember() throw() {
47      try {
48        ptr.reset(new Type());
49      } catch (...) {}
50    }
51
52    ExceptionMember(const Type& type) throw() {
53      try {
54        ptr.reset(new Type());
55        if (ptr.get() == 0) return;
56        *ptr = type;
57      } catch (...) {}
58    }
59
60    ExceptionMember(const ExceptionMember& copy) throw() {
61      try {
62        if (!copy.valid()) return;
63        ptr.reset(new Type());
64        if (ptr.get() == 0) return;
65        *ptr = copy.get();
66      } catch (...) {}
67    }
68
69    ExceptionMember& operator=(const ExceptionMember& copy) throw() {
70      if (ptr.get() == 0) return;
71      try {
72        if (!copy.valid()) return;
73        *ptr = copy.get();
74      } catch (...) {}
75    }
76
77    void set(const Type& type) throw() {
78      if (ptr.get() == 0) return;
79      try {
80        *ptr = type;
81      } catch (...) {}
82    }
83
84    const Type& get() const {
85      return *ptr;
86    }
87
88    bool valid() const throw() {
89      return ptr.get() != 0;
90    }
91
92  private:
93    std::auto_ptr<_Type> ptr;
94  };
95
96  /// Exception-safe convenient error message builder class.
97
98  /// Helper class which provides a convenient ostream-like (operator <<
99  /// based) interface to create a string message. Mostly useful in
100  /// exception classes (therefore the name).
101  class ErrorMessage {
102  protected:
103    ///\e
104
105    ///\todo The good solution is boost::shared_ptr...
106    ///
107    mutable std::auto_ptr<std::ostringstream> buf;
108
109    ///\e
110    bool init() throw() {
111      try {
112        buf.reset(new std::ostringstream);
113      }
114      catch(...) {
115        buf.reset();
116      }
117      return buf.get();
118    }
119
120  public:
121
122    ///\e
123    ErrorMessage() throw() { init(); }
124
125    ErrorMessage(const ErrorMessage& em) throw() : buf(em.buf) { }
126
127    ///\e
128    ErrorMessage(const char *msg) throw() {
129      init();
130      *this << msg;
131    }
132
133    ///\e
134    ErrorMessage(const std::string &msg) throw() {
135      init();
136      *this << msg;
137    }
138
139    ///\e
140    template <typename T>
141    ErrorMessage& operator<<(const T &t) throw() {
142      if( ! buf.get() ) return *this;
143
144      try {
145        *buf << t;
146      }
147      catch(...) {
148        buf.reset();
149      }
150      return *this;
151    }
152
153    ///\e
154    const char* message() throw() {
155      if( ! buf.get() ) return 0;
156
157      const char* mes = 0;
158      try {
159        mes = buf->str().c_str();
160      }
161      catch(...) {}
162      return mes;
163    }
164
165  };
166
167  /// Generic exception class.
168
169  /// Base class for exceptions used in LEMON.
170  ///
171  class Exception : public std::exception {
172  public:
173    ///\e
174    Exception() {}
175    ///\e
176    virtual ~Exception() throw() {}
177    ///\e
178    virtual const char* what() const throw() {
179      return "lemon::Exception";
180    }
181  };
182
183  /// One of the two main subclasses of \ref Exception.
184
185  /// Logic errors represent problems in the internal logic of a program;
186  /// in theory, these are preventable, and even detectable before the
187  /// program runs (e.g. violations of class invariants).
188  ///
189  /// A typical example for this is \ref UninitializedParameter.
190  class LogicError : public Exception {
191  public:
192    virtual const char* what() const throw() {
193      return "lemon::LogicError";
194    }
195  };
196
197  /// \ref Exception for uninitialized parameters.
198
199  /// This error represents problems in the initialization
200  /// of the parameters of the algorithms.
201  class UninitializedParameter : public LogicError {
202  public:
203    virtual const char* what() const throw() {
204      return "lemon::UninitializedParameter";
205    }
206  };
207
208
209  /// One of the two main subclasses of \ref Exception.
210
211  /// Runtime errors represent problems outside the scope of a program;
212  /// they cannot be easily predicted and can generally only be caught
213  /// as the program executes.
214  class RuntimeError : public Exception {
215  public:
216    virtual const char* what() const throw() {
217      return "lemon::RuntimeError";
218    }
219  };
220
221  ///\e
222  class RangeError : public RuntimeError {
223  public:
224    virtual const char* what() const throw() {
225      return "lemon::RangeError";
226    }
227  };
228
229  ///\e
230  class IoError : public RuntimeError {
231  public:
232    virtual const char* what() const throw() {
233      return "lemon::IoError";
234    }
235  };
236
237  ///\e
238  class DataFormatError : public IoError {
239  protected:
240    ExceptionMember<std::string> _message;
241    ExceptionMember<std::string> _file;
242    int _line;
243
244    mutable ExceptionMember<std::string> _message_holder;
245  public:
246
247    DataFormatError(const DataFormatError &dfe) :
248      IoError(dfe), _message(dfe._message), _file(dfe._file),
249      _line(dfe._line) {}
250
251    ///\e
252    explicit DataFormatError(const char *the_message)
253      : _message(the_message), _line(0) {}
254
255    ///\e
256    DataFormatError(const std::string &file_name, int line_num,
257                    const char *the_message)
258      : _message(the_message), _line(line_num) { file(file_name); }
259
260    ///\e
261    void line(int ln) { _line = ln; }
262    ///\e
263    void message(const std::string& msg) { _message.set(msg); }
264    ///\e
265    void file(const std::string &fl) { _file.set(fl); }
266
267    ///\e
268    int line() const { return _line; }
269    ///\e
270    const char* message() const {
271      if (_message.valid() && !_message.get().empty()) {
272        return _message.get().c_str();
273      } else {
274        return 0;
275      }
276    }
277
278    /// \brief Returns the filename.
279    ///
280    /// Returns \e null if the filename was not specified.
281    const char* file() const {
282      if (_file.valid() && !_file.get().empty()) {
283        return _file.get().c_str();
284      } else {
285        return 0;
286      }
287    }
288
289    ///\e
290    virtual const char* what() const throw() {
291      try {
292        std::ostringstream ostr;
293        ostr << "lemon:DataFormatError" << ": ";
294        if (message()) ostr << message();
295        if( file() || line() != 0 ) {
296          ostr << " (";
297          if( file() ) ostr << "in file '" << file() << "'";
298          if( file() && line() != 0 ) ostr << " ";
299          if( line() != 0 ) ostr << "at line " << line();
300          ostr << ")";
301        }
302        _message_holder.set(ostr.str());
303      }
304      catch (...) {}
305      if( _message_holder.valid()) return _message_holder.get().c_str();
306      return "lemon:DataFormatError";
307    }
308
309    virtual ~DataFormatError() throw() {}
310  };
311
312  ///\e
313  class FileOpenError : public IoError {
314  protected:
315    ExceptionMember<std::string> _file;
316
317    mutable ExceptionMember<std::string> _message_holder;
318  public:
319
320    FileOpenError(const FileOpenError &foe) :
321      IoError(foe), _file(foe._file) {}
322
323    ///\e
324    explicit FileOpenError(const std::string& fl)
325      : _file(fl) {}
326
327
328    ///\e
329    void file(const std::string &fl) { _file.set(fl); }
330
331    /// \brief Returns the filename.
332    ///
333    /// Returns \e null if the filename was not specified.
334    const char* file() const {
335      if (_file.valid() && !_file.get().empty()) {
336        return _file.get().c_str();
337      } else {
338        return 0;
339      }
340    }
341
342    ///\e
343    virtual const char* what() const throw() {
344      try {
345        std::ostringstream ostr;
346        ostr << "lemon::FileOpenError" << ": ";
347        ostr << "Cannot open file - " << file();
348        _message_holder.set(ostr.str());
349      }
350      catch (...) {}
351      if( _message_holder.valid()) return _message_holder.get().c_str();
352      return "lemon::FileOpenError";
353    }
354    virtual ~FileOpenError() throw() {}
355  };
356
357  class IoParameterError : public IoError {
358  protected:
359    ExceptionMember<std::string> _message;
360    ExceptionMember<std::string> _file;
361
362    mutable ExceptionMember<std::string> _message_holder;
363  public:
364
365    IoParameterError(const IoParameterError &ile) :
366      IoError(ile), _message(ile._message), _file(ile._file) {}
367
368    ///\e
369    explicit IoParameterError(const char *the_message)
370      : _message(the_message) {}
371
372    ///\e
373    IoParameterError(const char *file_name, const char *the_message)
374      : _message(the_message), _file(file_name) {}
375
376     ///\e
377    void message(const std::string& msg) { _message.set(msg); }
378    ///\e
379    void file(const std::string &fl) { _file.set(fl); }
380
381     ///\e
382    const char* message() const {
383      if (_message.valid()) {
384        return _message.get().c_str();
385      } else {
386        return 0;
387      }
388    }
389
390    /// \brief Returns the filename.
391    ///
392    /// Returns \c 0 if the filename was not specified.
393    const char* file() const {
394      if (_file.valid()) {
395        return _file.get().c_str();
396      } else {
397        return 0;
398      }
399    }
400
401    ///\e
402    virtual const char* what() const throw() {
403      try {
404        std::ostringstream ostr;
405        if (message()) ostr << message();
406        if (file()) ostr << "(when reading file '" << file() << "')";
407        _message_holder.set(ostr.str());
408      }
409      catch (...) {}
410      if( _message_holder.valid() ) return _message_holder.get().c_str();
411      return "lemon:IoParameterError";
412    }
413    virtual ~IoParameterError() throw() {}
414  };
415
416  /// @}
417
418}
419
420#endif // LEMON_ERROR_H
Note: See TracBrowser for help on using the repository browser.