RMF
exceptions.h
Go to the documentation of this file.
1 /**
2  * \file RMF/exceptions.h
3  * \brief Declarations of the various exception types.
4  *
5  * Copyright 2007-2022 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 noexcept override;
35  virtual ~Exception() 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. */
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 thrown, 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);
52  ~UsageException() 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() 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);
72  ~InternalException() 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);
81  ~IndexException() 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 */
std::string get_message(const Exception &e)
Various compiler workarounds.