COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/lemon/error.h @ 1139:f59038affc7e

Last change on this file since 1139:f59038affc7e was 1125:377e240b050f, checked in by Alpar Juttner, 16 years ago

A new exception class called UninitializedParameter?.

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