COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/lemon/error.h @ 1163:eb4e28715baf

Last change on this file since 1163:eb4e28715baf was 1157:3996d2098090, checked in by Mihaly Barasz, 19 years ago

lemon/error.h: boost::shared_ptr helyett std::auto_ptr

(Sokkal kenylemetlenebb, es nem teljesen biztos, hogy helyes megoldas)

File size: 9.7 KB
Line 
1/* -*- C++ -*-
2 *
3 * src/lemon/error.h - Part of LEMON, a generic C++ optimization library
4 *
5 * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi
6 * Kutatocsoport (Egervary Combinatorial Optimization Research Group,
7 * 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  /// Exception-safe convenient "error message" class.
39
40  /// Helper class which provides a convenient ostream-like (operator <<
41  /// based) interface to create a string message. Mostly useful in
42  /// exception classes (therefore the name).
43  class ErrorMessage {
44  protected:
45    ///\e
46    ///\todo The good solution is boost:shared_ptr...
47    mutable
48    std::auto_ptr<std::ostringstream> buf;
49   
50    ///\e
51    bool init() throw() {
52      try {
53        buf.reset(new std::ostringstream);
54      }
55      catch(...) {
56        buf.reset();
57      }
58      return buf.get();
59    }
60
61  public:
62
63    ///\e
64    ErrorMessage() throw() { init(); }
65
66    ErrorMessage(const ErrorMessage& em) throw() : buf(em.buf) { }
67
68    ///\e
69    ErrorMessage(const char *message) throw() {
70      init();
71      *this << message;
72    }
73
74    ///\e
75    ErrorMessage(const std::string &message) throw() {
76      init();
77      *this << message;
78    }
79
80    ///\e
81    template <typename T>
82    ErrorMessage& operator<<(const T &t) throw() {
83      if( ! buf.get() ) return *this;
84
85      try {
86        *buf << t;
87      }
88      catch(...) {
89        buf.reset();
90      }
91    }
92
93    ///\e
94    const char* message() throw() {
95      if( ! buf.get() ) return 0;
96
97      const char* mes = 0;
98      try {
99        mes = buf->str().c_str();
100      }
101      catch(...) {}
102      return mes;
103    }
104   
105  };
106
107  /**
108   * \brief Generic exception class.
109   *
110   * Base class for exceptions used in LEMON.
111   */
112  class Exception : public std::exception {
113  public:
114    ///\e
115    Exception() {}
116    ///\e
117    virtual ~Exception() throw() {}
118
119    ///\e
120    virtual const char* exceptionName() const {
121      return "lemon::Exception";
122    }
123   
124    ///\e
125    virtual const char* what() const throw() {
126      return exceptionName();
127    }
128  };
129
130  /**
131   * \brief One of the two main subclasses of \ref Exception.
132   *
133   * Logic errors represent problems in the internal logic of a program;
134   * in theory, these are preventable, and even detectable before the
135   * program runs (e.g., violations of class invariants).
136   *
137   * A typical example for this is \ref UninitializedParameter.
138   */
139  class LogicError : public Exception {
140  public:
141    virtual const char* exceptionName() const {
142      return "lemon::LogicError";
143    }
144  };
145
146  /**
147   * \brief \ref Exception for uninitialized parameters.
148   *
149   * This error represents problems in the initialization
150   * of the parameters of the algorithms.
151   */
152  class UninitializedParameter : public LogicError {
153  public:
154    virtual const char* exceptionName() const {
155      return "lemon::UninitializedParameter";
156    }
157  };
158
159 
160  /**
161   * \brief One of the two main subclasses of \ref Exception.
162   *
163   * Runtime errors represent problems outside the scope of a program;
164   * they cannot be easily predicted and can generally only be caught as
165   * the program executes.
166   */
167  class RuntimeError : public Exception {
168  public:
169    virtual const char* exceptionName() const {
170      return "lemon::RuntimeError";
171    }
172  };
173
174  ///\e
175  class RangeError : public RuntimeError {
176  public:
177    virtual const char* exceptionName() const {
178      return "lemon::RangeError";
179    }
180  };
181
182  ///\e
183  class IOError : public RuntimeError {
184  public:
185    virtual const char* exceptionName() const {
186      return "lemon::IOError";
187    }
188  };
189
190  ///\e
191  class DataFormatError : public IOError {
192  protected:
193    const char *_message;
194    int _line;
195
196    ///\todo Much better solution is boost::shared_ptr
197    mutable
198    std::auto_ptr<std::string> _file;
199
200  public:
201
202    DataFormatError(const DataFormatError &dfe) :
203      IOError(dfe), _message(dfe._message), _line(dfe._line),
204      _file(dfe._file) {}
205
206    ///\e
207    explicit DataFormatError(const char *the_message)
208      : _message(the_message), _line(0) {}
209    ///\e
210    DataFormatError(const std::string &file_name, int line_num,
211                    const char *the_message)
212      : _message(the_message), _line(line_num) { file(file_name); }
213
214    ///\e
215    void line(int line_num) { _line=line_num; }
216    ///\e
217    void message(char *the_message) { _message=the_message; }
218    ///\e
219    void file(const std::string &file_name) {
220      try {
221        _file.reset(new std::string);
222        *_file = file_name;
223      }
224      catch(...) {
225        _file.reset();
226      }
227    }
228
229    ///\e
230    int line() const { return _line; }
231    ///\e
232    const char* message() const { return _message; }
233
234    /// \brief Returns the filename.
235    ///
236    /// Returns \e "(unknown)" if the filename was not specified.
237    const char* file() const {
238      if( _file.get() )
239        return _file->c_str();
240      else
241        return "(unknown)";
242    }
243
244    ///\e
245    virtual const char* what() const throw() {
246      const char *mes = 0;
247      try {
248        std::ostringstream ostr;
249        ostr << _message;
250        if( _file.get() || _line ) {
251          ostr << " (";
252          if( _file.get() ) ostr << "in file '" << *_file << "'";
253          if( _file.get() && _line ) ostr << " ";
254          if( _line ) ostr << "at line " << _line;
255          ostr << ")";
256        }
257        mes = ostr.str().c_str();
258      }
259      catch(...) {}
260      if( mes ) return mes;
261      return exceptionName();
262    }
263
264    virtual const char* exceptionName() const {
265      return "lemon::DataFormatError";
266    }
267
268    virtual ~DataFormatError() throw() {}
269  };
270
271
272  ///\e
273  class AssertionFailedError : public LogicError {
274  protected:
275    const char *assertion;
276    const char *file;
277    int line;
278    const char *function;
279    const char *message;
280  public:
281    ///\e
282    AssertionFailedError(const char *_file, int _line, const char *func,
283                         const char *msg, const char *_assertion = 0) :
284      assertion(_assertion), file(_file), line(_line), function(func),
285      message(msg) {}
286
287    ///\e
288    const char* get_assertion() const { return assertion; }
289    ///\e
290    const char* get_message() const { return message; }
291    ///\e
292    const char* get_file() const { return file; }
293    ///\e
294    const char* get_function() const { return function; }
295    ///\e
296    int get_line() const { return line; }
297
298
299    virtual const char* what() const throw() {
300      const char *mes = 0;
301      try {
302        std::ostringstream ostr;
303        ostr << file << ":" << line << ": ";
304        if( function )
305          ostr << function << ": ";
306        ostr << message;
307        if( assertion )
308          ostr << " (assertion '" << assertion << "' failed)";
309        mes = ostr.str().c_str();
310      }
311      catch(...) {}
312      if( mes ) return mes;
313      return exceptionName();
314    }
315
316    virtual const char* exceptionName() const {
317      return "lemon::AssertionFailedError";
318    }
319
320    virtual ~AssertionFailedError() throw() {}
321  };
322
323
324  /****************  Macros  ****************/
325
326
327  inline
328  void assert_fail(const char *file, int line, const char *func,
329                   const char *message, const char *assertion = 0,
330                   bool do_abort=true)
331  {
332    using namespace std;
333    cerr << file << ":" << line << ": ";
334    if( func )
335      cerr << func << ": ";
336    cerr << message;
337    if( assertion )
338      cerr << " (assertion '" << assertion << "' failed)";
339    cerr << endl;
340    if(do_abort)
341      abort();
342  }
343
344  inline
345  void assert_fail_throw(const char *file, int line, const char *func,
346                   const char *message, const char *assertion = 0,
347                   bool = true)
348  {
349    throw AssertionFailedError(file, line, func, message, assertion);
350  }
351
352/// @}
353
354}
355#endif // LEMON_ERROR_H
356
357#undef LEMON_ASSERT
358#undef LEMON_FIXME
359
360#ifndef LEMON_ASSERT_ABORT
361#  define LEMON_ASSERT_ABORT 1
362#endif
363
364#ifndef LEMON_ASSERT_HANDLER
365#  ifdef LEMON_ASSERT_EXCEPTION
366#    define LEMON_ASSERT_HANDLER ::lemon::assert_fail_throw
367#  else
368#    define LEMON_ASSERT_HANDLER ::lemon::assert_fail
369#  endif
370#endif
371
372#if defined(NDEBUG) || defined(LEMON_DISABLE_ASSERTS)
373
374#  define LEMON_ASSERT(exp, msg)  (static_cast<void> (0))
375
376#else
377
378/**
379 * \brief Macro for assertions with customizable message
380 *
381 * Macro for assertions with customizable message.
382 *
383 * The behaviour can be customized with LEMON_ASSERT_HANDLER,
384 * LEMON_ASSERT_EXCEPTION and LEMON_ASSERT_ABORT defines. Asserts can be
385 * disabled by defining either NDEBUG or LEMON_DISABLE_ASSERTS macros.
386 *
387 * \todo We should provide some way to reset to the default behaviour,
388 * shouldn't we?
389 *
390 * \todo This whole 'assert' business should be placed in a separate
391 * include file.
392 *
393 * \todo __PRETTY_FUNCTION__ should be replaced by something
394 * compiler-independant, like BOOST_CURRENT_FUNCTION
395 */
396
397#  define LEMON_ASSERT(exp, msg)                 \
398     (static_cast<void> (!!(exp) ? 0 : (         \
399       LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \
400                            __PRETTY_FUNCTION__, \
401                            (msg), #exp, LEMON_ASSERT_ABORT), 0)))
402
403#endif // NDEBUG || LEMON_DISABLE_ASSERTS
404
405/**
406 * \brief Macro for mark not yet implemented features.
407 *
408 * \todo Is this the right place for this? It should be used only in
409 * modules under development.
410 *
411 * \todo __PRETTY_FUNCTION__ should be replaced by something
412 * compiler-independant, like BOOST_CURRENT_FUNCTION
413 */
414
415# define LEMON_FIXME(msg) \
416    (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, __PRETTY_FUNCTION__, \
417                          "FIXME: " msg))
Note: See TracBrowser for help on using the repository browser.