RTC Toolkit  2.0.0
exceptions.hpp
Go to the documentation of this file.
1 
12 #ifndef RTCTK_COMPONENTFRAMEWORK_EXCEPTIONS_HPP
13 #define RTCTK_COMPONENTFRAMEWORK_EXCEPTIONS_HPP
14 
15 #include <string_view>
16 #include <type_traits>
17 #include <typeinfo>
18 
19 #include <ciiBasicDataType.hpp>
20 #include <ciiException.hpp>
21 
22 namespace {
23 
24 // Constructs an exception object. Depending on the type of the exception, additional context
25 // information is added to the object if supported.
26 // This function is used to implement the CII_THROW and CII_THROW_WITH_NESTED macros.
27 template <typename T, typename N, typename... Args>
28 T CreateExceptionObject(
29  const N& nested_exception, const char* file, int line, const char* function, Args&&... args) {
30  if constexpr (std::is_base_of_v<elt::error::CiiException, T>) {
31  T throwing_exception = T(std::forward<Args>(args)...);
32  throwing_exception.SetFileName(boost::filesystem::path(file).filename().string());
33  throwing_exception.SetFunctionName(function);
34  throwing_exception.SetLineNumber(line);
35  throwing_exception.SetClassName(boost::core::demangle(typeid(T).name()));
36  std::vector<std::string> this_stack;
37  this_stack.push_back(throwing_exception.getCiiMessage());
38  if constexpr (std::is_base_of_v<elt::error::CiiException, N>) {
39  std::vector<std::string> nested_stack = nested_exception.getCiiExceptionStack();
40  this_stack.insert(this_stack.end(), nested_stack.begin(), nested_stack.end());
41  } else if constexpr (std::is_base_of_v<std::exception, N>) {
42  this_stack.push_back(nested_exception.what());
43  } else {
44  this_stack.push_back("Unknown exception.");
45  }
46  throwing_exception.SetCiiExceptionStack(this_stack);
47  return throwing_exception;
48  } else {
49  return T(std::forward<Args>(args)...);
50  }
51 }
52 
53 } // namespace
54 
55 // We temporarily redefine the CII_THROW_WITH_NESTED macro to be backwards compatible with
56 // std::runtime_error and std::logic_error, i.e. to still support these as nested exception.
57 // TODO: Remove the redefinitions once CII allows std::exceptions for nested exceptions.
58 
59 #ifdef CII_THROW_WITH_NESTED
60 #undef CII_THROW_WITH_NESTED
61 
62 #define CII_THROW_WITH_NESTED(exceptionType_t, nested_exception, ...) \
63  { \
64  exceptionType_t throwing_exception = CreateExceptionObject<exceptionType_t>( \
65  nested_exception, __FILE__, __LINE__, __FUNCTION__, __VA_ARGS__); \
66  std::throw_with_nested(throwing_exception); \
67  }
68 
69 #endif // CII_THROW_WITH_NESTED
70 
71 namespace rtctk::componentFramework {
72 namespace detail {
73 
79 template <class T>
80 struct UnspecifiedNested : virtual T, virtual std::nested_exception {
81  template <class E>
82  explicit UnspecifiedNested(E&& e) noexcept(std::is_nothrow_constructible_v<T, E&&>)
83  : T(std::forward<E>(e)) {
84  }
85 };
86 
92 std::ostream& JoinLines(std::ostream& os,
93  std::string_view lines,
94  std::string_view initial_indent,
95  std::string_view subsequent_indent);
96 
97 } // namespace detail
98 
115 template <class E>
116 auto WrapWithNested(E&& exception) noexcept(
117  std::is_nothrow_constructible_v<detail::UnspecifiedNested<typename std::decay_t<E>>, E&&>) {
118  using Type = typename std::decay_t<E>;
119  static_assert(std::is_class_v<Type>, "exception must be a non-union class-type");
120 
121  return detail::UnspecifiedNested<Type>(std::forward<E>(exception));
122 }
123 
136 void PrintNestedExceptions(std::ostream& os, std::exception const& exception);
137 
146 void PrintNestedExceptions(std::ostream& os, std::exception_ptr ptr);
147 
158 public:
162  explicit NestedExceptionPrinter(std::exception const& exception) noexcept
163  : m_ptr(), m_exception(&exception){};
167  explicit NestedExceptionPrinter(std::exception_ptr ptr) noexcept
168  : m_ptr(std::move(ptr)), m_exception(nullptr){};
169 
175  std::string Str() const {
176  std::stringstream ss;
177  ss << *this;
178  return ss.str();
179  }
180 
188  friend std::ostream& operator<<(std::ostream& os, NestedExceptionPrinter const& printer) {
189  if (printer.m_ptr) {
190  PrintNestedExceptions(os, printer.m_ptr);
191  } else if (printer.m_exception) {
192  PrintNestedExceptions(os, *printer.m_exception);
193  }
194  return os;
195  }
196 
197 private:
198  // A variant or union would occupy same space so this was preferred over
199  // including <variant>
200  std::exception_ptr m_ptr;
201  std::exception const* m_exception;
202 };
203 
207 class RtctkException : public elt::error::CiiBaseException {
208 public:
209  RtctkException() noexcept;
210 
211  explicit RtctkException(const std::string& msg);
212 
213  RtctkException(const RtctkException& other) noexcept;
214 
215  virtual ~RtctkException() override = default;
216 };
217 
223 public:
224  explicit NotImplementedException(const std::string& feature);
225 };
226 
232 public:
233  explicit UnsupportedTypeException(const std::string& type);
234  explicit UnsupportedTypeException(const std::type_info& type);
235  explicit UnsupportedTypeException(const elt::common::CiiBasicDataType type);
236 };
237 
243 public:
244  explicit UnsupportedUriException(const elt::mal::Uri& uri);
245 };
246 
252 public:
253  explicit BufferTooSmall(const std::size_t actual, const std::size_t expected);
254  std::size_t GetActualBufferSize() const {
255  return m_actual;
256  }
257  std::size_t GetExpectedBufferSize() const {
258  return m_expected;
259  }
260 
261 protected:
262  std::size_t m_actual;
263  std::size_t m_expected;
264 };
265 
267 public:
268  explicit InvalidArgumentException(const std::string& message);
269 };
270 
277 public:
278  explicit InitialisationException(const std::string& message);
279 };
280 
281 } // namespace rtctk::componentFramework
282 
283 #endif // RTCTK_COMPONENTFRAMEWORK_EXCEPTIONS_HPP
rtctk::componentFramework::UnsupportedTypeException
The UnsupportedTypeException is thrown whenever an attempt is made to use an unsupported type in the ...
Definition: exceptions.hpp:231
rtctk::componentFramework::detail::UnspecifiedNested
Unspecified exception used by WrapWithNested.
Definition: exceptions.hpp:80
wscript.name
name
Definition: wscript:15
rtctk::componentFramework::NestedExceptionPrinter::NestedExceptionPrinter
NestedExceptionPrinter(std::exception_ptr ptr) noexcept
Construct from exception_ptr.
Definition: exceptions.hpp:167
rtctk::componentFramework::detail::JoinLines
std::ostream & JoinLines(std::ostream &os, std::string_view lines, std::string_view initial_indent, std::string_view subsequent_indent)
Join each line in lines with.
Definition: exceptions.cpp:24
rtctk::componentFramework::NotImplementedException
The NotImplementedException is thrown whenever an attempt is made to use a feature or function that h...
Definition: exceptions.hpp:222
rtctk::componentFramework::PrintNestedExceptions
void PrintNestedExceptions(std::ostream &os, std::exception const &exception)
Print nested exception(s) in exception messages to os.
Definition: exceptions.cpp:161
rtctk::componentFramework::RtctkException::RtctkException
RtctkException() noexcept
Definition: exceptions.cpp:99
rtctk::componentFramework::InitialisationException::InitialisationException
InitialisationException(const std::string &message)
Definition: exceptions.cpp:155
rtctk::componentFramework::BufferTooSmall::m_expected
std::size_t m_expected
Definition: exceptions.hpp:263
rtctk::componentFramework::Args
detail::Args Args
Definition: rtcComponentMain.hpp:37
rtctk::componentFramework
Definition: commandReplier.cpp:20
rtctk::componentFramework::WrapWithNested
auto WrapWithNested(E &&exception) noexcept(std::is_nothrow_constructible_v< detail::UnspecifiedNested< typename std::decay_t< E >>, E && >)
Constructs an unspecified exception that derives from both the provided object and std::nested_except...
Definition: exceptions.hpp:116
rtctk::componentFramework::RtctkException
The RtctkException class is the base class for all Rtctk exceptions.
Definition: exceptions.hpp:207
rtctk::componentFramework::NestedExceptionPrinter
Adapter object intended to be used in contexts without direct access to the output-stream object.
Definition: exceptions.hpp:157
rtctk::componentFramework::NestedExceptionPrinter::operator<<
friend std::ostream & operator<<(std::ostream &os, NestedExceptionPrinter const &printer)
Formats exception from printer using PrintNestedExceptions.
Definition: exceptions.hpp:188
rtctk::componentFramework::NotImplementedException::NotImplementedException
NotImplementedException(const std::string &feature)
Definition: exceptions.cpp:111
rtctk::componentFramework::UnsupportedTypeException::UnsupportedTypeException
UnsupportedTypeException(const std::string &type)
Definition: exceptions.cpp:118
rtctk::componentFramework::RtctkException::~RtctkException
virtual ~RtctkException() override=default
rtctk::componentFramework::BufferTooSmall::GetActualBufferSize
std::size_t GetActualBufferSize() const
Definition: exceptions.hpp:254
rtctk_config_tool.message
message
Definition: rtctk_config_tool.py:42
rtctk::componentFramework::UnsupportedUriException::UnsupportedUriException
UnsupportedUriException(const elt::mal::Uri &uri)
Definition: exceptions.cpp:134
rtctk::componentFramework::NestedExceptionPrinter::Str
std::string Str() const
Convenience function for constructing a std::string from the exception.
Definition: exceptions.hpp:175
rtctk::componentFramework::NestedExceptionPrinter::NestedExceptionPrinter
NestedExceptionPrinter(std::exception const &exception) noexcept
Construct from exception derived from std::exception.
Definition: exceptions.hpp:162
rtctk::componentFramework::InitialisationException
Thrown in cases where an initialisation routine has failed.
Definition: exceptions.hpp:276
rtctk::componentFramework::BufferTooSmall
The BufferTooSmall is thrown when an API call fails because the provided buffer is not big enough to ...
Definition: exceptions.hpp:251
std
Definition: mudpiProcessingError.hpp:119
rtctk::componentFramework::BufferTooSmall::m_actual
std::size_t m_actual
Definition: exceptions.hpp:262
rtctk::componentFramework::InvalidArgumentException::InvalidArgumentException
InvalidArgumentException(const std::string &message)
Definition: exceptions.cpp:149
rtctk::componentFramework::BufferTooSmall::GetExpectedBufferSize
std::size_t GetExpectedBufferSize() const
Definition: exceptions.hpp:257
rtctk::componentFramework::BufferTooSmall::BufferTooSmall
BufferTooSmall(const std::size_t actual, const std::size_t expected)
Definition: exceptions.cpp:140
rtctk::componentFramework::detail::UnspecifiedNested::UnspecifiedNested
UnspecifiedNested(E &&e) noexcept(std::is_nothrow_constructible_v< T, E && >)
Definition: exceptions.hpp:82
rtctk::componentFramework::UnsupportedUriException
The UnsupportedUriException is thrown whenever an attempt is made to use an unsupported URI in the RT...
Definition: exceptions.hpp:242
rtctk_config_tool.type
type
List all available datapoint paths under a given path hierarchy.
Definition: rtctk_config_tool.py:44
rtctk::componentFramework::InvalidArgumentException
Definition: exceptions.hpp:266
rtctkExampleDataTaskGenFitsData.filename
filename
Definition: rtctkExampleDataTaskGenFitsData.py:11