File: exception.hpp

package info (click to toggle)
cppgir 2.0%2Bgit20240928.c8bb1c6%2Breally2.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,228 kB
  • sloc: cpp: 14,307; ansic: 339; makefile: 11; sh: 9
file content (185 lines) | stat: -rw-r--r-- 5,133 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#ifndef GI_EXCEPTION_HPP
#define GI_EXCEPTION_HPP

#include "base.hpp"
#include "wrap.hpp"

#include <exception>
#include <glib.h>

namespace gi
{
namespace detail
{
inline std::logic_error
transform_error(GType tp, const char *name = nullptr)
{
  auto n = g_type_name(tp);
  auto msg = std::string("could not transform value to type ") +
             detail::make_string(n);
  if (name)
    msg += std::string(" of property \'") + name + "\'";
  return std::invalid_argument(msg);
}

inline std::logic_error
unknown_property_error(GType tp, const gchar *property)
{
  auto n = g_type_name(tp);
  auto msg = std::string("object of type ") + detail::make_string(n) +
             " does not have property \'" + detail::make_string(property) +
             "\'";
  return std::invalid_argument(msg);
}

inline std::logic_error
unknown_signal_error(GType tp, const std::string &name)
{
  auto n = g_type_name(tp);
  auto msg = std::string("object of type ") + detail::make_string(n) +
             " does not have signal \'" + name + "\'";
  return std::invalid_argument(msg);
}

inline std::logic_error
invalid_signal_callback_error(
    GType tp, const std::string &name, const std::string &_msg)
{
  auto n = g_type_name(tp);
  auto msg = std::string("invalid callback for signal ") + n + "::" + name +
             "; " + _msg;
  return std::invalid_argument(msg);
}

// partially generated GError wrapper
class Error : public gi::detail::GBoxedWrapperBase<Error, GError>
{
  typedef gi::detail::GBoxedWrapperBase<Error, GError> super_type;

public:
  Error(GError *obj = nullptr) : super_type(obj) {}

  static GType get_type_() G_GNUC_CONST { return g_error_get_type(); }

  // use with care; dangling reference caution applies here
  gint &code_() { return gobj_()->code; }
  const gint &code_() const { return gobj_()->code; }

  // use with care; dangling reference caution applies here
  gi::cstring_v message_() const { return gobj_()->message; }

  // gboolean g_error_matches (const GError* error, GQuark domain, gint code);
  inline bool matches(GQuark domain, gint code) const
  {
    return g_error_matches(gobj_(), domain, code);
  }

}; // class

} // namespace detail

namespace repository
{
namespace GLib
{
class Error_Ref;

class Error
    : public std::runtime_error,
      public detail::GBoxedWrapper<Error, ::GError, detail::Error, Error_Ref>
{
  typedef std::runtime_error super;

  static inline std::string make_message(GError *error)
  {
    return error ? detail::make_string(g_quark_to_string(error->domain)) +
                       ": " + detail::make_string(error->message) + "(" +
                       std::to_string(error->code) + ")"
                 : "";
  }

public:
  explicit Error(GError *obj = nullptr) : super(make_message(obj))
  {
    data_ = obj;
  }

  // GError* g_error_new_literal (GQuark domain, gint code, const gchar*
  // message);
  static inline Error new_literal(
      GQuark domain, gint code, const std::string &message)
  {
    return Error(g_error_new_literal(
        domain, code, gi::unwrap(message, gi::transfer_none)));
  }

  // GError* g_error_copy (const GError* error);
  inline Error copy() const { return Error(g_error_copy(gobj_())); }

  // override wrap since we are no longer in a simple single-base case
  template<typename Cpp, typename Enable = typename std::enable_if<
                             std::is_base_of<Error, Cpp>::value>::type>
  static Cpp wrap(const typename Cpp::BaseObjectType *obj)
  {
    static_assert(sizeof(Cpp) == sizeof(Error), "type wrap not supported");
    Error w(const_cast<GError *>(obj));
    return std::move(*static_cast<Cpp *>(&w));
  }
};

class Error_Ref
    : public gi::detail::GBoxedRefWrapper<GLib::Error, ::GError, detail::Error>
{
  typedef gi::detail::GBoxedRefWrapper<GLib::Error, ::GError, detail::Error>
      super_type;
  using super_type::super_type;

  // GError* g_error_copy (const GError* error);
  inline Error copy() const { return Error(g_error_copy(gobj_())); }
};

} // namespace GLib

template<>
struct declare_cpptype_of<GError>
{
  typedef GLib::Error type;
};

} // namespace repository

inline void
check_error(GError *error)
{
  if (error)
    detail::try_throw(repository::GLib::Error(error));
}

namespace detail
{
inline repository::GLib::Error
missing_symbol_error(const std::string &symbol)
{
  ::GQuark domain = g_quark_from_static_string("gi-error-quark");
  auto error =
      g_error_new(domain, 0, "could not find symbol %s", symbol.c_str());
  return repository::GLib::Error(error);
}
} // namespace detail

// exception specification is generated according to settings and situation
// some derived code (e.g. overrides) may need to follow suit accordingly
#if GI_EXPECTED
// no exception if reported through expected
#define GI_NOEXCEPT_DECL(nonthrowing) noexcept
#elif GI_DL
// otherwise, everything can start failing if resolved at runtime
#define GI_NOEXCEPT_DECL(nonthrowing)
#else
// otherwise, depends on whether (wrapped) function is (GError) throwing
#define GI_NOEXCEPT_DECL(nonthrowing) noexcept(nonthrowing)
#endif

} // namespace gi

#endif // GI_EXCEPTION_HPP