1 /* Copyright 2002 The gtkmm Development Team
2 *
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17 #include <glibmm/value.h>
18 #include <glibmm/objectbase.h>
19 #include <glibmm/utility.h>
20 #include <glibmm/vectorutils.h>
21 #include <glibmm/wrap.h>
22 #include <cstring> // std::memset()
23
24 namespace Glib
25 {
26
27 /**** Glib::ValueBase ******************************************************/
28
ValueBase()29 ValueBase::ValueBase()
30 {
31 std::memset(&gobject_, 0, sizeof(GValue));
32 }
33
34 void
init(GType type)35 ValueBase::init(GType type)
36 {
37 g_value_init(&gobject_, type);
38 }
39
40 void
init(const GValue * value)41 ValueBase::init(const GValue* value)
42 {
43 g_value_init(&gobject_, G_VALUE_TYPE(value));
44
45 if (value)
46 g_value_copy(value, &gobject_);
47 }
48
ValueBase(const ValueBase & other)49 ValueBase::ValueBase(const ValueBase& other)
50 {
51 std::memset(&gobject_, 0, sizeof(GValue));
52
53 g_value_init(&gobject_, G_VALUE_TYPE(&other.gobject_));
54 g_value_copy(&other.gobject_, &gobject_);
55 }
56
57 ValueBase&
operator =(const ValueBase & other)58 ValueBase::operator=(const ValueBase& other)
59 {
60 // g_value_copy() prevents self-assignment and deletes the destination.
61 g_value_copy(&other.gobject_, &gobject_);
62 return *this;
63 }
64
~ValueBase()65 ValueBase::~ValueBase() noexcept
66 {
67 g_value_unset(&gobject_);
68 }
69
70 void
reset()71 ValueBase::reset()
72 {
73 g_value_reset(&gobject_);
74 }
75
76 /**** Glib::ValueBase_Boxed ************************************************/
77
78 // static
79 GType
value_type()80 ValueBase_Boxed::value_type()
81 {
82 return G_TYPE_BOXED;
83 }
84
85 void
set_boxed(const void * data)86 ValueBase_Boxed::set_boxed(const void* data)
87 {
88 g_value_set_boxed(&gobject_, data);
89 }
90
91 void*
get_boxed() const92 ValueBase_Boxed::get_boxed() const
93 {
94 return g_value_get_boxed(&gobject_);
95 }
96
97 GParamSpec*
create_param_spec(const Glib::ustring & name) const98 ValueBase_Boxed::create_param_spec(const Glib::ustring& name) const
99 {
100 return create_param_spec(name, Glib::ustring(), Glib::ustring(),
101 static_cast<Glib::ParamFlags>(G_PARAM_READABLE | G_PARAM_WRITABLE));
102 }
103
create_param_spec(const Glib::ustring & name,const Glib::ustring & nick,const Glib::ustring & blurb,Glib::ParamFlags flags) const104 GParamSpec* ValueBase_Boxed::create_param_spec(const Glib::ustring& name,
105 const Glib::ustring& nick, const Glib::ustring& blurb, Glib::ParamFlags flags) const
106 {
107 return g_param_spec_boxed(
108 name.c_str(), c_str_or_nullptr(nick), c_str_or_nullptr(blurb),
109 G_VALUE_TYPE(&gobject_), static_cast<GParamFlags>(flags));
110 }
111
112 /**** Glib::ValueBase_Object ***********************************************/
113
114 // static
115 GType
value_type()116 ValueBase_Object::value_type()
117 {
118 return G_TYPE_OBJECT;
119 }
120
121 void
set_object(Glib::ObjectBase * data)122 ValueBase_Object::set_object(Glib::ObjectBase* data)
123 {
124 g_value_set_object(&gobject_, (data) ? data->gobj() : nullptr);
125 }
126
127 Glib::ObjectBase*
get_object() const128 ValueBase_Object::get_object() const
129 {
130 GObject* const data = static_cast<GObject*>(g_value_get_object(&gobject_));
131 return Glib::wrap_auto(data, false);
132 }
133
134 Glib::RefPtr<Glib::ObjectBase>
get_object_copy() const135 ValueBase_Object::get_object_copy() const
136 {
137 GObject* const data = static_cast<GObject*>(g_value_get_object(&gobject_));
138 return Glib::RefPtr<Glib::ObjectBase>(Glib::wrap_auto(data, true));
139 }
140
141 GParamSpec*
create_param_spec(const Glib::ustring & name) const142 ValueBase_Object::create_param_spec(const Glib::ustring& name) const
143 {
144 return create_param_spec(name, Glib::ustring(), Glib::ustring(),
145 static_cast<Glib::ParamFlags>(G_PARAM_READABLE | G_PARAM_WRITABLE));
146 }
147
148 GParamSpec*
create_param_spec(const Glib::ustring & name,const Glib::ustring & nick,const Glib::ustring & blurb,Glib::ParamFlags flags) const149 ValueBase_Object::create_param_spec(const Glib::ustring& name,
150 const Glib::ustring& nick, const Glib::ustring& blurb, Glib::ParamFlags flags) const
151 {
152 // Glib::Value_Pointer<> derives from Glib::ValueBase_Object, because
153 // we don't know beforehand whether a certain type is derived from
154 // Glib::Object or not. To keep create_param_spec() out of the template
155 // struggle, we dispatch here at runtime.
156
157 if (G_VALUE_HOLDS_OBJECT(&gobject_))
158 {
159 return g_param_spec_object(name.c_str(), c_str_or_nullptr(nick), c_str_or_nullptr(blurb),
160 G_VALUE_TYPE(&gobject_), static_cast<GParamFlags>(flags));
161 }
162 else
163 {
164 g_return_val_if_fail(G_VALUE_HOLDS_POINTER(&gobject_), nullptr);
165
166 return g_param_spec_pointer(
167 name.c_str(), c_str_or_nullptr(nick), c_str_or_nullptr(blurb),
168 static_cast<GParamFlags>(flags));
169 }
170 }
171
172 /**** Glib::ValueBase_Enum *************************************************/
173
174 // static
175 GType
value_type()176 ValueBase_Enum::value_type()
177 {
178 return G_TYPE_ENUM;
179 }
180
181 void
set_enum(int data)182 ValueBase_Enum::set_enum(int data)
183 {
184 g_value_set_enum(&gobject_, data);
185 }
186
187 int
get_enum() const188 ValueBase_Enum::get_enum() const
189 {
190 return g_value_get_enum(&gobject_);
191 }
192
193 GParamSpec*
create_param_spec(const Glib::ustring & name) const194 ValueBase_Enum::create_param_spec(const Glib::ustring& name) const
195 {
196 return create_param_spec(name, Glib::ustring(), Glib::ustring(),
197 static_cast<Glib::ParamFlags>(G_PARAM_READABLE | G_PARAM_WRITABLE));
198 }
199
200 GParamSpec*
create_param_spec(const Glib::ustring & name,const Glib::ustring & nick,const Glib::ustring & blurb,Glib::ParamFlags flags) const201 ValueBase_Enum::create_param_spec(const Glib::ustring& name,
202 const Glib::ustring& nick, const Glib::ustring& blurb, Glib::ParamFlags flags) const
203 {
204 return g_param_spec_enum(
205 name.c_str(), c_str_or_nullptr(nick), c_str_or_nullptr(blurb), G_VALUE_TYPE(&gobject_),
206 g_value_get_enum(&gobject_), static_cast<GParamFlags>(flags));
207 }
208
209 /**** Glib::ValueBase_Flags ************************************************/
210
211 // static
212 GType
value_type()213 ValueBase_Flags::value_type()
214 {
215 return G_TYPE_FLAGS;
216 }
217
218 void
set_flags(unsigned int data)219 ValueBase_Flags::set_flags(unsigned int data)
220 {
221 g_value_set_flags(&gobject_, data);
222 }
223
224 unsigned int
get_flags() const225 ValueBase_Flags::get_flags() const
226 {
227 return g_value_get_flags(&gobject_);
228 }
229
230 GParamSpec*
create_param_spec(const Glib::ustring & name) const231 ValueBase_Flags::create_param_spec(const Glib::ustring& name) const
232 {
233 return create_param_spec(name, Glib::ustring(), Glib::ustring(),
234 static_cast<Glib::ParamFlags>(G_PARAM_READABLE | G_PARAM_WRITABLE));
235 }
236
create_param_spec(const Glib::ustring & name,const Glib::ustring & nick,const Glib::ustring & blurb,Glib::ParamFlags flags) const237 GParamSpec* ValueBase_Flags::create_param_spec(const Glib::ustring& name,
238 const Glib::ustring& nick, const Glib::ustring& blurb, Glib::ParamFlags flags) const
239 {
240 return g_param_spec_flags(name.c_str(), c_str_or_nullptr(nick), c_str_or_nullptr(blurb),
241 G_VALUE_TYPE(&gobject_), g_value_get_flags(&gobject_), static_cast<GParamFlags>(flags));
242 }
243
244 /**** Glib::ValueBase_String ***********************************************/
245
246 // static
247 GType
value_type()248 ValueBase_String::value_type()
249 {
250 return G_TYPE_STRING;
251 }
252
253 void
set_cstring(const char * data)254 ValueBase_String::set_cstring(const char* data)
255 {
256 g_value_set_string(&gobject_, data);
257 }
258
259 const char*
get_cstring() const260 ValueBase_String::get_cstring() const
261 {
262 if (const char* const data = g_value_get_string(&gobject_))
263 return data;
264 else
265 return "";
266 }
267
268 GParamSpec*
create_param_spec(const Glib::ustring & name) const269 ValueBase_String::create_param_spec(const Glib::ustring& name) const
270 {
271 return create_param_spec(name, Glib::ustring(), Glib::ustring(),
272 static_cast<Glib::ParamFlags>(G_PARAM_READABLE | G_PARAM_WRITABLE));
273 }
274
275 GParamSpec*
create_param_spec(const Glib::ustring & name,const Glib::ustring & nick,const Glib::ustring & blurb,Glib::ParamFlags flags) const276 ValueBase_String::create_param_spec(const Glib::ustring& name,
277 const Glib::ustring& nick, const Glib::ustring& blurb, Glib::ParamFlags flags) const
278 {
279 return g_param_spec_string(name.c_str(), c_str_or_nullptr(nick), c_str_or_nullptr(blurb),
280 get_cstring(), static_cast<GParamFlags>(flags));
281 }
282
283 /**** Glib::ValueBase_Variant ************************************************/
284
285 // static
value_type()286 GType ValueBase_Variant::value_type()
287 {
288 return G_TYPE_VARIANT;
289 }
290
set_variant(GVariant * data)291 void ValueBase_Variant::set_variant(GVariant* data)
292 {
293 g_value_set_variant(&gobject_, data);
294 }
295
get_variant() const296 GVariant* ValueBase_Variant::get_variant() const
297 {
298 return g_value_get_variant(&gobject_);
299 }
300
create_param_spec(const Glib::ustring & name,const Glib::ustring & nick,const Glib::ustring & blurb,Glib::ParamFlags flags) const301 GParamSpec* ValueBase_Variant::create_param_spec(const Glib::ustring& name,
302 const Glib::ustring& nick, const Glib::ustring& blurb, Glib::ParamFlags flags) const
303 {
304 GVariant* gvariant = g_value_get_variant(&gobject_);
305 const GVariantType* gvariant_type = gvariant ? g_variant_get_type(gvariant) : G_VARIANT_TYPE_ANY;
306
307 return g_param_spec_variant(
308 name.c_str(), c_str_or_nullptr(nick), c_str_or_nullptr(blurb),
309 gvariant_type, gvariant, static_cast<GParamFlags>(flags));
310 }
311
312 /**** Glib::Value<std::string> *********************************************/
313
314 void
set(const std::string & data)315 Value<std::string>::set(const std::string& data)
316 {
317 g_value_set_string(&gobject_, data.c_str());
318 }
319
320 /**** Glib::Value<Glib::ustring> *******************************************/
321
322 void
set(const Glib::ustring & data)323 Value<Glib::ustring>::set(const Glib::ustring& data)
324 {
325 g_value_set_string(&gobject_, data.c_str());
326 }
327
328 /**** Glib::Value<std::vector<std::string>> ********************************/
329
330 // static
value_type()331 GType Value<std::vector<std::string>>::value_type()
332 {
333 return G_TYPE_STRV;
334 }
335
set(const CppType & data)336 void Value<std::vector<std::string>>::set(const CppType& data)
337 {
338 set_boxed(Glib::ArrayHandler<std::string>::vector_to_array(data).data());
339 }
340
get() const341 std::vector<std::string> Value<std::vector<std::string>>::get() const
342 {
343 return Glib::ArrayHandler<std::string>::array_to_vector(
344 static_cast<const char* const*>(get_boxed()), Glib::OWNERSHIP_NONE);
345 }
346
347 /**** Glib::Value<std::vector<Glib::ustring>> ********************************/
348
349 // static
value_type()350 GType Value<std::vector<Glib::ustring>>::value_type()
351 {
352 return G_TYPE_STRV;
353 }
354
set(const CppType & data)355 void Value<std::vector<Glib::ustring>>::set(const CppType& data)
356 {
357 set_boxed(Glib::ArrayHandler<Glib::ustring>::vector_to_array(data).data());
358 }
359
get() const360 std::vector<Glib::ustring> Value<std::vector<Glib::ustring>>::get() const
361 {
362 return Glib::ArrayHandler<Glib::ustring>::array_to_vector(
363 static_cast<const char* const*>(get_boxed()), Glib::OWNERSHIP_NONE);
364 }
365
366 } // namespace Glib
367