1 /** 2 * \file RMF/exceptions.h 3 * \brief Declarations of the various exception types. 4 * 5 * Copyright 2007-2021 IMP Inventors. All rights reserved. 6 * 7 */ 8 9 #ifndef RMF_EXCEPTIONS_H 10 #define RMF_EXCEPTIONS_H 11 12 #include <boost/exception/exception.hpp> // IWYU pragma: export 13 #include <exception> 14 #include <string> 15 16 #include "RMF/config.h" 17 #include "compiler_macros.h" 18 19 RMF_ENABLE_WARNINGS 20 namespace RMF { 21 /** The base class for RMF exceptions. Use the what() method 22 to get back a string describing the exception. 23 24 Use get_message() to get a nice message describing the 25 exception. 26 */ 27 class RMFEXPORT Exception : public virtual std::exception, 28 public virtual boost::exception { 29 mutable std::string message_; 30 31 public: 32 RMF_CXX11_DEFAULT_COPY_CONSTRUCTOR(Exception); 33 Exception(); 34 const char* what() const RMF_NOEXCEPT RMF_OVERRIDE; 35 virtual ~Exception() RMF_NOEXCEPT; 36 }; 37 38 /** Use this instead of the more standard what() to get the 39 message as what() presents issues for memory management 40 with dynamically generated messages like. */ 41 RMFEXPORT std::string get_message(const Exception& e); 42 43 /** Usage exceptions are thrown when the library is misused in some way, 44 e.g., an out of bounds element is requested from a collection. In general 45 when these are throw, the failed operation should have been cleanly 46 aborted without changing the file. 47 */ 48 class RMFEXPORT UsageException : public Exception { 49 public: 50 RMF_CXX11_DEFAULT_COPY_CONSTRUCTOR(UsageException); 51 UsageException(); 52 ~UsageException() RMF_NOEXCEPT; 53 }; 54 55 /** IOExceptions are thrown when some operation on a disk file fails. 56 */ 57 class RMFEXPORT IOException : public Exception { 58 public: 59 RMF_CXX11_DEFAULT_COPY_CONSTRUCTOR(IOException); 60 IOException(); 61 ~IOException() RMF_NOEXCEPT; 62 }; 63 64 /** Internal exceptions are thrown when the library discovers that some 65 internal invariant no longer holds. Since they represent bugs in the 66 library, one can not necessarily recover when they occur.. 67 */ 68 class RMFEXPORT InternalException : public Exception { 69 public: 70 RMF_CXX11_DEFAULT_COPY_CONSTRUCTOR(InternalException); 71 InternalException(); 72 ~InternalException() RMF_NOEXCEPT; 73 }; 74 75 /** IndexExceptions are thrown when you walk off the end of something. 76 */ 77 class RMFEXPORT IndexException : public Exception { 78 public: 79 RMF_CXX11_DEFAULT_COPY_CONSTRUCTOR(IndexException); 80 IndexException(); 81 ~IndexException() RMF_NOEXCEPT; 82 }; 83 } 84 85 #define RMF_THROW(m, e) \ 86 { \ 87 using namespace ::RMF::internal::ErrorInfo; \ 88 using ::RMF::internal::ErrorInfo::Type; \ 89 using ::RMF::internal::ErrorInfo::Category; \ 90 using ::RMF::internal::ErrorInfo::Key; \ 91 using ::RMF::internal::ErrorInfo::Decorator; \ 92 using boost::operator<<; \ 93 throw e() << m; \ 94 } 95 96 #define RMF_RETHROW(m, e) \ 97 { \ 98 using namespace ::RMF::internal::ErrorInfo; \ 99 using ::RMF::internal::ErrorInfo::Type; \ 100 using ::RMF::internal::ErrorInfo::Category; \ 101 using ::RMF::internal::ErrorInfo::Key; \ 102 using ::RMF::internal::ErrorInfo::Decorator; \ 103 using boost::operator<<; \ 104 e << m; \ 105 throw; \ 106 } 107 108 #define RMF_USAGE_CHECK(check, message) \ 109 do { \ 110 if (!(check)) { \ 111 RMF_THROW(Message(message) << Type("Usage"), ::RMF::UsageException); \ 112 } \ 113 } while (false) 114 115 #define RMF_INDEX_CHECK(value, end) \ 116 RMF_USAGE_CHECK( \ 117 static_cast<unsigned int>(value) < static_cast<unsigned int>(end), \ 118 "Out of range index"); 119 120 #define RMF_PATH_CHECK(path) \ 121 if (!boost::filesystem::exists(path)) { \ 122 RMF_THROW(Message("File does not exist") << File(path) << Type("Usage"), \ 123 IOException); \ 124 } 125 126 #ifndef RMF_NDEBUG 127 #define RMF_INTERNAL_CHECK(check, message) \ 128 do { \ 129 if (!(check)) { \ 130 RMF_THROW(Message(message) << Type("Internal") << SourceFile(__FILE__) \ 131 << SourceLine(__LINE__) \ 132 << Function(BOOST_CURRENT_FUNCTION), \ 133 ::RMF::InternalException); \ 134 } \ 135 } while (false) 136 137 #define RMF_IF_CHECK if (true) 138 139 #else // NDEBUG 140 #define RMF_INTERNAL_CHECK(check, message) 141 #define RMF_IF_CHECK 142 143 #endif 144 145 #define RMF_NOT_IMPLEMENTED \ 146 RMF_THROW(Message("Not implemented") << Function(BOOST_CURRENT_FUNCTION) \ 147 << SourceFile(__FILE__) \ 148 << SourceLine(__LINE__) \ 149 << Type("NotImplemented"), \ 150 ::RMF::InternalException) 151 152 RMF_DISABLE_WARNINGS 153 154 #include "RMF/internal/errors.h" // IWYU pragma: export 155 156 #endif /* RMF_EXCEPTIONS_H */ 157