COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/lemon/error.h @ 1151:b217fc69f913

Last change on this file since 1151:b217fc69f913 was 1151:b217fc69f913, checked in by Alpar Juttner, 16 years ago

Several changes in the docs.

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