Exception.hpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. #pragma once
  2. #include <stddef.h>
  3. #include <stdint.h>
  4. #include <exception>
  5. #include <string>
  6. #include <vector>
  7. #include <utility>
  8. namespace ARL {
  9. class Exception : public std::exception {
  10. private:
  11. const char* m_SourceFile;
  12. const size_t m_SourceLine;
  13. std::string m_Message;
  14. std::vector<std::string> m_Hints;
  15. public:
  16. template<typename... __ArgTypes>
  17. Exception(const char* SourceFile, size_t SourceLine, const char* Format, __ArgTypes&&... Args) noexcept :
  18. m_SourceFile(SourceFile),
  19. m_SourceLine(SourceLine)
  20. {
  21. if constexpr (sizeof...(Args) == 0) {
  22. m_Message.assign(Format);
  23. } else {
  24. int l;
  25. l = snprintf(nullptr, 0, Format, std::forward<__ArgTypes>(Args)...);
  26. if (l < 0) {
  27. std::terminate();
  28. }
  29. m_Message.resize(l + 1);
  30. l = snprintf(m_Message.data(), m_Message.length(), Format, std::forward<__ArgTypes>(Args)...);
  31. if (l < 0) {
  32. std::terminate();
  33. }
  34. while (m_Message.back() == '\x00') {
  35. m_Message.pop_back();
  36. }
  37. }
  38. }
  39. [[nodiscard]]
  40. auto ExceptionFile() const noexcept {
  41. return m_SourceFile;
  42. }
  43. [[nodiscard]]
  44. auto ExceptionLine() const noexcept {
  45. return m_SourceLine;
  46. }
  47. [[nodiscard]]
  48. auto ExceptionMessage() const noexcept {
  49. return m_Message.c_str();
  50. }
  51. template<typename __HintType>
  52. auto& PushHint(__HintType&& Hint) noexcept { // if an exception is thrown, just suppress and terminate.
  53. m_Hints.emplace_back(std::forward<__HintType>(Hint));
  54. return *this;
  55. }
  56. template<typename... __ArgTypes>
  57. auto& PushFormatHint(const char* Format, __ArgTypes&&... Args) noexcept { // if an exception is thrown, just suppress and terminate.
  58. int l;
  59. std::string s;
  60. l = snprintf(nullptr, 0, Format, std::forward<__ArgTypes>(Args)...);
  61. if (l < 0) {
  62. std::terminate();
  63. }
  64. s.resize(l + 1);
  65. l = snprintf(s.data(), s.length(), Format, std::forward<__ArgTypes>(Args)...);
  66. if (l < 0) {
  67. std::terminate();
  68. }
  69. while (s.back() == '\x00') {
  70. s.pop_back();
  71. }
  72. m_Hints.emplace_back(std::move(s));
  73. return *this;
  74. }
  75. [[nodiscard]]
  76. const auto& Hints() const noexcept {
  77. return m_Hints;
  78. }
  79. [[nodiscard]]
  80. virtual bool HasErrorCode() const noexcept {
  81. return false;
  82. }
  83. [[nodiscard]]
  84. virtual intptr_t ErrorCode() const noexcept {
  85. return 0;
  86. }
  87. [[nodiscard]]
  88. virtual const char* ErrorString() const noexcept {
  89. return nullptr;
  90. }
  91. [[nodiscard]]
  92. // NOLINTNEXTLINE: mark "virtual" explicitly for more readability
  93. virtual const char* what() const noexcept override {
  94. return ExceptionMessage();
  95. }
  96. };
  97. }