COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/work/klao/error.h @ 1068:e0b0dcee5e17

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