COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/lemon/error.h @ 1138:f68cb8752d81

Last change on this file since 1138:f68cb8752d81 was 1125:377e240b050f, checked in by Alpar Juttner, 19 years ago

A new exception class called UninitializedParameter?.

File size: 9.3 KB
RevLine 
[906]1/* -*- C++ -*-
[921]2 * src/lemon/error.h - Part of LEMON, a generic C++ optimization library
[906]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 */
[883]16
[921]17#ifndef LEMON_ERROR_H
18#define LEMON_ERROR_H
[883]19
20//! \ingroup misc
21//! \file
[1067]22//! \brief Basic exception classes and error handling.
[883]23
24#include <exception>
25#include <string>
26#include <sstream>
[1067]27#include <iostream>
28#include <cstdlib>
[883]29
[1056]30#include <boost/shared_ptr.hpp>
[883]31
[921]32namespace lemon {
[883]33
[1056]34  /// Exception-safe convenient "error message" class.
[1067]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).
[1056]39  class ErrorMessage {
40  protected:
[1067]41    ///\e
[1056]42    boost::shared_ptr<std::ostringstream> buf;
43   
[1067]44    ///\e
[1056]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
[1067]57    ///\e
[1056]58    ErrorMessage() throw() { init(); }
59
[1067]60    ///\e
[1056]61    ErrorMessage(const char *message) throw() {
62      init();
63      *this << message;
64    }
65
[1067]66    ///\e
[1056]67    ErrorMessage(const std::string &message) throw() {
68      init();
69      *this << message;
70    }
71
[1067]72    ///\e
[1056]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
[1067]85    ///\e
[1056]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
[883]99  /**
100   * \brief Generic exception class.
101   *
[1056]102   * Base class for exceptions used in LEMON.
[883]103   */
[1067]104  class Exception : public std::exception {
[883]105  public:
[1067]106    ///\e
[1120]107    Exception() {}
[1067]108    ///\e
[883]109    virtual ~Exception() throw() {}
[1120]110
111    ///\e
112    virtual const char* exceptionName() const {
113      return "lemon::Exception";
114    }
[883]115   
[1067]116    ///\e
[883]117    virtual const char* what() const throw() {
[1120]118      return exceptionName();
[1056]119    }
120  };
121
[1120]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   *
[1125]129   * A typical example for this is \ref UninitializedParameter.
[1120]130   */
[1056]131  class LogicError : public Exception {
[1067]132  public:
[1120]133    virtual const char* exceptionName() const {
134      return "lemon::LogicError";
135    }
[1056]136  };
137
[1125]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
[1120]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   */
[1056]159  class RuntimeError : public Exception {
[1067]160  public:
[1120]161    virtual const char* exceptionName() const {
162      return "lemon::RuntimeError";
163    }
[1056]164  };
165
[1067]166  ///\e
[1056]167  class RangeError : public RuntimeError {
[1067]168  public:
[1120]169    virtual const char* exceptionName() const {
170      return "lemon::RangeError";
171    }
[1056]172  };
173
[1061]174  ///\e
[1056]175  class IOError : public RuntimeError {
[1067]176  public:
[1120]177    virtual const char* exceptionName() const {
178      return "lemon::IOError";
179    }
[1056]180  };
181
[1061]182  ///\e
[1056]183  class DataFormatError : public IOError {
[1067]184  protected:
[1120]185    const char *_message;
186    int _line;
187    boost::shared_ptr<std::string> _file;
[1067]188
189  public:
190    ///\e
[1120]191    explicit DataFormatError(const char *the_message)
192      : _message(the_message), _line(0) {}
[1067]193    ///\e
[1056]194    DataFormatError(const std::string &file_name, int line_num,
[1120]195                    const char *the_message)
196      : _message(the_message), _line(line_num) { file(file_name); }
[1056]197
[1067]198    ///\e
[1120]199    void line(int line_num) { _line=line_num; }
[1067]200    ///\e
[1120]201    void message(char *the_message) { _message=the_message; }
202    ///\e
203    void file(const std::string &file_name) {
[1056]204      try {
[1120]205        _file.reset(new std::string);
206        *_file = file_name;
[1056]207      }
208      catch(...) {
[1120]209        _file.reset();
[1056]210      }
[883]211    }
212
[1067]213    ///\e
[1120]214    int line() const { return _line; }
215    ///\e
216    const char* message() const { return _message; }
[1067]217
218    /// \brief Returns the filename.
219    ///
[1068]220    /// Returns \e "(unknown)" if the filename was not specified.
[1120]221    const char* file() const {
222      if( _file )
223        return _file->c_str();
[1067]224      else
225        return "(unknown)";
226    }
227
228    ///\e
229    virtual const char* what() const throw() {
[1056]230      const char *mes = 0;
231      try {
232        std::ostringstream ostr;
[1120]233        ostr << _message;
234        if( _file || _line ) {
[1056]235          ostr << " (";
[1120]236          if( _file ) ostr << "in file '" << *_file << "'";
237          if( _file && _line ) ostr << " ";
238          if( _line ) ostr << "at line " << _line;
[1067]239          ostr << ")";
[1056]240        }
241        mes = ostr.str().c_str();
242      }
243      catch(...) {}
244      if( mes ) return mes;
[1120]245      return exceptionName();
246    }
247
248    virtual const char* exceptionName() const {
[1056]249      return "lemon::DataFormatError";
250    }
[1067]251
252    virtual ~DataFormatError() throw() {}
[883]253  };
254
[1056]255
[1068]256  ///\e
[1067]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;
[1120]297      return exceptionName();
298    }
299
300    virtual const char* exceptionName() const {
[1067]301      return "lemon::AssertionFailedError";
302    }
303
304    virtual ~AssertionFailedError() throw() {}
305  };
306
[1056]307
308  /****************  Macros  ****************/
309
310
[1067]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  }
[1056]327
[1067]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  }
[1056]335
[883]336
337}
[921]338#endif // LEMON_ERROR_H
[1067]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
[1120]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
[1067]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 *
[1120]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 *
[1067]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
[1120]386#endif // NDEBUG || LEMON_DISABLE_ASSERTS
[1067]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.