exception.hpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. #ifndef GI_EXCEPTION_HPP
  2. #define GI_EXCEPTION_HPP
  3. #include "base.hpp"
  4. #include "wrap.hpp"
  5. #include <exception>
  6. #include <glib.h>
  7. namespace gi
  8. {
  9. namespace detail
  10. {
  11. inline std::logic_error
  12. transform_error(GType tp, const char *name = nullptr)
  13. {
  14. auto n = g_type_name(tp);
  15. auto msg = std::string("could not transform value to type ") +
  16. detail::make_string(n);
  17. if (name)
  18. msg += std::string(" of property \'") + name + "\'";
  19. return std::invalid_argument(msg);
  20. }
  21. inline std::logic_error
  22. unknown_property_error(GType tp, const gchar *property)
  23. {
  24. auto n = g_type_name(tp);
  25. auto msg = std::string("object of type ") + detail::make_string(n) +
  26. " does not have property \'" + detail::make_string(property) +
  27. "\'";
  28. return std::invalid_argument(msg);
  29. }
  30. inline std::logic_error
  31. unknown_signal_error(GType tp, const std::string &name)
  32. {
  33. auto n = g_type_name(tp);
  34. auto msg = std::string("object of type ") + detail::make_string(n) +
  35. " does not have signal \'" + name + "\'";
  36. return std::invalid_argument(msg);
  37. }
  38. inline std::logic_error
  39. invalid_signal_callback_error(
  40. GType tp, const std::string &name, const std::string &_msg)
  41. {
  42. auto n = g_type_name(tp);
  43. auto msg = std::string("invalid callback for signal ") + n + "::" + name +
  44. "; " + _msg;
  45. return std::invalid_argument(msg);
  46. }
  47. // partially generated GError wrapper
  48. class Error : public gi::detail::GBoxedWrapperBase<Error, GError>
  49. {
  50. typedef gi::detail::GBoxedWrapperBase<Error, GError> super_type;
  51. public:
  52. Error(GError *obj = nullptr) : super_type(obj) {}
  53. static GType get_type_() G_GNUC_CONST { return g_error_get_type(); }
  54. // use with care; dangling reference caution applies here
  55. gint &code_() { return gobj_()->code; }
  56. const gint &code_() const { return gobj_()->code; }
  57. // use with care; dangling reference caution applies here
  58. gi::cstring_v message_() const { return gobj_()->message; }
  59. // gboolean g_error_matches (const GError* error, GQuark domain, gint code);
  60. inline bool matches(GQuark domain, gint code) const
  61. {
  62. return g_error_matches(gobj_(), domain, code);
  63. }
  64. }; // class
  65. } // namespace detail
  66. namespace repository
  67. {
  68. namespace GLib
  69. {
  70. class Error_Ref;
  71. class Error
  72. : public std::runtime_error,
  73. public detail::GBoxedWrapper<Error, ::GError, detail::Error, Error_Ref>
  74. {
  75. typedef std::runtime_error super;
  76. static inline std::string make_message(GError *error)
  77. {
  78. return error ? detail::make_string(g_quark_to_string(error->domain)) +
  79. ": " + detail::make_string(error->message) + "(" +
  80. std::to_string(error->code) + ")"
  81. : "";
  82. }
  83. public:
  84. explicit Error(GError *obj = nullptr) : super(make_message(obj))
  85. {
  86. data_ = obj;
  87. }
  88. // GError* g_error_new_literal (GQuark domain, gint code, const gchar*
  89. // message);
  90. static inline Error new_literal(
  91. GQuark domain, gint code, const std::string &message)
  92. {
  93. return Error(g_error_new_literal(
  94. domain, code, gi::unwrap(message, gi::transfer_none)));
  95. }
  96. // GError* g_error_copy (const GError* error);
  97. inline Error copy() const { return Error(g_error_copy(gobj_())); }
  98. // override wrap since we are no longer in a simple single-base case
  99. template<typename Cpp, typename Enable = typename std::enable_if<
  100. std::is_base_of<Error, Cpp>::value>::type>
  101. static Cpp wrap(const typename Cpp::BaseObjectType *obj)
  102. {
  103. static_assert(sizeof(Cpp) == sizeof(Error), "type wrap not supported");
  104. Error w(const_cast<GError *>(obj));
  105. return std::move(*static_cast<Cpp *>(&w));
  106. }
  107. };
  108. class Error_Ref
  109. : public gi::detail::GBoxedRefWrapper<GLib::Error, ::GError, detail::Error>
  110. {
  111. typedef gi::detail::GBoxedRefWrapper<GLib::Error, ::GError, detail::Error>
  112. super_type;
  113. using super_type::super_type;
  114. // GError* g_error_copy (const GError* error);
  115. inline Error copy() const { return Error(g_error_copy(gobj_())); }
  116. };
  117. } // namespace GLib
  118. template<>
  119. struct declare_cpptype_of<GError>
  120. {
  121. typedef GLib::Error type;
  122. };
  123. } // namespace repository
  124. inline void
  125. check_error(GError *error)
  126. {
  127. if (error)
  128. detail::try_throw(repository::GLib::Error(error));
  129. }
  130. namespace detail
  131. {
  132. inline repository::GLib::Error
  133. missing_symbol_error(const std::string &symbol)
  134. {
  135. ::GQuark domain = g_quark_from_static_string("gi-error-quark");
  136. auto error =
  137. g_error_new(domain, 0, "could not find symbol %s", symbol.c_str());
  138. return repository::GLib::Error(error);
  139. }
  140. } // namespace detail
  141. // exception specification is generated according to settings and situation
  142. // some derived code (e.g. overrides) may need to follow suit accordingly
  143. #if GI_EXPECTED
  144. // no exception if reported through expected
  145. #define GI_NOEXCEPT_DECL(nonthrowing) noexcept
  146. #elif GI_DL
  147. // otherwise, everything can start failing if resolved at runtime
  148. #define GI_NOEXCEPT_DECL(nonthrowing)
  149. #else
  150. // otherwise, depends on whether (wrapped) function is (GError) throwing
  151. #define GI_NOEXCEPT_DECL(nonthrowing) noexcept(nonthrowing)
  152. #endif
  153. } // namespace gi
  154. #endif // GI_EXCEPTION_HPP