/workspaces/astro/sol3-sdk/cpp/sol3/log/except.h Source File

Space-ng SDK: /workspaces/astro/sol3-sdk/cpp/sol3/log/except.h Source File
Space-ng SDK
except.h
Go to the documentation of this file.
1 // Copyright (c) Space-ng, inc. All rights reserved.
2 
3 #pragma once
4 #include <boost/stacktrace.hpp>
5 #include <fmt/format.h>
6 #include <fmt/ostream.h>
7 #include <tl/expected.hpp>
8 
9 #include <stdexcept>
10 
11 namespace sol3::log {
12 
19 //
24 //
27 class ExceptionBase : public std::runtime_error {
28  public:
29  explicit ExceptionBase(
30  std::string const& short_message,
31  char const* file_name,
32  int line_number,
33  char const* function_name,
34  boost::stacktrace::stacktrace stacktrace =
35  boost::stacktrace::stacktrace{});
36  std::string short_message;
37  boost::stacktrace::stacktrace stacktrace;
38  char const* file_name;
40  char const* function_name;
41 };
42 
49  public:
51  std::string const& message,
52  char const* file_name,
53  int line_number,
54  char const* function_name,
55  boost::stacktrace::stacktrace stacktrace =
56  boost::stacktrace::stacktrace{});
57 };
58 
62  public:
63  explicit InvalidResource(
64  std::string const& message,
65  char const* file_name,
66  int line_number,
67  char const* function_name,
68  boost::stacktrace::stacktrace stacktrace =
69  boost::stacktrace::stacktrace{});
70 };
71 
72 namespace details {
73 
74 template <class TWrapper, class TException>
75 struct UnwrapImpl {
76  static auto impl(
77  TWrapper&& wrapper, // NOLINT
78  char const* file,
79  int line,
80  char const* func,
81  std::string msg) -> decltype(*std::forward<TWrapper>(wrapper)) {
82  if (!bool(wrapper)) {
83  throw TException(msg, file, line, func);
84  }
85  return *std::forward<TWrapper>(wrapper);
86  }
87 };
88 
91 template <class TT, class TE, class TException>
92 struct UnwrapImpl<tl::expected<TT, TE>, TException> {
93  template <class TExpected>
94  static auto impl(
95  TExpected&& expected,
96  char const* file,
97  int line,
98  char const* func,
99  std::string msg) -> decltype(*std::forward<TExpected>(expected)) {
100  if (!bool(expected)) {
101  msg += fmt::format("\nUnexpected: {}", expected.error());
102  throw TException(msg, file, line, func);
103  }
104  return *std::forward<TExpected>(expected);
105  }
106 };
107 
108 template <class TT, class TE, class TException>
109 struct UnwrapImpl<tl::expected<TT, TE>&, TException>
110  : UnwrapImpl<tl::expected<TT, TE>, TException> {};
111 
112 template <class TT, class TE, class TException>
113 struct UnwrapImpl<tl::expected<TT, TE> const&, TException>
114  : UnwrapImpl<tl::expected<TT, TE>, TException> {};
115 
116 template <class TT, class TE, class TException>
117 struct UnwrapImpl<tl::expected<TT, TE>&&, TException>
118  : UnwrapImpl<tl::expected<TT, TE>, TException> {};
119 
120 template <class TContainer, class TKey, class TException>
122  TContainer& container,
123  TKey const& key,
124  char const* container_cstr,
125  char const* key_cstr,
126  char const* file,
127  int line,
128  char const* func,
129  std::string msg) -> decltype(*(container.find(key))) {
130  auto it = container.find(key);
131  if (it == container.end()) {
132  msg += fmt::format(
133  "SOL3_GET key `{}` (={}) not in associative container `{}` of "
134  "size "
135  "`{}`",
136  key_cstr,
137  key,
138  container_cstr,
139  container.size());
140  throw TException(msg, file, line, func);
141  }
142 
143  return *it;
144 }
145 
146 template <class TContainer, class TException>
148  TContainer& container,
149  size_t index,
150  char const* container_cstr,
151  char const* index_cstr,
152  char const* file,
153  int line,
154  char const* func,
155  std::string msg) -> decltype(container[index]) {
156  if (index >= container.size()) {
157  msg += fmt::format(
158  "SOL3_AT index `{}` (={}) not in contiguous container `{}` of "
159  "size "
160  "`{}`",
161  index_cstr,
162  index,
163  container_cstr,
164  container.size());
165  throw TException(msg, file, line, func);
166  }
167  return container[index];
168 }
169 
170 } // namespace details
171 } // namespace sol3::log
172 
177 #define SOL3_THROW(TException, ...) /* NOLINT*/ \
178  throw TException( \
179  ::fmt::format(__VA_ARGS__), \
180  __FILE__, \
181  __LINE__, \
182  (char const*)(__PRETTY_FUNCTION__))
183 
185 //
191 //
193 //
197 //
198 #define SOL3_UNWRAP_OR_THROW(expression, TException) \
199  ::sol3::log::details::UnwrapImpl<decltype((expression)), TException>::impl( \
200  std::forward<decltype((expression))>(expression), \
201  __FILE__, \
202  __LINE__, \
203  (char const*)(__PRETTY_FUNCTION__), \
204  ::fmt::format( \
205  "[SOL3_UNWRAP_OR_THROW] called unwrap on an invalid `{}`", \
206  #expression))
207 
208 // NOLINTNEXTLINE: macro because we want __FILE__ and __LINE__
209 #define SOL3_UNWRAP(expression) \
210  SOL3_UNWRAP_OR_THROW(expression, ::sol3::log::ContractViolation)
211 
212 // NOLINTNEXTLINE: macro because we want __FILE__ and __LINE__
213 #define SOL3_PANIC(...) \
214  SOL3_THROW( \
215  ::sol3::log::ContractViolation, \
216  "SOL3_PANIC({})", \
217  ::fmt::format(__VA_ARGS__));
218 
222 #define SOL3_EXPECT(condition, ...) \
223  do { \
224  if (!(condition)) { \
225  SOL3_THROW( \
226  ::sol3::log::ContractViolation, \
227  "SOL3_EXPECT({}, {})", \
228  #condition, \
229  ::fmt::format(__VA_ARGS__)); \
230  } \
231  } while (0)
232 
233 #define SOL3_IMPL_EXPECT_OP(symbol, name_str, lhs, rhs, ...) \
234  do { \
235  if (!((lhs)symbol(rhs))) { \
236  SOL3_THROW( \
237  ::sol3::log::ContractViolation, \
238  "SOL3_EXPECT_{}({} {} {})\n{}\nvs.\n{}\n{}", \
239  name_str, \
240  #lhs, \
241  #symbol, \
242  #rhs, \
243  lhs, \
244  rhs, \
245  ::fmt::format(__VA_ARGS__)); \
246  } \
247  } while (false)
248 
252 #define SOL3_EXPECT_EQ(lhs, rhs, ...) /*NOLINT*/ \
253  SOL3_IMPL_EXPECT_OP(==, "EQ", lhs, rhs, __VA_ARGS__)
254 
258 #define SOL3_EXPECT_NE(lhs, rhs, ...) /*NOLINT*/ \
259  SOL3_IMPL_EXPECT_OP(!=, "NE", lhs, rhs, __VA_ARGS__)
260 
264 #define SOL3_EXPECT_LE(lhs, rhs, ...) /*NOLINT*/ \
265  SOL3_IMPL_EXPECT_OP(<=, "LE", lhs, rhs, __VA_ARGS__)
266 
270 #define SOL3_EXPECT_LT(lhs, rhs, ...) /*NOLINT*/ \
271  SOL3_IMPL_EXPECT_OP(<, "LT", lhs, rhs, __VA_ARGS__)
272 
276 #define SOL3_EXPECT_GE(lhs, rhs, ...) /*NOLINT*/ \
277  SOL3_IMPL_EXPECT_OP(>=, "GE", lhs, rhs, __VA_ARGS__)
278 
282 #define SOL3_EXPECT_GT(lhs, rhs, ...) /*NOLINT*/ \
283  SOL3_IMPL_EXPECT_OP(>, "GT", lhs, rhs, __VA_ARGS__)
284 
298 //
299 // NOLINTNEXTLINE: macro because we want __FILE__ and __LINE__
300 #define SOL3_GET_OR_THROW(associative_container, key, TException, ...) \
301  ::sol3::log::details::checkedGetFromAssociativeContainer< \
302  decltype((associative_container)), \
303  decltype((key)), \
304  TException>( \
305  associative_container, \
306  key, \
307  #associative_container, \
308  #key, \
309  __FILE__, \
310  __LINE__, \
311  __func__, /*NOLINT*/ \
312  ::fmt::format(__VA_ARGS__))
313 
322 //
323 // NOLINTNEXTLINE: macro because we want __FILE__ and __LINE__
324 #define SOL3_GET(associative_container, key, ...) \
325  SOL3_GET_OR_THROW( \
326  associative_container, key, ::sol3::log::ContractViolation, __VA_ARGS__)
327 
328 // NOLINTNEXTLINE: macro because we want __FILE__ and __LINE__
329 #define SOL3_AT_OR_THROW(contiguous_container, index, TException, ...) \
330  ::sol3::log::details::checkedAtContiguousContainer< \
331  decltype((contiguous_container)), \
332  TException>( \
333  contiguous_container, \
334  index, \
335  #contiguous_container, \
336  #index, \
337  __FILE__, \
338  __LINE__, \
339  __func__, /*NOLINT*/ \
340  ::fmt::format(__VA_ARGS__))
341 
342 // NOLINTNEXTLINE: macro because we want __FILE__ and __LINE__
343 #define SOL3_AT(contiguous_container, index, ...) \
344  SOL3_AT_OR_THROW( \
345  contiguous_container, \
346  index, \
347  ::sol3::log::ContractViolation, \
348  __VA_ARGS__)
Definition: except.h:48
ContractViolation(std::string const &message, char const *file_name, int line_number, char const *function_name, boost::stacktrace::stacktrace stacktrace=boost::stacktrace::stacktrace{})
Definition: except.h:27
std::string short_message
Definition: except.h:36
char const * function_name
Definition: except.h:40
boost::stacktrace::stacktrace stacktrace
Definition: except.h:37
ExceptionBase(std::string const &short_message, char const *file_name, int line_number, char const *function_name, boost::stacktrace::stacktrace stacktrace=boost::stacktrace::stacktrace{})
char const * file_name
Definition: except.h:38
int line_number
Definition: except.h:39
Definition: except.h:61
InvalidResource(std::string const &message, char const *file_name, int line_number, char const *function_name, boost::stacktrace::stacktrace stacktrace=boost::stacktrace::stacktrace{})
auto checkedGetFromAssociativeContainer(TContainer &container, TKey const &key, char const *container_cstr, char const *key_cstr, char const *file, int line, char const *func, std::string msg) -> decltype(*(container.find(key)))
Definition: except.h:121
auto checkedAtContiguousContainer(TContainer &container, size_t index, char const *container_cstr, char const *index_cstr, char const *file, int line, char const *func, std::string msg) -> decltype(container[index])
Definition: except.h:147
Definition: except.h:11
static auto impl(TExpected &&expected, char const *file, int line, char const *func, std::string msg) -> decltype(*std::forward< TExpected >(expected))
Definition: except.h:94
Definition: except.h:75
static auto impl(TWrapper &&wrapper, char const *file, int line, char const *func, std::string msg) -> decltype(*std::forward< TWrapper >(wrapper))
Definition: except.h:76