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