00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef LEMON_ERROR_H
00020 #define LEMON_ERROR_H
00021
00025
00026 #include <exception>
00027 #include <string>
00028 #include <sstream>
00029 #include <iostream>
00030 #include <cstdlib>
00031 #include <memory>
00032
00033 namespace lemon {
00034
00037
00039
00043 class ErrorMessage {
00044 protected:
00047 mutable
00048 std::auto_ptr<std::ostringstream> buf;
00049
00051 bool init() throw() {
00052 try {
00053 buf.reset(new std::ostringstream);
00054 }
00055 catch(...) {
00056 buf.reset();
00057 }
00058 return buf.get();
00059 }
00060
00061 public:
00062
00064 ErrorMessage() throw() { init(); }
00065
00066 ErrorMessage(const ErrorMessage& em) throw() : buf(em.buf) { }
00067
00069 ErrorMessage(const char *message) throw() {
00070 init();
00071 *this << message;
00072 }
00073
00075 ErrorMessage(const std::string &message) throw() {
00076 init();
00077 *this << message;
00078 }
00079
00081 template <typename T>
00082 ErrorMessage& operator<<(const T &t) throw() {
00083 if( ! buf.get() ) return *this;
00084
00085 try {
00086 *buf << t;
00087 }
00088 catch(...) {
00089 buf.reset();
00090 }
00091 }
00092
00094 const char* message() throw() {
00095 if( ! buf.get() ) return 0;
00096
00097 const char* mes = 0;
00098 try {
00099 mes = buf->str().c_str();
00100 }
00101 catch(...) {}
00102 return mes;
00103 }
00104
00105 };
00106
00112 class Exception : public std::exception {
00113 public:
00115 Exception() {}
00117 virtual ~Exception() throw() {}
00118
00120 virtual const char* exceptionName() const {
00121 return "lemon::Exception";
00122 }
00123
00125 virtual const char* what() const throw() {
00126 return exceptionName();
00127 }
00128 };
00129
00139 class LogicError : public Exception {
00140 public:
00141 virtual const char* exceptionName() const {
00142 return "lemon::LogicError";
00143 }
00144 };
00145
00152 class UninitializedParameter : public LogicError {
00153 public:
00154 virtual const char* exceptionName() const {
00155 return "lemon::UninitializedParameter";
00156 }
00157 };
00158
00159
00167 class RuntimeError : public Exception {
00168 public:
00169 virtual const char* exceptionName() const {
00170 return "lemon::RuntimeError";
00171 }
00172 };
00173
00175 class RangeError : public RuntimeError {
00176 public:
00177 virtual const char* exceptionName() const {
00178 return "lemon::RangeError";
00179 }
00180 };
00181
00183 class IOError : public RuntimeError {
00184 public:
00185 virtual const char* exceptionName() const {
00186 return "lemon::IOError";
00187 }
00188 };
00189
00191 class DataFormatError : public IOError {
00192 protected:
00193 const char *_message;
00194 int _line;
00195
00197 mutable
00198 std::auto_ptr<std::string> _file;
00199
00200 public:
00201
00202 DataFormatError(const DataFormatError &dfe) :
00203 IOError(dfe), _message(dfe._message), _line(dfe._line),
00204 _file(dfe._file) {}
00205
00207 explicit DataFormatError(const char *the_message)
00208 : _message(the_message), _line(0) {}
00210 DataFormatError(const std::string &file_name, int line_num,
00211 const char *the_message)
00212 : _message(the_message), _line(line_num) { file(file_name); }
00213
00215 void line(int line_num) { _line=line_num; }
00217 void message(char *the_message) { _message=the_message; }
00219 void file(const std::string &file_name) {
00220 try {
00221 _file.reset(new std::string);
00222 *_file = file_name;
00223 }
00224 catch(...) {
00225 _file.reset();
00226 }
00227 }
00228
00230 int line() const { return _line; }
00232 const char* message() const { return _message; }
00233
00237 const char* file() const {
00238 if( _file.get() )
00239 return _file->c_str();
00240 else
00241 return "(unknown)";
00242 }
00243
00245 virtual const char* what() const throw() {
00246 const char *mes = 0;
00247 try {
00248 std::ostringstream ostr;
00249 ostr << _message;
00250 if( _file.get() || _line ) {
00251 ostr << " (";
00252 if( _file.get() ) ostr << "in file '" << *_file << "'";
00253 if( _file.get() && _line ) ostr << " ";
00254 if( _line ) ostr << "at line " << _line;
00255 ostr << ")";
00256 }
00257 mes = ostr.str().c_str();
00258 }
00259 catch(...) {}
00260 if( mes ) return mes;
00261 return exceptionName();
00262 }
00263
00264 virtual const char* exceptionName() const {
00265 return "lemon::DataFormatError";
00266 }
00267
00268 virtual ~DataFormatError() throw() {}
00269 };
00270
00271
00273 class AssertionFailedError : public LogicError {
00274 protected:
00275 const char *assertion;
00276 const char *file;
00277 int line;
00278 const char *function;
00279 const char *message;
00280 public:
00282 AssertionFailedError(const char *_file, int _line, const char *func,
00283 const char *msg, const char *_assertion = 0) :
00284 assertion(_assertion), file(_file), line(_line), function(func),
00285 message(msg) {}
00286
00288 const char* get_assertion() const { return assertion; }
00290 const char* get_message() const { return message; }
00292 const char* get_file() const { return file; }
00294 const char* get_function() const { return function; }
00296 int get_line() const { return line; }
00297
00298
00299 virtual const char* what() const throw() {
00300 const char *mes = 0;
00301 try {
00302 std::ostringstream ostr;
00303 ostr << file << ":" << line << ": ";
00304 if( function )
00305 ostr << function << ": ";
00306 ostr << message;
00307 if( assertion )
00308 ostr << " (assertion '" << assertion << "' failed)";
00309 mes = ostr.str().c_str();
00310 }
00311 catch(...) {}
00312 if( mes ) return mes;
00313 return exceptionName();
00314 }
00315
00316 virtual const char* exceptionName() const {
00317 return "lemon::AssertionFailedError";
00318 }
00319
00320 virtual ~AssertionFailedError() throw() {}
00321 };
00322
00323
00324
00325
00326
00327 inline
00328 void assert_fail(const char *file, int line, const char *func,
00329 const char *message, const char *assertion = 0,
00330 bool do_abort=true)
00331 {
00332 using namespace std;
00333 cerr << file << ":" << line << ": ";
00334 if( func )
00335 cerr << func << ": ";
00336 cerr << message;
00337 if( assertion )
00338 cerr << " (assertion '" << assertion << "' failed)";
00339 cerr << endl;
00340 if(do_abort)
00341 abort();
00342 }
00343
00344 inline
00345 void assert_fail_throw(const char *file, int line, const char *func,
00346 const char *message, const char *assertion = 0,
00347 bool = true)
00348 {
00349 throw AssertionFailedError(file, line, func, message, assertion);
00350 }
00351
00353
00354 }
00355 #endif // LEMON_ERROR_H
00356
00357 #undef LEMON_ASSERT
00358 #undef LEMON_FIXME
00359
00360 #ifndef LEMON_ASSERT_ABORT
00361 # define LEMON_ASSERT_ABORT 1
00362 #endif
00363
00364 #ifndef LEMON_ASSERT_HANDLER
00365 # ifdef LEMON_ASSERT_EXCEPTION
00366 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_throw
00367 # else
00368 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail
00369 # endif
00370 #endif
00371
00372 #if defined(NDEBUG) || defined(LEMON_DISABLE_ASSERTS)
00373
00374 # define LEMON_ASSERT(exp, msg) (static_cast<void> (0))
00375
00376 #else
00377
00397 # define LEMON_ASSERT(exp, msg) \
00398 (static_cast<void> (!!(exp) ? 0 : ( \
00399 LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \
00400 __PRETTY_FUNCTION__, \
00401 (msg), #exp, LEMON_ASSERT_ABORT), 0)))
00402
00403 #endif // NDEBUG || LEMON_DISABLE_ASSERTS
00404
00415 # define LEMON_FIXME(msg) \
00416 (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, __PRETTY_FUNCTION__, \
00417 "FIXME: " msg))