00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef LEMON_ERROR_H
00019 #define LEMON_ERROR_H
00020
00024
00025 #include <exception>
00026 #include <string>
00027 #include <sstream>
00028 #include <iostream>
00029 #include <cstdlib>
00030 #include <memory>
00031
00032 namespace lemon {
00033
00036
00040 template <typename _Type>
00041 class ExceptionMember {
00042 public:
00043 typedef _Type Type;
00044
00045 ExceptionMember() throw () {
00046 try {
00047 ptr.reset(new Type());
00048 } catch (...) {}
00049 }
00050
00051 ExceptionMember(const Type& type) throw () {
00052 try {
00053 ptr.reset(new Type());
00054 if (ptr.get() == 0) return;
00055 *ptr = type;
00056 } catch (...) {}
00057 }
00058
00059 ExceptionMember(const ExceptionMember& copy) throw() {
00060 try {
00061 if (!copy.valid()) return;
00062 ptr.reset(new Type());
00063 if (ptr.get() == 0) return;
00064 *ptr = copy.get();
00065 } catch (...) {}
00066 }
00067
00068 ExceptionMember& operator=(const ExceptionMember& copy) {
00069 if (ptr.get() == 0) return;
00070 try {
00071 if (!copy.valid()) return;
00072 *ptr = copy.get();
00073 } catch (...) {}
00074 }
00075
00076 void set(const Type& type) {
00077 if (ptr.get() == 0) return;
00078 try {
00079 *ptr = type;
00080 } catch (...) {}
00081 }
00082
00083 const Type& get() const {
00084 return *ptr;
00085 }
00086
00087 bool valid() const {
00088 return ptr.get() != 0;
00089 }
00090
00091 private:
00092 std::auto_ptr<_Type> ptr;
00093 };
00094
00096
00100 class ErrorMessage {
00101 protected:
00103
00106 mutable
00107 std::auto_ptr<std::ostringstream> buf;
00108
00110 bool init() throw() {
00111 try {
00112 buf.reset(new std::ostringstream);
00113 }
00114 catch(...) {
00115 buf.reset();
00116 }
00117 return buf.get();
00118 }
00119
00120 public:
00121
00123 ErrorMessage() throw() { init(); }
00124
00125 ErrorMessage(const ErrorMessage& em) throw() : buf(em.buf) { }
00126
00128 ErrorMessage(const char *message) throw() {
00129 init();
00130 *this << message;
00131 }
00132
00134 ErrorMessage(const std::string &message) throw() {
00135 init();
00136 *this << message;
00137 }
00138
00140 template <typename T>
00141 ErrorMessage& operator<<(const T &t) throw() {
00142 if( ! buf.get() ) return *this;
00143
00144 try {
00145 *buf << t;
00146 }
00147 catch(...) {
00148 buf.reset();
00149 }
00150 return *this;
00151 }
00152
00154 const char* message() throw() {
00155 if( ! buf.get() ) return 0;
00156
00157 const char* mes = 0;
00158 try {
00159 mes = buf->str().c_str();
00160 }
00161 catch(...) {}
00162 return mes;
00163 }
00164
00165 };
00166
00172 class Exception : public std::exception {
00173 public:
00175 Exception() {}
00177 virtual ~Exception() throw() {}
00178
00180 virtual const char* exceptionName() const {
00181 return "lemon::Exception";
00182 }
00183
00185 virtual const char* what() const throw() {
00186 return exceptionName();
00187 }
00188 };
00189
00199 class LogicError : public Exception {
00200 public:
00201 virtual const char* exceptionName() const {
00202 return "lemon::LogicError";
00203 }
00204 };
00205
00212 class UninitializedParameter : public LogicError {
00213 public:
00214 virtual const char* exceptionName() const {
00215 return "lemon::UninitializedParameter";
00216 }
00217 };
00218
00219
00227 class RuntimeError : public Exception {
00228 public:
00229 virtual const char* exceptionName() const {
00230 return "lemon::RuntimeError";
00231 }
00232 };
00233
00235 class RangeError : public RuntimeError {
00236 public:
00237 virtual const char* exceptionName() const {
00238 return "lemon::RangeError";
00239 }
00240 };
00241
00243 class IOError : public RuntimeError {
00244 public:
00245 virtual const char* exceptionName() const {
00246 return "lemon::IOError";
00247 }
00248 };
00249
00251 class DataFormatError : public IOError {
00252 protected:
00253 ExceptionMember<std::string> _message;
00254 ExceptionMember<std::string> _file;
00255 int _line;
00256
00257 mutable ExceptionMember<std::string> _message_holder;
00258 public:
00259
00260 DataFormatError(const DataFormatError &dfe) :
00261 IOError(dfe), _message(dfe._message), _file(dfe._file),
00262 _line(dfe._line) {}
00263
00265 explicit DataFormatError(const char *the_message)
00266 : _message(the_message), _line(0) {}
00267
00269 DataFormatError(const std::string &file_name, int line_num,
00270 const char *the_message)
00271 : _message(the_message), _line(line_num) { file(file_name); }
00272
00274 void line(int line) { _line = line; }
00276 void message(const std::string& message) { _message.set(message); }
00278 void file(const std::string &file) { _file.set(file); }
00279
00281 int line() const { return _line; }
00283 const char* message() const {
00284 if (_message.valid() && !_message.get().empty()) {
00285 return _message.get().c_str();
00286 } else {
00287 return 0;
00288 }
00289 }
00290
00294 const char* file() const {
00295 if (_file.valid() && !_file.get().empty()) {
00296 return _file.get().c_str();
00297 } else {
00298 return 0;
00299 }
00300 }
00301
00303 virtual const char* what() const throw() {
00304 try {
00305 std::ostringstream ostr;
00306 ostr << exceptionName() << ": ";
00307 if (message()) ostr << message();
00308 if( file() || line() != 0 ) {
00309 ostr << " (";
00310 if( file() ) ostr << "in file '" << file() << "'";
00311 if( file() && line() != 0 ) ostr << " ";
00312 if( line() != 0 ) ostr << "at line " << line();
00313 ostr << ")";
00314 }
00315 _message_holder.set(ostr.str());
00316 }
00317 catch (...) {}
00318 if( _message_holder.valid()) return _message_holder.get().c_str();
00319 return exceptionName();
00320 }
00321
00322 virtual const char* exceptionName() const {
00323 return "lemon::DataFormatError";
00324 }
00325
00326 virtual ~DataFormatError() throw() {}
00327 };
00328
00329 class IOParameterError : public LogicError {
00330 protected:
00331 ExceptionMember<std::string> _message;
00332 ExceptionMember<std::string> _file;
00333
00334 mutable ExceptionMember<std::string> _message_holder;
00335 public:
00336
00337 IOParameterError(const IOParameterError &ile) :
00338 LogicError(ile), _message(ile._message), _file(ile._file) {}
00339
00341 explicit IOParameterError(const char *the_message)
00342 : _message(the_message) {}
00343
00345 IOParameterError(const char *file_name, const char *the_message)
00346 : _message(the_message), _file(file_name) {}
00347
00349 void message(const std::string& message) { _message.set(message); }
00351 void file(const std::string &file) { _file.set(file); }
00352
00354 const char* message() const {
00355 if (_message.valid()) {
00356 return _message.get().c_str();
00357 } else {
00358 return 0;
00359 }
00360 }
00361
00365 const char* file() const {
00366 if (_file.valid()) {
00367 return _file.get().c_str();
00368 } else {
00369 return 0;
00370 }
00371 }
00372
00374 virtual const char* what() const throw() {
00375 try {
00376 std::ostringstream ostr;
00377 if (message()) ostr << message();
00378 if (file()) ostr << "(when reading file '" << file() << "')";
00379 _message_holder.set(ostr.str());
00380 }
00381 catch (...) {}
00382 if( _message_holder.valid() ) return _message_holder.get().c_str();
00383 return exceptionName();
00384 }
00385
00386 virtual const char* exceptionName() const {
00387 return "lemon::IOParameterError";
00388 }
00389
00390 virtual ~IOParameterError() throw() {}
00391 };
00392
00393
00395 class AssertionFailedError : public LogicError {
00396 protected:
00397 const char *assertion;
00398 const char *file;
00399 int line;
00400 const char *function;
00401 const char *message;
00402
00403 mutable ExceptionMember<std::string> _message_holder;
00404 public:
00406 AssertionFailedError(const char *_file, int _line, const char *func,
00407 const char *msg, const char *_assertion = 0) :
00408 assertion(_assertion), file(_file), line(_line), function(func),
00409 message(msg) {}
00410
00412 const char* get_assertion() const { return assertion; }
00414 const char* get_message() const { return message; }
00416 const char* get_file() const { return file; }
00418 const char* get_function() const { return function; }
00420 int get_line() const { return line; }
00421
00422
00423 virtual const char* what() const throw() {
00424 try {
00425 std::ostringstream ostr;
00426 ostr << file << ":" << line << ": ";
00427 if( function )
00428 ostr << function << ": ";
00429 ostr << message;
00430 if( assertion )
00431 ostr << " (assertion '" << assertion << "' failed)";
00432 _message_holder.set(ostr.str());
00433 return ostr.str().c_str();
00434 }
00435 catch(...) {}
00436 if( _message_holder.valid() ) return _message_holder.get().c_str();
00437 return exceptionName();
00438 }
00439
00440 virtual const char* exceptionName() const {
00441 return "lemon::AssertionFailedError";
00442 }
00443
00444 virtual ~AssertionFailedError() throw() {}
00445 };
00446
00447
00448
00449
00450
00451 inline
00452 void assert_fail(const char *file, int line, const char *func,
00453 const char *message, const char *assertion = 0,
00454 bool do_abort=true)
00455 {
00456 using namespace std;
00457 cerr << file << ":" << line << ": ";
00458 if( func )
00459 cerr << func << ": ";
00460 cerr << message;
00461 if( assertion )
00462 cerr << " (assertion '" << assertion << "' failed)";
00463 cerr << endl;
00464 if(do_abort)
00465 abort();
00466 }
00467
00468 inline
00469 void assert_fail_throw(const char *file, int line, const char *func,
00470 const char *message, const char *assertion = 0,
00471 bool = true)
00472 {
00473 throw AssertionFailedError(file, line, func, message, assertion);
00474 }
00475
00477
00478 }
00479 #endif // LEMON_ERROR_H
00480
00481 #undef LEMON_ASSERT
00482 #undef LEMON_FIXME
00483
00484 #ifndef LEMON_ASSERT_ABORT
00485 # define LEMON_ASSERT_ABORT 1
00486 #endif
00487
00488 #ifndef LEMON_ASSERT_HANDLER
00489 # ifdef LEMON_ASSERT_EXCEPTION
00490 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_throw
00491 # else
00492 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail
00493 # endif
00494 #endif
00495
00496 #if defined(NDEBUG) || defined(LEMON_DISABLE_ASSERTS)
00497
00498 # define LEMON_ASSERT(exp, msg) (static_cast<void> (0))
00499
00500 #else
00501
00521 # define LEMON_ASSERT(exp, msg) \
00522 (static_cast<void> (!!(exp) ? 0 : ( \
00523 LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \
00524 __PRETTY_FUNCTION__, \
00525 (msg), #exp, LEMON_ASSERT_ABORT), 0)))
00526
00527 #endif // NDEBUG || LEMON_DISABLE_ASSERTS
00528
00539 # define LEMON_FIXME(msg) \
00540 (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, __PRETTY_FUNCTION__, \
00541 "FIXME: " msg))