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
00041 template <typename _Type>
00042 class ExceptionMember {
00043 public:
00044 typedef _Type Type;
00045
00046 ExceptionMember() throw () {
00047 try {
00048 ptr.reset(new Type());
00049 } catch (...) {}
00050 }
00051
00052 ExceptionMember(const Type& type) throw () {
00053 try {
00054 ptr.reset(new Type());
00055 if (ptr.get() == 0) return;
00056 *ptr = type;
00057 } catch (...) {}
00058 }
00059
00060 ExceptionMember(const ExceptionMember& copy) throw() {
00061 try {
00062 if (!copy.valid()) return;
00063 ptr.reset(new Type());
00064 if (ptr.get() == 0) return;
00065 *ptr = copy.get();
00066 } catch (...) {}
00067 }
00068
00069 ExceptionMember& operator=(const ExceptionMember& copy) {
00070 if (ptr.get() == 0) return;
00071 try {
00072 if (!copy.valid()) return;
00073 *ptr = copy.get();
00074 } catch (...) {}
00075 }
00076
00077 void set(const Type& type) {
00078 if (ptr.get() == 0) return;
00079 try {
00080 *ptr = type;
00081 } catch (...) {}
00082 }
00083
00084 const Type& get() const {
00085 return *ptr;
00086 }
00087
00088 bool valid() const {
00089 return ptr.get() != 0;
00090 }
00091
00092 private:
00093 std::auto_ptr<_Type> ptr;
00094 };
00095
00097
00101 class ErrorMessage {
00102 protected:
00104
00107 mutable
00108 std::auto_ptr<std::ostringstream> buf;
00109
00111 bool init() throw() {
00112 try {
00113 buf.reset(new std::ostringstream);
00114 }
00115 catch(...) {
00116 buf.reset();
00117 }
00118 return buf.get();
00119 }
00120
00121 public:
00122
00124 ErrorMessage() throw() { init(); }
00125
00126 ErrorMessage(const ErrorMessage& em) throw() : buf(em.buf) { }
00127
00129 ErrorMessage(const char *message) throw() {
00130 init();
00131 *this << message;
00132 }
00133
00135 ErrorMessage(const std::string &message) throw() {
00136 init();
00137 *this << message;
00138 }
00139
00141 template <typename T>
00142 ErrorMessage& operator<<(const T &t) throw() {
00143 if( ! buf.get() ) return *this;
00144
00145 try {
00146 *buf << t;
00147 }
00148 catch(...) {
00149 buf.reset();
00150 }
00151 return *this;
00152 }
00153
00155 const char* message() throw() {
00156 if( ! buf.get() ) return 0;
00157
00158 const char* mes = 0;
00159 try {
00160 mes = buf->str().c_str();
00161 }
00162 catch(...) {}
00163 return mes;
00164 }
00165
00166 };
00167
00173 class Exception : public std::exception {
00174 public:
00176 Exception() {}
00178 virtual ~Exception() throw() {}
00179
00181 virtual const char* exceptionName() const {
00182 return "lemon::Exception";
00183 }
00184
00186 virtual const char* what() const throw() {
00187 return exceptionName();
00188 }
00189 };
00190
00200 class LogicError : public Exception {
00201 public:
00202 virtual const char* exceptionName() const {
00203 return "lemon::LogicError";
00204 }
00205 };
00206
00213 class UninitializedParameter : public LogicError {
00214 public:
00215 virtual const char* exceptionName() const {
00216 return "lemon::UninitializedParameter";
00217 }
00218 };
00219
00220
00228 class RuntimeError : public Exception {
00229 public:
00230 virtual const char* exceptionName() const {
00231 return "lemon::RuntimeError";
00232 }
00233 };
00234
00236 class RangeError : public RuntimeError {
00237 public:
00238 virtual const char* exceptionName() const {
00239 return "lemon::RangeError";
00240 }
00241 };
00242
00244 class IOError : public RuntimeError {
00245 public:
00246 virtual const char* exceptionName() const {
00247 return "lemon::IOError";
00248 }
00249 };
00250
00252 class DataFormatError : public IOError {
00253 protected:
00254 ExceptionMember<std::string> _message;
00255 ExceptionMember<std::string> _file;
00256 int _line;
00257
00258 mutable ExceptionMember<std::string> _message_holder;
00259 public:
00260
00261 DataFormatError(const DataFormatError &dfe) :
00262 IOError(dfe), _message(dfe._message), _file(dfe._file),
00263 _line(dfe._line) {}
00264
00266 explicit DataFormatError(const char *the_message)
00267 : _message(the_message), _line(0) {}
00268
00270 DataFormatError(const std::string &file_name, int line_num,
00271 const char *the_message)
00272 : _message(the_message), _line(line_num) { file(file_name); }
00273
00275 void line(int line) { _line = line; }
00277 void message(const std::string& message) { _message.set(message); }
00279 void file(const std::string &file) { _file.set(file); }
00280
00282 int line() const { return _line; }
00284 const char* message() const {
00285 if (_message.valid() && !_message.get().empty()) {
00286 return _message.get().c_str();
00287 } else {
00288 return 0;
00289 }
00290 }
00291
00295 const char* file() const {
00296 if (_file.valid() && !_file.get().empty()) {
00297 return _file.get().c_str();
00298 } else {
00299 return 0;
00300 }
00301 }
00302
00304 virtual const char* what() const throw() {
00305 try {
00306 std::ostringstream ostr;
00307 ostr << exceptionName() << ": ";
00308 if (message()) ostr << message();
00309 if( file() || line() != 0 ) {
00310 ostr << " (";
00311 if( file() ) ostr << "in file '" << file() << "'";
00312 if( file() && line() != 0 ) ostr << " ";
00313 if( line() != 0 ) ostr << "at line " << line();
00314 ostr << ")";
00315 }
00316 _message_holder.set(ostr.str());
00317 }
00318 catch (...) {}
00319 if( _message_holder.valid()) return _message_holder.get().c_str();
00320 return exceptionName();
00321 }
00322
00323 virtual const char* exceptionName() const {
00324 return "lemon::DataFormatError";
00325 }
00326
00327 virtual ~DataFormatError() throw() {}
00328 };
00329
00331 class FileOpenError : public IOError {
00332 protected:
00333 ExceptionMember<std::string> _file;
00334
00335 mutable ExceptionMember<std::string> _message_holder;
00336 public:
00337
00338 FileOpenError(const FileOpenError &foe) :
00339 IOError(foe), _file(foe._file) {}
00340
00342 explicit FileOpenError(const std::string& file)
00343 : _file(file) {}
00344
00345
00347 void file(const std::string &file) { _file.set(file); }
00348
00352 const char* file() const {
00353 if (_file.valid() && !_file.get().empty()) {
00354 return _file.get().c_str();
00355 } else {
00356 return 0;
00357 }
00358 }
00359
00361 virtual const char* what() const throw() {
00362 try {
00363 std::ostringstream ostr;
00364 ostr << exceptionName() << ": ";
00365 ostr << "Cannot open file - " << file();
00366 _message_holder.set(ostr.str());
00367 }
00368 catch (...) {}
00369 if( _message_holder.valid()) return _message_holder.get().c_str();
00370 return exceptionName();
00371 }
00372
00373 virtual const char* exceptionName() const {
00374 return "lemon::FileOpenError";
00375 }
00376
00377 virtual ~FileOpenError() throw() {}
00378 };
00379
00380 class IOParameterError : public IOError {
00381 protected:
00382 ExceptionMember<std::string> _message;
00383 ExceptionMember<std::string> _file;
00384
00385 mutable ExceptionMember<std::string> _message_holder;
00386 public:
00387
00388 IOParameterError(const IOParameterError &ile) :
00389 IOError(ile), _message(ile._message), _file(ile._file) {}
00390
00392 explicit IOParameterError(const char *the_message)
00393 : _message(the_message) {}
00394
00396 IOParameterError(const char *file_name, const char *the_message)
00397 : _message(the_message), _file(file_name) {}
00398
00400 void message(const std::string& message) { _message.set(message); }
00402 void file(const std::string &file) { _file.set(file); }
00403
00405 const char* message() const {
00406 if (_message.valid()) {
00407 return _message.get().c_str();
00408 } else {
00409 return 0;
00410 }
00411 }
00412
00416 const char* file() const {
00417 if (_file.valid()) {
00418 return _file.get().c_str();
00419 } else {
00420 return 0;
00421 }
00422 }
00423
00425 virtual const char* what() const throw() {
00426 try {
00427 std::ostringstream ostr;
00428 if (message()) ostr << message();
00429 if (file()) ostr << "(when reading file '" << file() << "')";
00430 _message_holder.set(ostr.str());
00431 }
00432 catch (...) {}
00433 if( _message_holder.valid() ) return _message_holder.get().c_str();
00434 return exceptionName();
00435 }
00436
00437 virtual const char* exceptionName() const {
00438 return "lemon::IOParameterError";
00439 }
00440
00441 virtual ~IOParameterError() throw() {}
00442 };
00443
00444
00446 class AssertionFailedError : public LogicError {
00447 protected:
00448 const char *assertion;
00449 const char *file;
00450 int line;
00451 const char *function;
00452 const char *message;
00453
00454 mutable ExceptionMember<std::string> _message_holder;
00455 public:
00457 AssertionFailedError(const char *_file, int _line, const char *func,
00458 const char *msg, const char *_assertion = 0) :
00459 assertion(_assertion), file(_file), line(_line), function(func),
00460 message(msg) {}
00461
00463 const char* get_assertion() const { return assertion; }
00465 const char* get_message() const { return message; }
00467 const char* get_file() const { return file; }
00469 const char* get_function() const { return function; }
00471 int get_line() const { return line; }
00472
00473
00474 virtual const char* what() const throw() {
00475 try {
00476 std::ostringstream ostr;
00477 ostr << file << ":" << line << ": ";
00478 if( function )
00479 ostr << function << ": ";
00480 ostr << message;
00481 if( assertion )
00482 ostr << " (assertion '" << assertion << "' failed)";
00483 _message_holder.set(ostr.str());
00484 return ostr.str().c_str();
00485 }
00486 catch(...) {}
00487 if( _message_holder.valid() ) return _message_holder.get().c_str();
00488 return exceptionName();
00489 }
00490
00491 virtual const char* exceptionName() const {
00492 return "lemon::AssertionFailedError";
00493 }
00494
00495 virtual ~AssertionFailedError() throw() {}
00496 };
00497
00498
00499
00500
00501
00502 template <typename Exception>
00503 inline void assert_fail(const char *file, int line, const char *func,
00504 Exception exception, const char *assertion = 0,
00505 bool do_abort=true)
00506 {
00507 using namespace std;
00508 cerr << file << ":" << line << ": ";
00509 if( func )
00510 cerr << func << ": ";
00511 cerr << exception.what();
00512 if( assertion )
00513 cerr << " (assertion '" << assertion << "' failed)";
00514 cerr << endl;
00515 if(do_abort)
00516 abort();
00517 }
00518
00519 template <>
00520 inline void assert_fail<const char *>(const char *file, int line, const char *func,
00521 const char *message,
00522 const char *assertion,
00523 bool do_abort)
00524 {
00525 using namespace std;
00526 cerr << file << ":" << line << ": ";
00527 if( func )
00528 cerr << func << ": ";
00529 cerr << message;
00530 if( assertion )
00531 cerr << " (assertion '" << assertion << "' failed)";
00532 cerr << endl;
00533 if(do_abort)
00534 abort();
00535 }
00536
00537 template <typename Exception>
00538 inline void assert_fail_failure(const char *file, int line, const char *func,
00539 Exception exception,
00540 const char *assertion = 0,
00541 bool = true)
00542 {
00543 throw AssertionFailedError(file, line, func, exception.what(), assertion);
00544 }
00545
00546 template <>
00547 inline void assert_fail_failure<const char *>(const char *file, int line,
00548 const char *func,
00549 const char *message,
00550 const char *assertion,
00551 bool)
00552 {
00553 throw AssertionFailedError(file, line, func, message, assertion);
00554 }
00555
00556 template <typename Exception>
00557 inline void assert_fail_exception(const char *file, int line, const char *func,
00558 Exception exception,
00559 const char *assertion = 0, bool = true)
00560 {
00561 throw exception;
00562 }
00563
00564 template <>
00565 inline void assert_fail_exception<const char *>(const char *file, int line,
00566 const char *func,
00567 const char *message,
00568 const char *assertion,
00569 bool)
00570 {
00571 throw AssertionFailedError(file, line, func, message, assertion);
00572 }
00573
00575
00576 }
00577 #endif // LEMON_ERROR_H
00578
00579 #undef LEMON_ASSERT
00580 #undef LEMON_FIXME
00581
00582 #ifndef LEMON_ASSERT_ABORT
00583 # define LEMON_ASSERT_ABORT 1
00584 #endif
00585
00586 #ifndef LEMON_ASSERT_HANDLER
00587 # if defined LEMON_ASSERT_EXCEPTION
00588 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_exception
00589 # elif defined LEMON_ASSERT_FAILURE
00590 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail_failure
00591 # else
00592 # define LEMON_ASSERT_HANDLER ::lemon::assert_fail
00593 # endif
00594 #endif
00595
00596 #if defined(NDEBUG) || defined(LEMON_DISABLE_ASSERTS)
00597
00598 # define LEMON_ASSERT(exp, msg) (static_cast<void> (0))
00599
00600 #else
00601
00623 # define LEMON_ASSERT(exp, msg) \
00624 (static_cast<void> (!!(exp) ? 0 : ( \
00625 LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \
00626 __PRETTY_FUNCTION__, \
00627 msg, #exp, LEMON_ASSERT_ABORT), 0)))
00628
00629 #endif // NDEBUG || LEMON_DISABLE_ASSERTS
00630
00641 # define LEMON_FIXME(msg) \
00642 (LEMON_ASSERT_HANDLER(__FILE__, __LINE__, __PRETTY_FUNCTION__, \
00643 "FIXME: " msg))