COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/work/klao/error.h @ 1067:47939f501c81

Last change on this file since 1067:47939f501c81 was 1067:47939f501c81, checked in by Mihaly Barasz, 15 years ago

Advances in error.h

  • More clear exception usage concept
  • sketch of LEMON_ASSERT interface
  • test file
File size: 7.6 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  protected:
106    ///\e
107    const char *message;
108
109  public:
110    ///\e
111    Exception() throw() : message(0) {}
112    ///\e
113    explicit Exception(const char *msg) throw()
114      : message(msg) {}
115    ///\e
116    virtual ~Exception() throw() {}
117   
118    ///\e
119    virtual const char* what() const throw() {
120      if( message ) return message;
121      return "lemon::Exception";
122    }
123  };
124
125  ///\e
126  class LogicError : public Exception {
127  public:
128    ///\e
129    explicit LogicError() {}
130    ///\e
131    explicit LogicError(const char *s)
132      : Exception(s) {}
133  };
134
135  ///\e
136  class RuntimeError : public Exception {
137  public:
138    ///\e
139    explicit RuntimeError() {}
140    ///\e
141    explicit RuntimeError(const char *s)
142      : Exception(s) {}
143  };
144
145  ///\e
146  class RangeError : public RuntimeError {
147  public:
148    ///\e
149    explicit RangeError(const char *s)
150      : RuntimeError(s) {}
151  };
152
153  ///\e
154  class IOError : public RuntimeError {
155  public:
156    ///\e
157    explicit IOError(const char *s)
158      : RuntimeError(s) {}
159  };
160
161  ///\e
162  class DataFormatError : public IOError {
163  protected:
164    int line;
165    boost::shared_ptr<std::string> file;
166
167  public:
168    ///\e
169    explicit DataFormatError(const char *message)
170      : IOError(message), line(0) {}
171    ///\e
172    DataFormatError(const std::string &file_name, int line_num,
173                    const char *message)
174      : IOError(message), line(line_num) { set_file(file_name); }
175
176    ///\e
177    void set_line(int line_num) { line=line_num; }
178    ///\e
179    void set_file(const std::string &file_name) {
180      try {
181        file.reset(new std::string);
182        *file = file_name;
183      }
184      catch(...) {
185        file.reset();
186      }
187    }
188
189    ///\e
190    int get_line() const { return line; }
191
192    /// \brief Returns the filename.
193    ///
194    /// Returns "(unknown)" if the filename was not specified.
195    const char* get_file() const {
196      if( file )
197        return file->c_str();
198      else
199        return "(unknown)";
200    }
201
202    ///\e
203    virtual const char* what() const throw() {
204      const char *mes = 0;
205      try {
206        std::ostringstream ostr;
207        ostr << IOError::what();
208        if( file || line ) {
209          ostr << " (";
210          if( file ) ostr << "in file '" << *file << "'";
211          if( file && line ) ostr << " ";
212          if( line ) ostr << "at line " << line;
213          ostr << ")";
214        }
215        mes = ostr.str().c_str();
216      }
217      catch(...) {}
218      if( mes ) return mes;
219      return "lemon::DataFormatError";
220    }
221
222    virtual ~DataFormatError() throw() {}
223  };
224
225
226  class AssertionFailedError : public LogicError {
227  protected:
228    const char *assertion;
229    const char *file;
230    int line;
231    const char *function;
232    const char *message;
233  public:
234    ///\e
235    AssertionFailedError(const char *_file, int _line, const char *func,
236                         const char *msg, const char *_assertion = 0) :
237      assertion(_assertion), file(_file), line(_line), function(func),
238      message(msg) {}
239
240    ///\e
241    const char* get_assertion() const { return assertion; }
242    ///\e
243    const char* get_message() const { return message; }
244    ///\e
245    const char* get_file() const { return file; }
246    ///\e
247    const char* get_function() const { return function; }
248    ///\e
249    int get_line() const { return line; }
250
251
252    virtual const char* what() const throw() {
253      const char *mes = 0;
254      try {
255        std::ostringstream ostr;
256        ostr << file << ":" << line << ": ";
257        if( function )
258          ostr << function << ": ";
259        ostr << message;
260        if( assertion )
261          ostr << " (assertion '" << assertion << "' failed)";
262        mes = ostr.str().c_str();
263      }
264      catch(...) {}
265      if( mes ) return mes;
266      return "lemon::AssertionFailedError";
267    }
268
269    virtual ~AssertionFailedError() throw() {}
270  };
271
272
273  /****************  Macros  ****************/
274
275
276  inline
277  void assert_fail(const char *file, int line, const char *func,
278                   const char *message, const char *assertion = 0,
279                   bool do_abort=true)
280  {
281    using namespace std;
282    cerr << file << ":" << line << ": ";
283    if( func )
284      cerr << func << ": ";
285    cerr << message;
286    if( assertion )
287      cerr << " (assertion '" << assertion << "' failed)";
288    cerr << endl;
289    if(do_abort)
290      abort();
291  }
292
293  inline
294  void assert_fail_throw(const char *file, int line, const char *func,
295                   const char *message, const char *assertion = 0,
296                   bool = true)
297  {
298    throw AssertionFailedError(file, line, func, message, assertion);
299  }
300
301
302}
303#endif // LEMON_ERROR_H
304
305#undef LEMON_ASSERT
306#undef LEMON_FIXME
307
308#ifndef LEMON_ASSERT_ABORT
309#  define LEMON_ASSERT_ABORT 1
310#endif
311
312#ifndef LEMON_ASSERT_HANDLER
313#  define LEMON_ASSERT_HANDLER ::lemon::assert_fail
314#endif
315
316#if defined(NDEBUG) || defined(LEMON_DISABLE_ASSERTS)
317
318#  define LEMON_ASSERT(exp, msg)  (static_cast<void> (0))
319
320#else
321
322/**
323 * \brief Macro for assertions with customizable message
324 *
325 * \todo __PRETTY_FUNCTION__ should be replaced by something
326 * compiler-independant, like BOOST_CURRENT_FUNCTION
327 */
328
329#  define LEMON_ASSERT(exp, msg)                 \
330     (static_cast<void> (!!(exp) ? 0 : (         \
331       LEMON_ASSERT_HANDLER(__FILE__, __LINE__,  \
332                            __PRETTY_FUNCTION__, \
333                            (msg), #exp, LEMON_ASSERT_ABORT), 0)))
334
335# endif // NDEBUG
336
337/**
338 * \brief Macro for mark not yet implemented features.
339 *
340 * \todo Is this the right place for this? It should be used only in
341 * modules under development.
342 *
343 * \todo __PRETTY_FUNCTION__ should be replaced by something
344 * compiler-independant, like BOOST_CURRENT_FUNCTION
345 */
346
347# define LEMON_FIXME(msg) \
348    (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, __PRETTY_FUNCTION__, \
349                          "FIXME: " msg))
Note: See TracBrowser for help on using the repository browser.