COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/lemon/error.h @ 1122:3ce7fc516cca

Last change on this file since 1122:3ce7fc516cca was 1122:3ce7fc516cca, checked in by Mihaly Barasz, 16 years ago

New error.h moved to lemon/

File size: 8.9 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   * For a typical example \see UninitializedParameterError.
130   */
131  class LogicError : public Exception {
132  public:
133    virtual const char* exceptionName() const {
134      return "lemon::LogicError";
135    }
136  };
137
138 
139  /**
140   * \brief One of the two main subclasses of \ref Exception.
141   *
142   * Runtime errors represent problems outside the scope of a program;
143   * they cannot be easily predicted and can generally only be caught as
144   * the program executes.
145   */
146  class RuntimeError : public Exception {
147  public:
148    virtual const char* exceptionName() const {
149      return "lemon::RuntimeError";
150    }
151  };
152
153  ///\e
154  class RangeError : public RuntimeError {
155  public:
156    virtual const char* exceptionName() const {
157      return "lemon::RangeError";
158    }
159  };
160
161  ///\e
162  class IOError : public RuntimeError {
163  public:
164    virtual const char* exceptionName() const {
165      return "lemon::IOError";
166    }
167  };
168
169  ///\e
170  class DataFormatError : public IOError {
171  protected:
172    const char *_message;
173    int _line;
174    boost::shared_ptr<std::string> _file;
175
176  public:
177    ///\e
178    explicit DataFormatError(const char *the_message)
179      : _message(the_message), _line(0) {}
180    ///\e
181    DataFormatError(const std::string &file_name, int line_num,
182                    const char *the_message)
183      : _message(the_message), _line(line_num) { file(file_name); }
184
185    ///\e
186    void line(int line_num) { _line=line_num; }
187    ///\e
188    void message(char *the_message) { _message=the_message; }
189    ///\e
190    void file(const std::string &file_name) {
191      try {
192        _file.reset(new std::string);
193        *_file = file_name;
194      }
195      catch(...) {
196        _file.reset();
197      }
198    }
199
200    ///\e
201    int line() const { return _line; }
202    ///\e
203    const char* message() const { return _message; }
204
205    /// \brief Returns the filename.
206    ///
207    /// Returns \e "(unknown)" if the filename was not specified.
208    const char* file() const {
209      if( _file )
210        return _file->c_str();
211      else
212        return "(unknown)";
213    }
214
215    ///\e
216    virtual const char* what() const throw() {
217      const char *mes = 0;
218      try {
219        std::ostringstream ostr;
220        ostr << _message;
221        if( _file || _line ) {
222          ostr << " (";
223          if( _file ) ostr << "in file '" << *_file << "'";
224          if( _file && _line ) ostr << " ";
225          if( _line ) ostr << "at line " << _line;
226          ostr << ")";
227        }
228        mes = ostr.str().c_str();
229      }
230      catch(...) {}
231      if( mes ) return mes;
232      return exceptionName();
233    }
234
235    virtual const char* exceptionName() const {
236      return "lemon::DataFormatError";
237    }
238
239    virtual ~DataFormatError() throw() {}
240  };
241
242
243  ///\e
244  class AssertionFailedError : public LogicError {
245  protected:
246    const char *assertion;
247    const char *file;
248    int line;
249    const char *function;
250    const char *message;
251  public:
252    ///\e
253    AssertionFailedError(const char *_file, int _line, const char *func,
254                         const char *msg, const char *_assertion = 0) :
255      assertion(_assertion), file(_file), line(_line), function(func),
256      message(msg) {}
257
258    ///\e
259    const char* get_assertion() const { return assertion; }
260    ///\e
261    const char* get_message() const { return message; }
262    ///\e
263    const char* get_file() const { return file; }
264    ///\e
265    const char* get_function() const { return function; }
266    ///\e
267    int get_line() const { return line; }
268
269
270    virtual const char* what() const throw() {
271      const char *mes = 0;
272      try {
273        std::ostringstream ostr;
274        ostr << file << ":" << line << ": ";
275        if( function )
276          ostr << function << ": ";
277        ostr << message;
278        if( assertion )
279          ostr << " (assertion '" << assertion << "' failed)";
280        mes = ostr.str().c_str();
281      }
282      catch(...) {}
283      if( mes ) return mes;
284      return exceptionName();
285    }
286
287    virtual const char* exceptionName() const {
288      return "lemon::AssertionFailedError";
289    }
290
291    virtual ~AssertionFailedError() throw() {}
292  };
293
294
295  /****************  Macros  ****************/
296
297
298  inline
299  void assert_fail(const char *file, int line, const char *func,
300                   const char *message, const char *assertion = 0,
301                   bool do_abort=true)
302  {
303    using namespace std;
304    cerr << file << ":" << line << ": ";
305    if( func )
306      cerr << func << ": ";
307    cerr << message;
308    if( assertion )
309      cerr << " (assertion '" << assertion << "' failed)";
310    cerr << endl;
311    if(do_abort)
312      abort();
313  }
314
315  inline
316  void assert_fail_throw(const char *file, int line, const char *func,
317                   const char *message, const char *assertion = 0,
318                   bool = true)
319  {
320    throw AssertionFailedError(file, line, func, message, assertion);
321  }
322
323
324}
325#endif // LEMON_ERROR_H
326
327#undef LEMON_ASSERT
328#undef LEMON_FIXME
329
330#ifndef LEMON_ASSERT_ABORT
331#  define LEMON_ASSERT_ABORT 1
332#endif
333
334#ifndef LEMON_ASSERT_HANDLER
335#  ifdef LEMON_ASSERT_EXCEPTION
336#    define LEMON_ASSERT_HANDLER ::lemon::assert_fail_throw
337#  else
338#    define LEMON_ASSERT_HANDLER ::lemon::assert_fail
339#  endif
340#endif
341
342#if defined(NDEBUG) || defined(LEMON_DISABLE_ASSERTS)
343
344#  define LEMON_ASSERT(exp, msg)  (static_cast<void> (0))
345
346#else
347
348/**
349 * \brief Macro for assertions with customizable message
350 *
351 * Macro for assertions with customizable message.
352 *
353 * The behaviour can be customized with LEMON_ASSERT_HANDLER,
354 * LEMON_ASSERT_EXCEPTION and LEMON_ASSERT_ABORT defines. Asserts can be
355 * disabled by defining either NDEBUG or LEMON_DISABLE_ASSERTS macros.
356 *
357 * \todo We should provide some way to reset to the default behaviour,
358 * shouldn't we?
359 *
360 * \todo This whole 'assert' business should be placed in a separate
361 * include file.
362 *
363 * \todo __PRETTY_FUNCTION__ should be replaced by something
364 * compiler-independant, like BOOST_CURRENT_FUNCTION
365 */
366
367#  define LEMON_ASSERT(exp, msg)                 \
368     (static_cast<void> (!!(exp) ? 0 : (         \
369       LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \
370                            __PRETTY_FUNCTION__, \
371                            (msg), #exp, LEMON_ASSERT_ABORT), 0)))
372
373#endif // NDEBUG || LEMON_DISABLE_ASSERTS
374
375/**
376 * \brief Macro for mark not yet implemented features.
377 *
378 * \todo Is this the right place for this? It should be used only in
379 * modules under development.
380 *
381 * \todo __PRETTY_FUNCTION__ should be replaced by something
382 * compiler-independant, like BOOST_CURRENT_FUNCTION
383 */
384
385# define LEMON_FIXME(msg) \
386    (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, __PRETTY_FUNCTION__, \
387                          "FIXME: " msg))
Note: See TracBrowser for help on using the repository browser.