Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

329 рядки
8.8 KiB

  1. #pragma once
  2. #include <string>
  3. #include <cstdint>
  4. #include <iomanip>
  5. #include <string.h>
  6. #include <execinfo.h>
  7. #include "flags.h"
  8. namespace cppcore
  9. {
  10. template<size_t N>
  11. struct stack_trace
  12. {
  13. public:
  14. enum class print_flag
  15. {
  16. print_trace, //!< print the stack trace
  17. print_number, //!< add a number before the stack entry
  18. resolve_symbol, //!< resolve the symbol
  19. resolve_filename, //!< resolve the filename
  20. };
  21. using print_flags = shifted_flags<print_flag>;
  22. private:
  23. using symbols = std::unique_ptr<char*, decltype(&free)>;
  24. private:
  25. void* _stack[N]; //!< Stack addresses.
  26. size_t _stack_size; //!< Number of elements actually stored in _stack.
  27. mutable symbols _symbols; //!< List of resolved symbols.
  28. public:
  29. static const size_t max_stack_size = N;
  30. /**
  31. * @brief Constructor.
  32. */
  33. inline stack_trace();
  34. /**
  35. * @brief Move constructor.
  36. */
  37. inline stack_trace(stack_trace&& other);
  38. /**
  39. * @brief Copy constructor.
  40. */
  41. inline stack_trace(const stack_trace& other);
  42. /**
  43. * @brief Move assignment constructor.
  44. */
  45. inline stack_trace& operator=(stack_trace&& other);
  46. /**
  47. * @brief Copy assigment constructor.
  48. */
  49. inline stack_trace& operator=(const stack_trace& other);
  50. /**
  51. * @brief Get the number of stack entries.
  52. */
  53. inline size_t size() const;
  54. /**
  55. * @brief Get the stack entry at the given index.
  56. */
  57. inline void* address(size_t index) const;
  58. /**
  59. * @brief Get the symbol at the given index.
  60. */
  61. inline const char* symbol(size_t index) const;
  62. /**
  63. * @brief Get the filename at the given index.
  64. */
  65. inline std::string filename(size_t index) const;
  66. /**
  67. * @brief Print the whole stack trace to the passed stream.
  68. *
  69. * @param[in] os Stream to print exception to.
  70. * @param[in] flags Flags to use for printing.
  71. */
  72. inline void print(
  73. std::ostream& os,
  74. const print_flags& flags) const;
  75. /**
  76. * @brief Convert the stack trace to string.
  77. *
  78. * @param[in] flags Flags to use for printing.
  79. *
  80. * @return String representation of the exception.
  81. */
  82. inline std::string print(
  83. const print_flags& flags) const;
  84. /**
  85. * @brief Print the whole stack trace to the passed stream.
  86. *
  87. * @param[in] os Stream to print exception to.
  88. * @param[in] index Index of trace element to print.
  89. * @param[in] flags Flags to use for printing.
  90. */
  91. inline void print(
  92. std::ostream& os,
  93. size_t index,
  94. const print_flags& flags) const;
  95. /**
  96. * @brief Convert the stack trace to string.
  97. *
  98. * @param[in] index Index of trace element to print.
  99. * @param[in] flags Flags to use for printing.
  100. *
  101. * @return String representation of the exception.
  102. */
  103. inline std::string print(
  104. size_t index,
  105. const print_flags& flags) const;
  106. };
  107. /**
  108. * @brief Basic exception with stack trace and some more small features.
  109. */
  110. struct exception
  111. : public std::exception
  112. {
  113. public:
  114. static constexpr size_t max_stack_size = 15;
  115. using stack_trace = cppcore::stack_trace<max_stack_size>;
  116. using print_flag = typename stack_trace::print_flag;
  117. using print_flags = typename stack_trace::print_flags;
  118. /**
  119. * @brief Get the default exception print flags.
  120. */
  121. static inline const print_flags& default_print_flags();
  122. /**
  123. * @brief Print the exception to the passed stream;
  124. *
  125. * @param[in] os Stream to print exception to.
  126. * @param[in] ex Exception to print to stream.
  127. *
  128. * @return The stream received as parameter (for further processing).
  129. */
  130. inline friend std::ostream& operator <<(std::ostream& os, const exception& ex);
  131. private:
  132. mutable bool _msg_cache_empty; //!< Indicates if the message cache was created or not.
  133. mutable std::string _msg_cache; //!< Caches the message of the exception.
  134. public:
  135. std::string message; //!< message of the exception
  136. stack_trace trace; //!< stack trace
  137. public:
  138. /**
  139. * @brief Default constructor.
  140. */
  141. inline exception();
  142. /**
  143. * @brief Constructor to create an exception.
  144. */
  145. inline exception(std::string msg);
  146. /**
  147. * @brief Destructor.
  148. */
  149. virtual inline ~exception() = default;
  150. /**
  151. * @brief Print the whole exception to the passed stream.
  152. *
  153. * @param[in] os Stream to print exception to.
  154. * @param[in] flags Flags to use for printing.
  155. */
  156. inline void print(
  157. std::ostream& os,
  158. const stack_trace::print_flags& flags = default_print_flags()) const;
  159. /**
  160. * @brief Convert the exception to string.
  161. *
  162. * @param[in] flags Flags to use for printing.
  163. *
  164. * @return String representation of the exception.
  165. */
  166. inline std::string print(
  167. const stack_trace::print_flags& flags = default_print_flags()) const;
  168. /**
  169. * @brief Convert the exception to a string.
  170. */
  171. inline const std::string& to_string() const;
  172. /**
  173. * @brief Get the message of the exception as c-string.
  174. */
  175. inline const char* what() const throw() override;
  176. protected:
  177. /**
  178. * @brief Print the message of the exception to the passed stream.
  179. *
  180. * @param[in] os Stream to print message of the exception to.
  181. */
  182. virtual inline void print_message(std::ostream& os) const;
  183. };
  184. /**
  185. * @brief Error exception. Wrapps the errors from the operating system.
  186. */
  187. struct error_exception
  188. : public exception
  189. {
  190. public:
  191. int error; //!< Error received from the operating system
  192. public:
  193. /**
  194. * @brief Constructor to create a error exception.
  195. *
  196. * @param[in] e Error code received from the operating system.
  197. */
  198. inline error_exception(int e);
  199. /**
  200. * @brief Constructor to create a error exception.
  201. *
  202. * @param[in] msg Message of the error exception.
  203. * @param[in] e Error code received from the operating system.
  204. */
  205. inline error_exception(const std::string& msg, int e);
  206. };
  207. /**
  208. * @brief Range exception.
  209. */
  210. struct range_exception
  211. : public exception
  212. {
  213. public:
  214. size_t min; //!< minimum valid value of the range
  215. size_t max; //!< maximum valid value of the range
  216. size_t index; //!< actual index that was used
  217. public:
  218. /**
  219. * @brief Constructor to create a range exception.
  220. */
  221. inline range_exception(size_t mi, size_t ma, size_t idx, std::string msg = "");
  222. protected:
  223. /**
  224. * @brief Print the message of the exception to the passed stream.
  225. *
  226. * @param[in] os Stream to print message of the exception to.
  227. */
  228. inline void print_message(std::ostream& os) const override;
  229. };
  230. /**
  231. * @brief Argument exception.
  232. */
  233. struct argument_exception
  234. : public exception
  235. {
  236. public:
  237. std::string argument; //!< argument that caused the exception
  238. public:
  239. /**
  240. * @brief Constructor to create the argument exception.
  241. *
  242. * @param[in] arg Argument that caused the exception.
  243. * @param[in] msg Message of the exception.
  244. */
  245. inline argument_exception(std::string arg, std::string msg = "");
  246. protected:
  247. /**
  248. * @brief Print the message of the exception to the passed stream.
  249. *
  250. * @param[in] os Stream to print message of the exception to.
  251. */
  252. inline void print_message(std::ostream& os) const override;
  253. };
  254. /**
  255. * @brief Invalid operation exception.
  256. */
  257. struct invalid_operation_exception
  258. : public exception
  259. {
  260. using exception::exception;
  261. };
  262. /**
  263. * @brief Convert exception.
  264. */
  265. struct convert_exception
  266. : public exception
  267. {
  268. using exception::exception;
  269. };
  270. }
  271. #include "exception.inl"