1 
2 /* -*- Mode: C; c-basic-offset: 4 -*-
3  * vim: tabstop=4 shiftwidth=4 expandtab
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 <Python.h>
20 #include "pygi-value.h"
21 #include "pygi-struct.h"
22 #include "pygi-basictype.h"
23 #include "pygobject-object.h"
24 #include "pygi-type.h"
25 #include "pygenum.h"
26 #include "pygpointer.h"
27 #include "pygboxed.h"
28 #include "pygflags.h"
29 #include "pygparamspec.h"
30 
31 
32 /* glib 2.62 has started to print warnings for these which can't be disabled selectively, so just copy them here */
33 #define PYGI_TYPE_VALUE_ARRAY (g_value_array_get_type())
34 #define PYGI_IS_PARAM_SPEC_VALUE_ARRAY(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), PYGI_TYPE_VALUE_ARRAY))
35 #define PYGI_PARAM_SPEC_VALUE_ARRAY(pspec)    (G_TYPE_CHECK_INSTANCE_CAST ((pspec), g_param_spec_types[18], GParamSpecValueArray))
36 
37 GIArgument
_pygi_argument_from_g_value(const GValue * value,GITypeInfo * type_info)38 _pygi_argument_from_g_value(const GValue *value,
39                             GITypeInfo *type_info)
40 {
41     GIArgument arg = { 0, };
42 
43     GITypeTag type_tag = g_type_info_get_tag (type_info);
44 
45     /* For the long handling: long can be equivalent to
46        int32 or int64, depending on the architecture, but
47        gi doesn't tell us (and same for ulong)
48     */
49     switch (type_tag) {
50         case GI_TYPE_TAG_BOOLEAN:
51             arg.v_boolean = g_value_get_boolean (value);
52             break;
53         case GI_TYPE_TAG_INT8:
54             arg.v_int8 = g_value_get_schar (value);
55             break;
56         case GI_TYPE_TAG_INT16:
57         case GI_TYPE_TAG_INT32:
58 	    if (g_type_is_a (G_VALUE_TYPE (value), G_TYPE_LONG))
59 		arg.v_int32 = (gint32)g_value_get_long (value);
60 	    else
61 		arg.v_int32 = (gint32)g_value_get_int (value);
62             break;
63         case GI_TYPE_TAG_INT64:
64 	    if (g_type_is_a (G_VALUE_TYPE (value), G_TYPE_LONG))
65 		arg.v_int64 = g_value_get_long (value);
66 	    else
67 		arg.v_int64 = g_value_get_int64 (value);
68             break;
69         case GI_TYPE_TAG_UINT8:
70             arg.v_uint8 = g_value_get_uchar (value);
71             break;
72         case GI_TYPE_TAG_UINT16:
73         case GI_TYPE_TAG_UINT32:
74 	    if (g_type_is_a (G_VALUE_TYPE (value), G_TYPE_ULONG))
75 		arg.v_uint32 = (guint32)g_value_get_ulong (value);
76 	    else
77 		arg.v_uint32 = (guint32)g_value_get_uint (value);
78             break;
79         case GI_TYPE_TAG_UINT64:
80 	    if (g_type_is_a (G_VALUE_TYPE (value), G_TYPE_ULONG))
81 		arg.v_uint64 = g_value_get_ulong (value);
82 	    else
83 		arg.v_uint64 = g_value_get_uint64 (value);
84             break;
85         case GI_TYPE_TAG_UNICHAR:
86             arg.v_uint32 = g_value_get_schar (value);
87             break;
88         case GI_TYPE_TAG_FLOAT:
89             arg.v_float = g_value_get_float (value);
90             break;
91         case GI_TYPE_TAG_DOUBLE:
92             arg.v_double = g_value_get_double (value);
93             break;
94         case GI_TYPE_TAG_GTYPE:
95             arg.v_size = g_value_get_gtype (value);
96             break;
97         case GI_TYPE_TAG_UTF8:
98         case GI_TYPE_TAG_FILENAME:
99             /* Callers are responsible for ensuring the GValue stays alive
100              * long enough for the string to be copied. */
101             arg.v_string = (char *)g_value_get_string (value);
102             break;
103         case GI_TYPE_TAG_GLIST:
104         case GI_TYPE_TAG_GSLIST:
105         case GI_TYPE_TAG_ARRAY:
106         case GI_TYPE_TAG_GHASH:
107             if (G_VALUE_HOLDS_BOXED (value))
108                 arg.v_pointer = g_value_get_boxed (value);
109             else
110                 /* e. g. GSettings::change-event */
111                 arg.v_pointer = g_value_get_pointer (value);
112             break;
113         case GI_TYPE_TAG_INTERFACE:
114         {
115             GIBaseInfo *info;
116             GIInfoType info_type;
117 
118             info = g_type_info_get_interface (type_info);
119             info_type = g_base_info_get_type (info);
120 
121             g_base_info_unref (info);
122 
123             switch (info_type) {
124                 case GI_INFO_TYPE_FLAGS:
125                     arg.v_uint = g_value_get_flags (value);
126                     break;
127                 case GI_INFO_TYPE_ENUM:
128                     arg.v_int = g_value_get_enum (value);
129                     break;
130                 case GI_INFO_TYPE_INTERFACE:
131                 case GI_INFO_TYPE_OBJECT:
132                     if (G_VALUE_HOLDS_PARAM (value))
133                       arg.v_pointer = g_value_get_param (value);
134                     else
135                       arg.v_pointer = g_value_get_object (value);
136                     break;
137                 case GI_INFO_TYPE_BOXED:
138                 case GI_INFO_TYPE_STRUCT:
139                 case GI_INFO_TYPE_UNION:
140                     if (G_VALUE_HOLDS (value, G_TYPE_BOXED)) {
141                         arg.v_pointer = g_value_get_boxed (value);
142                     } else if (G_VALUE_HOLDS (value, G_TYPE_VARIANT)) {
143                         arg.v_pointer = g_value_get_variant (value);
144                     } else if (G_VALUE_HOLDS (value, G_TYPE_POINTER)) {
145                         arg.v_pointer = g_value_get_pointer (value);
146                     } else {
147                         PyErr_Format (PyExc_NotImplementedError,
148                                       "Converting GValue's of type '%s' is not implemented.",
149                                       g_type_name (G_VALUE_TYPE (value)));
150                     }
151                     break;
152                 default:
153                     PyErr_Format (PyExc_NotImplementedError,
154                                   "Converting GValue's of type '%s' is not implemented.",
155                                   g_info_type_to_string (info_type));
156                     break;
157             }
158             break;
159         }
160         case GI_TYPE_TAG_ERROR:
161             arg.v_pointer = g_value_get_boxed (value);
162             break;
163         case GI_TYPE_TAG_VOID:
164             arg.v_pointer = g_value_get_pointer (value);
165             break;
166         default:
167             break;
168     }
169 
170     return arg;
171 }
172 
173 
174 /* Ignore g_value_array deprecations. Although they are deprecated,
175  * we still need to support the marshaling of them in PyGObject.
176  */
177 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
178 
179 static int
pyg_value_array_from_pyobject(GValue * value,PyObject * obj,const GParamSpecValueArray * pspec)180 pyg_value_array_from_pyobject(GValue *value,
181                               PyObject *obj,
182                               const GParamSpecValueArray *pspec)
183 {
184     Py_ssize_t seq_len;
185     GValueArray *value_array;
186     guint len, i;
187 
188     seq_len = PySequence_Length(obj);
189     if (seq_len == -1) {
190         PyErr_Clear();
191         return -1;
192     }
193     len = (guint)seq_len;
194 
195     if (pspec && pspec->fixed_n_elements > 0 && len != pspec->fixed_n_elements)
196         return -1;
197 
198     value_array = g_value_array_new(len);
199 
200     for (i = 0; i < len; ++i) {
201         PyObject *item = PySequence_GetItem(obj, i);
202         GType type;
203 
204         if (! item) {
205             PyErr_Clear();
206             g_value_array_free(value_array);
207             return -1;
208         }
209 
210         if (pspec && pspec->element_spec)
211             type = G_PARAM_SPEC_VALUE_TYPE(pspec->element_spec);
212         else if (item == Py_None)
213             type = G_TYPE_POINTER; /* store None as NULL */
214         else {
215             type = pyg_type_from_object((PyObject*)Py_TYPE(item));
216             if (! type) {
217                 PyErr_Clear();
218                 g_value_array_free(value_array);
219                 Py_DECREF(item);
220                 return -1;
221             }
222         }
223 
224         if (type == G_TYPE_VALUE) {
225             const GValue * item_value = pyg_boxed_get(item, GValue);
226             g_value_array_append(value_array, item_value);
227         } else {
228             GValue item_value = { 0, };
229             int status;
230 
231             g_value_init(&item_value, type);
232             status = (pspec && pspec->element_spec)
233                 ? pyg_param_gvalue_from_pyobject(&item_value, item, pspec->element_spec)
234                 : pyg_value_from_pyobject(&item_value, item);
235             Py_DECREF(item);
236 
237             if (status == -1) {
238                 g_value_array_free(value_array);
239                 g_value_unset(&item_value);
240                 return -1;
241             }
242             g_value_array_append(value_array, &item_value);
243             g_value_unset(&item_value);
244         }
245     }
246 
247     g_value_take_boxed(value, value_array);
248     return 0;
249 }
250 
251 G_GNUC_END_IGNORE_DEPRECATIONS
252 
253 static int
pyg_array_from_pyobject(GValue * value,PyObject * obj)254 pyg_array_from_pyobject(GValue *value,
255                         PyObject *obj)
256 {
257     Py_ssize_t len, i;
258     GArray *array;
259 
260     len = PySequence_Length(obj);
261     if (len == -1) {
262         PyErr_Clear();
263         return -1;
264     }
265 
266     array = g_array_new(FALSE, TRUE, sizeof(GValue));
267 
268     for (i = 0; i < len; ++i) {
269         PyObject *item = PySequence_GetItem(obj, i);
270         GType type;
271         GValue item_value = { 0, };
272         int status;
273 
274         if (! item) {
275             PyErr_Clear();
276             g_array_free(array, FALSE);
277             return -1;
278         }
279 
280         if (item == Py_None)
281             type = G_TYPE_POINTER; /* store None as NULL */
282         else {
283             type = pyg_type_from_object((PyObject*)Py_TYPE(item));
284             if (! type) {
285                 PyErr_Clear();
286                 g_array_free(array, FALSE);
287                 Py_DECREF(item);
288                 return -1;
289             }
290         }
291 
292         g_value_init(&item_value, type);
293         status = pyg_value_from_pyobject(&item_value, item);
294         Py_DECREF(item);
295 
296         if (status == -1) {
297             g_array_free(array, FALSE);
298             g_value_unset(&item_value);
299             return -1;
300         }
301 
302         g_array_append_val(array, item_value);
303     }
304 
305     g_value_take_boxed(value, array);
306     return 0;
307 }
308 
309 /**
310  * pyg_value_from_pyobject_with_error:
311  * @value: the GValue object to store the converted value in.
312  * @obj: the Python object to convert.
313  *
314  * This function converts a Python object and stores the result in a
315  * GValue.  The GValue must be initialised in advance with
316  * g_value_init().  If the Python object can't be converted to the
317  * type of the GValue, then an error is returned.
318  *
319  * Returns: 0 on success, -1 on error.
320  */
321 int
pyg_value_from_pyobject_with_error(GValue * value,PyObject * obj)322 pyg_value_from_pyobject_with_error(GValue *value, PyObject *obj)
323 {
324     GType value_type = G_VALUE_TYPE(value);
325 
326     switch (G_TYPE_FUNDAMENTAL(value_type)) {
327     case G_TYPE_INTERFACE:
328         /* we only handle interface types that have a GObject prereq */
329         if (g_type_is_a(value_type, G_TYPE_OBJECT)) {
330             if (obj == Py_None)
331                 g_value_set_object(value, NULL);
332             else {
333                 if (!PyObject_TypeCheck(obj, &PyGObject_Type)) {
334                     PyErr_SetString(PyExc_TypeError, "GObject is required");
335                     return -1;
336                 }
337                 if (!G_TYPE_CHECK_INSTANCE_TYPE(pygobject_get(obj),
338                         value_type)) {
339                     PyErr_SetString(PyExc_TypeError, "Invalid GObject type for assignment");
340                     return -1;
341                 }
342                 g_value_set_object(value, pygobject_get(obj));
343             }
344         } else {
345             PyErr_SetString(PyExc_TypeError, "Unsupported conversion");
346             return -1;
347         }
348         break;
349     case G_TYPE_CHAR:
350     {
351         gint8 temp;
352         if (pygi_gschar_from_py (obj, &temp)) {
353             g_value_set_schar (value, temp);
354             return 0;
355         } else
356             return -1;
357     }
358     case G_TYPE_UCHAR:
359     {
360         guchar temp;
361         if (pygi_guchar_from_py (obj, &temp)) {
362             g_value_set_uchar (value, temp);
363             return 0;
364         } else
365             return -1;
366     }
367     case G_TYPE_BOOLEAN:
368     {
369         gboolean temp;
370         if (pygi_gboolean_from_py (obj, &temp)) {
371             g_value_set_boolean (value, temp);
372             return 0;
373         } else
374             return -1;
375     }
376     case G_TYPE_INT:
377     {
378         gint temp;
379         if (pygi_gint_from_py (obj, &temp)) {
380             g_value_set_int (value, temp);
381             return 0;
382         } else
383             return -1;
384     }
385     case G_TYPE_UINT:
386     {
387         guint temp;
388         if (pygi_guint_from_py (obj, &temp)) {
389             g_value_set_uint (value, temp);
390             return 0;
391         } else
392             return -1;
393     }
394     case G_TYPE_LONG:
395     {
396         glong temp;
397         if (pygi_glong_from_py (obj, &temp)) {
398             g_value_set_long (value, temp);
399             return 0;
400         } else
401             return -1;
402     }
403     case G_TYPE_ULONG:
404     {
405         gulong temp;
406         if (pygi_gulong_from_py (obj, &temp)) {
407             g_value_set_ulong (value, temp);
408             return 0;
409         } else
410             return -1;
411     }
412     case G_TYPE_INT64:
413     {
414         gint64 temp;
415         if (pygi_gint64_from_py (obj, &temp)) {
416             g_value_set_int64 (value, temp);
417             return 0;
418         } else
419             return -1;
420     }
421     case G_TYPE_UINT64:
422     {
423         guint64 temp;
424         if (pygi_guint64_from_py (obj, &temp)) {
425             g_value_set_uint64 (value, temp);
426             return 0;
427         } else
428             return -1;
429     }
430     case G_TYPE_ENUM:
431     {
432         gint val = 0;
433         if (pyg_enum_get_value(G_VALUE_TYPE(value), obj, &val) < 0) {
434             return -1;
435         }
436         g_value_set_enum(value, val);
437     }
438     break;
439     case G_TYPE_FLAGS:
440     {
441         guint val = 0;
442         if (pyg_flags_get_value(G_VALUE_TYPE(value), obj, &val) < 0) {
443             return -1;
444         }
445         g_value_set_flags(value, val);
446         return 0;
447     }
448     break;
449     case G_TYPE_FLOAT:
450     {
451         gfloat temp;
452         if (pygi_gfloat_from_py (obj, &temp)) {
453             g_value_set_float (value, temp);
454             return 0;
455         } else
456             return -1;
457     }
458     case G_TYPE_DOUBLE:
459     {
460         gdouble temp;
461         if (pygi_gdouble_from_py (obj, &temp)) {
462             g_value_set_double (value, temp);
463             return 0;
464         } else
465             return -1;
466     }
467     case G_TYPE_STRING:
468     {
469         gchar *temp;
470         if (pygi_utf8_from_py (obj, &temp)) {
471             g_value_take_string (value, temp);
472             return 0;
473         } else {
474             /* also allows setting anything implementing __str__ */
475             PyObject* str;
476             PyErr_Clear ();
477             str = PyObject_Str (obj);
478             if (str == NULL)
479                 return -1;
480             if (pygi_utf8_from_py (str, &temp)) {
481                 Py_DECREF (str);
482                 g_value_take_string (value, temp);
483                 return 0;
484             }
485             Py_DECREF (str);
486             return -1;
487         }
488     }
489     case G_TYPE_POINTER:
490         if (obj == Py_None)
491             g_value_set_pointer(value, NULL);
492         else if (PyObject_TypeCheck(obj, &PyGPointer_Type) &&
493                 G_VALUE_HOLDS(value, ((PyGPointer *)obj)->gtype))
494             g_value_set_pointer(value, pyg_pointer_get(obj, gpointer));
495         else if (PyCapsule_CheckExact (obj))
496             g_value_set_pointer(value, PyCapsule_GetPointer (obj, NULL));
497         else if (G_VALUE_HOLDS_GTYPE (value))
498             g_value_set_gtype (value, pyg_type_from_object (obj));
499         else {
500             PyErr_SetString(PyExc_TypeError, "Expected pointer");
501             return -1;
502         }
503         break;
504     case G_TYPE_BOXED: {
505         PyGTypeMarshal *bm;
506         gboolean holds_value_array;
507 
508         G_GNUC_BEGIN_IGNORE_DEPRECATIONS
509         holds_value_array = G_VALUE_HOLDS(value, PYGI_TYPE_VALUE_ARRAY);
510         G_GNUC_END_IGNORE_DEPRECATIONS
511 
512         if (obj == Py_None)
513             g_value_set_boxed(value, NULL);
514         else if (G_VALUE_HOLDS(value, PY_TYPE_OBJECT))
515             g_value_set_boxed(value, obj);
516         else if (PyObject_TypeCheck(obj, &PyGBoxed_Type) &&
517                 G_VALUE_HOLDS(value, ((PyGBoxed *)obj)->gtype))
518             g_value_set_boxed(value, pyg_boxed_get(obj, gpointer));
519         else if (G_VALUE_HOLDS(value, G_TYPE_VALUE)) {
520             GType type;
521             GValue *n_value;
522 
523             type = pyg_type_from_object((PyObject*)Py_TYPE(obj));
524             if (G_UNLIKELY (! type)) {
525                 return -1;
526             }
527             n_value = g_new0 (GValue, 1);
528             g_value_init (n_value, type);
529             g_value_take_boxed (value, n_value);
530             return pyg_value_from_pyobject_with_error (n_value, obj);
531         }
532         else if (PySequence_Check(obj) && holds_value_array)
533             return pyg_value_array_from_pyobject(value, obj, NULL);
534 
535         else if (PySequence_Check(obj) &&
536                 G_VALUE_HOLDS(value, G_TYPE_ARRAY))
537             return pyg_array_from_pyobject(value, obj);
538         else if (PyUnicode_Check (obj) &&
539                 G_VALUE_HOLDS(value, G_TYPE_GSTRING)) {
540             GString *string;
541             char *buffer;
542             Py_ssize_t len;
543             buffer = PyUnicode_AsUTF8AndSize (obj, &len);
544             if (buffer == NULL)
545                 return -1;
546             string = g_string_new_len(buffer, len);
547             g_value_set_boxed(value, string);
548             g_string_free (string, TRUE);
549             break;
550         }
551         else if ((bm = pyg_type_lookup(G_VALUE_TYPE(value))) != NULL)
552             return bm->tovalue(value, obj);
553         else if (PyCapsule_CheckExact (obj))
554             g_value_set_boxed(value, PyCapsule_GetPointer (obj, NULL));
555         else {
556             PyErr_SetString(PyExc_TypeError, "Expected Boxed");
557             return -1;
558         }
559         break;
560     }
561     case G_TYPE_PARAM:
562         /* we need to support both the wrapped _gi.GParamSpec and the GI
563          * GObject.ParamSpec */
564         if (G_IS_PARAM_SPEC (pygobject_get (obj)))
565             g_value_set_param(value, G_PARAM_SPEC (pygobject_get (obj)));
566         else if (pyg_param_spec_check (obj))
567             g_value_set_param(value, PyCapsule_GetPointer (obj, NULL));
568         else {
569             PyErr_SetString(PyExc_TypeError, "Expected ParamSpec");
570             return -1;
571         }
572         break;
573     case G_TYPE_OBJECT:
574         if (obj == Py_None) {
575             g_value_set_object(value, NULL);
576         } else if (PyObject_TypeCheck(obj, &PyGObject_Type) &&
577                 G_TYPE_CHECK_INSTANCE_TYPE(pygobject_get(obj),
578                         G_VALUE_TYPE(value))) {
579             g_value_set_object(value, pygobject_get(obj));
580         } else {
581             PyErr_SetString(PyExc_TypeError, "Expected GObject");
582             return -1;
583         }
584         break;
585     case G_TYPE_VARIANT:
586     {
587         if (obj == Py_None)
588             g_value_set_variant(value, NULL);
589         else if (pyg_type_from_object_strict(obj, FALSE) == G_TYPE_VARIANT)
590             g_value_set_variant(value, pyg_boxed_get(obj, GVariant));
591         else {
592             PyErr_SetString(PyExc_TypeError, "Expected Variant");
593             return -1;
594         }
595         break;
596     }
597     default:
598     {
599         PyGTypeMarshal *bm;
600         if ((bm = pyg_type_lookup(G_VALUE_TYPE(value))) != NULL) {
601             return bm->tovalue(value, obj);
602         } else {
603             PyErr_SetString(PyExc_TypeError, "Unknown value type");
604             return -1;
605         }
606         break;
607     }
608     }
609 
610     /* If an error occurred, unset the GValue but don't clear the Python error. */
611     if (PyErr_Occurred()) {
612         g_value_unset(value);
613         return -1;
614     }
615 
616     return 0;
617 }
618 
619 /**
620  * pyg_value_from_pyobject:
621  * @value: the GValue object to store the converted value in.
622  * @obj: the Python object to convert.
623  *
624  * Same basic function as pyg_value_from_pyobject_with_error but clears
625  * any Python errors before returning.
626  *
627  * Returns: 0 on success, -1 on error.
628  */
629 int
pyg_value_from_pyobject(GValue * value,PyObject * obj)630 pyg_value_from_pyobject(GValue *value, PyObject *obj)
631 {
632     int res = pyg_value_from_pyobject_with_error (value, obj);
633 
634     if (PyErr_Occurred()) {
635         PyErr_Clear();
636         return -1;
637     }
638     return res;
639 }
640 
641 /**
642  * pygi_value_to_py_basic_type:
643  * @value: the GValue object.
644  * @handled: (out): TRUE if the return value is defined
645  *
646  * This function creates/returns a Python wrapper object that
647  * represents the GValue passed as an argument limited to supporting basic types
648  * like ints, bools, and strings.
649  *
650  * Returns: a PyObject representing the value.
651  */
652 PyObject *
pygi_value_to_py_basic_type(const GValue * value,GType fundamental,gboolean * handled)653 pygi_value_to_py_basic_type (const GValue *value, GType fundamental, gboolean *handled)
654 {
655     *handled = TRUE;
656     switch (fundamental) {
657         case G_TYPE_CHAR:
658             return PyLong_FromLong (g_value_get_schar (value));
659         case G_TYPE_UCHAR:
660             return PyLong_FromLong (g_value_get_uchar (value));
661         case G_TYPE_BOOLEAN:
662             return pygi_gboolean_to_py (g_value_get_boolean (value));
663         case G_TYPE_INT:
664             return pygi_gint_to_py (g_value_get_int (value));
665         case G_TYPE_UINT:
666             return pygi_guint_to_py (g_value_get_uint (value));
667         case G_TYPE_LONG:
668             return pygi_glong_to_py (g_value_get_long(value));
669         case G_TYPE_ULONG:
670             return pygi_gulong_to_py (g_value_get_ulong (value));
671         case G_TYPE_INT64:
672             return pygi_gint64_to_py (g_value_get_int64 (value));
673         case G_TYPE_UINT64:
674             return pygi_guint64_to_py (g_value_get_uint64 (value));
675         case G_TYPE_ENUM:
676             return pyg_enum_from_gtype (G_VALUE_TYPE (value),
677                                         g_value_get_enum (value));
678         case G_TYPE_FLAGS:
679             return pyg_flags_from_gtype (G_VALUE_TYPE (value),
680                                          g_value_get_flags (value));
681         case G_TYPE_FLOAT:
682             return pygi_gfloat_to_py (g_value_get_float (value));
683         case G_TYPE_DOUBLE:
684             return pygi_gdouble_to_py (g_value_get_double (value));
685         case G_TYPE_STRING:
686             return pygi_utf8_to_py (g_value_get_string (value));
687         default:
688             *handled = FALSE;
689             return NULL;
690     }
691 }
692 
693 /**
694  * value_to_py_structured_type:
695  * @value: the GValue object.
696  * @copy_boxed: true if boxed values should be copied.
697  *
698  * This function creates/returns a Python wrapper object that
699  * represents the GValue passed as an argument.
700  *
701  * Returns: a PyObject representing the value or NULL and sets an error;
702  */
703 static PyObject *
value_to_py_structured_type(const GValue * value,GType fundamental,gboolean copy_boxed)704 value_to_py_structured_type (const GValue *value, GType fundamental, gboolean copy_boxed)
705 {
706     const gchar *type_name;
707 
708     switch (fundamental) {
709     case G_TYPE_INTERFACE:
710         if (g_type_is_a(G_VALUE_TYPE(value), G_TYPE_OBJECT))
711             return pygobject_new(g_value_get_object(value));
712         else
713             break;
714 
715     case G_TYPE_POINTER:
716         if (G_VALUE_HOLDS_GTYPE (value))
717             return pyg_type_wrapper_new (g_value_get_gtype (value));
718         else
719             return pyg_pointer_new(G_VALUE_TYPE(value),
720                     g_value_get_pointer(value));
721     case G_TYPE_BOXED: {
722         PyGTypeMarshal *bm;
723         gboolean holds_value_array;
724 
725         G_GNUC_BEGIN_IGNORE_DEPRECATIONS
726         holds_value_array = G_VALUE_HOLDS(value, PYGI_TYPE_VALUE_ARRAY);
727         G_GNUC_END_IGNORE_DEPRECATIONS
728 
729         if (G_VALUE_HOLDS(value, PY_TYPE_OBJECT)) {
730             PyObject *ret = (PyObject *)g_value_dup_boxed(value);
731             if (ret == NULL) {
732                 Py_INCREF(Py_None);
733                 return Py_None;
734             }
735             return ret;
736         } else if (G_VALUE_HOLDS(value, G_TYPE_VALUE)) {
737             GValue *n_value = g_value_get_boxed (value);
738             return pyg_value_as_pyobject(n_value, copy_boxed);
739         } else if (holds_value_array) {
740             GValueArray *array = (GValueArray *) g_value_get_boxed(value);
741             Py_ssize_t n_values = array ? array->n_values : 0;
742             PyObject *ret = PyList_New(n_values);
743             int i;
744             for (i = 0; i < n_values; ++i)
745                 PyList_SET_ITEM(ret, i, pyg_value_as_pyobject
746                         (array->values + i, copy_boxed));
747             return ret;
748         } else if (G_VALUE_HOLDS(value, G_TYPE_GSTRING)) {
749             GString *string = (GString *) g_value_get_boxed(value);
750             PyObject *ret = PyUnicode_FromStringAndSize (string->str, string->len);
751             return ret;
752         }
753         bm = pyg_type_lookup(G_VALUE_TYPE(value));
754         if (bm) {
755             return bm->fromvalue(value);
756         } else {
757             if (copy_boxed)
758                 return pygi_gboxed_new(G_VALUE_TYPE(value),
759                         g_value_get_boxed(value), TRUE, TRUE);
760             else
761                 return pygi_gboxed_new(G_VALUE_TYPE(value),
762                         g_value_get_boxed(value),FALSE,FALSE);
763         }
764     }
765     case G_TYPE_PARAM:
766         return pyg_param_spec_new(g_value_get_param(value));
767     case G_TYPE_OBJECT:
768         return pygobject_new(g_value_get_object(value));
769     case G_TYPE_VARIANT:
770     {
771         GVariant *v = g_value_get_variant(value);
772         if (v == NULL) {
773             Py_INCREF(Py_None);
774             return Py_None;
775         }
776         return pygi_struct_new_from_g_type (G_TYPE_VARIANT, g_variant_ref(v), FALSE);
777     }
778     default:
779     {
780         PyGTypeMarshal *bm;
781         if ((bm = pyg_type_lookup(G_VALUE_TYPE(value))))
782             return bm->fromvalue(value);
783         break;
784     }
785     }
786 
787     type_name = g_type_name (G_VALUE_TYPE (value));
788     if (type_name == NULL) {
789         type_name = "(null)";
790     }
791     PyErr_Format (PyExc_TypeError, "unknown type %s", type_name);
792     return NULL;
793 }
794 
795 
796 /**
797  * pyg_value_as_pyobject:
798  * @value: the GValue object.
799  * @copy_boxed: true if boxed values should be copied.
800  *
801  * This function creates/returns a Python wrapper object that
802  * represents the GValue passed as an argument.
803  *
804  * Returns: a PyObject representing the value or %NULL and sets an exception.
805  */
806 PyObject *
pyg_value_as_pyobject(const GValue * value,gboolean copy_boxed)807 pyg_value_as_pyobject (const GValue *value, gboolean copy_boxed)
808 {
809     PyObject *pyobj;
810     gboolean handled;
811     GType fundamental = G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value));
812 
813     /* HACK: special case char and uchar to return PyBytes intstead of integers
814      * in the general case. Property access will skip this by calling
815      * pygi_value_to_py_basic_type() directly.
816      * See: https://bugzilla.gnome.org/show_bug.cgi?id=733893 */
817     if (fundamental == G_TYPE_CHAR) {
818         gint8 val = g_value_get_schar(value);
819         return PyUnicode_FromStringAndSize ((char *)&val, 1);
820     } else if (fundamental == G_TYPE_UCHAR) {
821         guint8 val = g_value_get_uchar(value);
822         return PyBytes_FromStringAndSize ((char *)&val, 1);
823     }
824 
825     pyobj = pygi_value_to_py_basic_type (value, fundamental, &handled);
826     if (handled)
827         return pyobj;
828 
829     pyobj = value_to_py_structured_type (value, fundamental, copy_boxed);
830     return pyobj;
831 }
832 
833 
834 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
835 int
pyg_param_gvalue_from_pyobject(GValue * value,PyObject * py_obj,const GParamSpec * pspec)836 pyg_param_gvalue_from_pyobject(GValue* value,
837                                PyObject* py_obj,
838 			       const GParamSpec* pspec)
839 {
840     if (G_IS_PARAM_SPEC_UNICHAR(pspec)) {
841 	gunichar u;
842 
843 	if (!pyg_pyobj_to_unichar_conv(py_obj, &u)) {
844 	    PyErr_Clear();
845 	    return -1;
846 	}
847         g_value_set_uint(value, u);
848 	return 0;
849     }
850     else if (PYGI_IS_PARAM_SPEC_VALUE_ARRAY(pspec))
851 	return pyg_value_array_from_pyobject(value, py_obj,
852 					     PYGI_PARAM_SPEC_VALUE_ARRAY(pspec));
853     else {
854 	return pyg_value_from_pyobject(value, py_obj);
855     }
856 }
857 
858 G_GNUC_END_IGNORE_DEPRECATIONS
859 
860 PyObject*
pyg_param_gvalue_as_pyobject(const GValue * gvalue,gboolean copy_boxed,const GParamSpec * pspec)861 pyg_param_gvalue_as_pyobject(const GValue* gvalue,
862                              gboolean copy_boxed,
863                              const GParamSpec* pspec)
864 {
865     if (G_IS_PARAM_SPEC_UNICHAR(pspec)) {
866         gunichar u;
867         gchar *encoded;
868         PyObject *retval;
869 
870         u = g_value_get_uint (gvalue);
871         encoded = g_ucs4_to_utf8 (&u, 1, NULL, NULL, NULL);
872         if (encoded == NULL) {
873             PyErr_SetString (PyExc_ValueError, "Failed to decode");
874             return NULL;
875         }
876         retval = PyUnicode_FromString (encoded);
877         g_free (encoded);
878         return retval;
879     }
880     else {
881         return pyg_value_as_pyobject(gvalue, copy_boxed);
882     }
883 }
884 
885 PyObject *
pyg__gvalue_get(PyObject * module,PyObject * pygvalue)886 pyg__gvalue_get(PyObject *module, PyObject *pygvalue)
887 {
888     if (!pyg_boxed_check (pygvalue, G_TYPE_VALUE)) {
889         PyErr_SetString (PyExc_TypeError, "Expected GValue argument.");
890         return NULL;
891     }
892 
893     return pyg_value_as_pyobject (pyg_boxed_get(pygvalue, GValue),
894                                   /*copy_boxed=*/ TRUE);
895 }
896 
897 PyObject *
pyg__gvalue_get_type(PyObject * module,PyObject * pygvalue)898 pyg__gvalue_get_type(PyObject *module, PyObject *pygvalue)
899 {
900     GValue *value;
901     GType type;
902 
903     if (!pyg_boxed_check (pygvalue, G_TYPE_VALUE)) {
904         PyErr_SetString (PyExc_TypeError, "Expected GValue argument.");
905         return NULL;
906     }
907 
908     value = pyg_boxed_get (pygvalue, GValue);
909     type = G_VALUE_TYPE (value);
910     return pyg_type_wrapper_new (type);
911 }
912 
913 PyObject *
pyg__gvalue_set(PyObject * module,PyObject * args)914 pyg__gvalue_set(PyObject *module, PyObject *args)
915 {
916     PyObject *pygvalue;
917     PyObject *pyobject;
918 
919     if (!PyArg_ParseTuple (args, "OO:_gi._gvalue_set",
920                            &pygvalue, &pyobject))
921         return NULL;
922 
923     if (!pyg_boxed_check (pygvalue, G_TYPE_VALUE)) {
924         PyErr_SetString (PyExc_TypeError, "Expected GValue argument.");
925         return NULL;
926     }
927 
928     if (pyg_value_from_pyobject_with_error (pyg_boxed_get (pygvalue, GValue),
929                                             pyobject) == -1)
930         return NULL;
931 
932     Py_RETURN_NONE;
933 }
934