1 /* error.cc
2 *
3 * Copyright 2002 The gtkmm Development Team
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <glibmmconfig.h>
20 #include <glibmm/error.h>
21 #include <glibmm/wrap.h>
22 #include <glibmm/wrap_init.h>
23 #include <glib.h>
24 #include <map>
25
26 namespace
27 {
28
29 using ThrowFuncTable = std::map<GQuark, Glib::Error::ThrowFunc>;
30
31 static ThrowFuncTable* throw_func_table = nullptr;
32
33 } // anonymous namespace
34
35 namespace Glib
36 {
37
Error()38 Error::Error() : gobject_(nullptr)
39 {
40 }
41
Error(GQuark error_domain,int error_code,const Glib::ustring & message)42 Error::Error(GQuark error_domain, int error_code, const Glib::ustring& message)
43 : gobject_(g_error_new_literal(error_domain, error_code, message.c_str()))
44 {
45 }
46
Error(GError * gobject,bool take_copy)47 Error::Error(GError* gobject, bool take_copy)
48 : gobject_((take_copy && gobject) ? g_error_copy(gobject) : gobject)
49 {
50 }
51
Error(const Error & other)52 Error::Error(const Error& other)
53 : Exception(other), gobject_((other.gobject_) ? g_error_copy(other.gobject_) : nullptr)
54 {
55 }
56
57 Error&
operator =(const Error & other)58 Error::operator=(const Error& other)
59 {
60 if (gobject_ != other.gobject_)
61 {
62 if (gobject_)
63 {
64 g_error_free(gobject_);
65 gobject_ = nullptr;
66 }
67 if (other.gobject_)
68 {
69 gobject_ = g_error_copy(other.gobject_);
70 }
71 }
72 return *this;
73 }
74
~Error()75 Error::~Error() noexcept
76 {
77 if (gobject_)
78 g_error_free(gobject_);
79 }
80
operator bool() const81 Error::operator bool() const
82 {
83 return gobject_ != nullptr;
84 }
85
86 GQuark
domain() const87 Error::domain() const
88 {
89 g_return_val_if_fail(gobject_ != nullptr, 0);
90
91 return gobject_->domain;
92 }
93
94 int
code() const95 Error::code() const
96 {
97 g_return_val_if_fail(gobject_ != nullptr, -1);
98
99 return gobject_->code;
100 }
101
102 Glib::ustring
what() const103 Error::what() const
104 {
105 g_return_val_if_fail(gobject_ != nullptr, "");
106 g_return_val_if_fail(gobject_->message != nullptr, "");
107
108 return gobject_->message;
109 }
110
111 bool
matches(GQuark error_domain,int error_code) const112 Error::matches(GQuark error_domain, int error_code) const
113 {
114 return g_error_matches(gobject_, error_domain, error_code);
115 }
116
117 GError*
gobj()118 Error::gobj()
119 {
120 return gobject_;
121 }
122
123 const GError*
gobj() const124 Error::gobj() const
125 {
126 return gobject_;
127 }
128
129 void
propagate(GError ** dest)130 Error::propagate(GError** dest)
131 {
132 g_propagate_error(dest, gobject_);
133 gobject_ = nullptr;
134 }
135
136 // static
137 void
register_init()138 Error::register_init()
139 {
140 if (!throw_func_table)
141 {
142 throw_func_table = new ThrowFuncTable();
143 Glib::wrap_register_init();
144 Glib::wrap_init(); // make sure that at least the Glib exceptions are registered
145 }
146 }
147
148 // static
149 void
register_cleanup()150 Error::register_cleanup()
151 {
152 if (throw_func_table)
153 {
154 delete throw_func_table;
155 throw_func_table = nullptr;
156 }
157 }
158
159 // static
160 void
register_domain(GQuark error_domain,Error::ThrowFunc throw_func)161 Error::register_domain(GQuark error_domain, Error::ThrowFunc throw_func)
162 {
163 g_assert(throw_func_table != nullptr);
164
165 (*throw_func_table)[error_domain] = throw_func;
166 }
167
168 // static, noreturn
169 void
throw_exception(GError * gobject)170 Error::throw_exception(GError* gobject)
171 {
172 g_assert(gobject != nullptr);
173
174 // Just in case Gtk::Main hasn't been instantiated yet.
175 if (!throw_func_table)
176 register_init();
177
178 if (const ThrowFunc throw_func = (*throw_func_table)[gobject->domain])
179 {
180 (*throw_func)(gobject);
181 g_assert_not_reached();
182 }
183
184 g_warning("Glib::Error::throw_exception():\n "
185 "unknown error domain '%s': throwing generic Glib::Error exception\n",
186 (gobject->domain) ? g_quark_to_string(gobject->domain) : "(null)");
187
188 // Doesn't copy, because error-returning functions return a newly allocated GError for us.
189 throw Glib::Error(gobject);
190 }
191
192 // Glib::Value<Glib::Error>
value_type()193 GType Value<Error>::value_type()
194 {
195 return g_error_get_type();
196 }
197
set(const CppType & data)198 void Value<Error>::set(const CppType& data)
199 {
200 set_boxed(data.gobj());
201 }
202
get() const203 Value<Error>::CppType Value<Error>::get() const
204 {
205 return Glib::Error(static_cast<CType>(get_boxed()), true);
206 }
207
208 } // namespace Glib
209