e1a7028ef3ebd32fd9043d1ffa327f9cc02b2425
[platform/upstream/python-gobject.git] / gi / pygi-enum-marshal.c
1 /* -*- Mode: C; c-basic-offset: 4 -*-
2  * vim: tabstop=4 shiftwidth=4 expandtab
3  *
4  * Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>
5  * Copyright (C) 2014 Simon Feltman <sfeltman@gnome.org>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <Python.h>
22 #include <glib.h>
23 #include <pyglib-python-compat.h>
24
25 #include "pygi-enum-marshal.h"
26 #include "pygi-private.h"
27
28 static gboolean
29 gi_argument_from_c_long (GIArgument *arg_out,
30                          long        c_long_in,
31                          GITypeTag   type_tag)
32 {
33     switch (type_tag) {
34       case GI_TYPE_TAG_INT8:
35           arg_out->v_int8 = c_long_in;
36           return TRUE;
37       case GI_TYPE_TAG_UINT8:
38           arg_out->v_uint8 = c_long_in;
39           return TRUE;
40       case GI_TYPE_TAG_INT16:
41           arg_out->v_int16 = c_long_in;
42           return TRUE;
43       case GI_TYPE_TAG_UINT16:
44           arg_out->v_uint16 = c_long_in;
45           return TRUE;
46       case GI_TYPE_TAG_INT32:
47           arg_out->v_int32 = c_long_in;
48           return TRUE;
49       case GI_TYPE_TAG_UINT32:
50           arg_out->v_uint32 = c_long_in;
51           return TRUE;
52       case GI_TYPE_TAG_INT64:
53           arg_out->v_int64 = c_long_in;
54           return TRUE;
55       case GI_TYPE_TAG_UINT64:
56           arg_out->v_uint64 = c_long_in;
57           return TRUE;
58       default:
59           PyErr_Format (PyExc_TypeError,
60                         "Unable to marshal C long %ld to %s",
61                         c_long_in,
62                         g_type_tag_to_string (type_tag));
63           return FALSE;
64     }
65 }
66
67 static gboolean
68 gi_argument_to_c_long (GIArgument *arg_in,
69                        long *c_long_out,
70                        GITypeTag type_tag)
71 {
72     switch (type_tag) {
73       case GI_TYPE_TAG_INT8:
74           *c_long_out = arg_in->v_int8;
75           return TRUE;
76       case GI_TYPE_TAG_UINT8:
77           *c_long_out = arg_in->v_uint8;
78           return TRUE;
79       case GI_TYPE_TAG_INT16:
80           *c_long_out = arg_in->v_int16;
81           return TRUE;
82       case GI_TYPE_TAG_UINT16:
83           *c_long_out = arg_in->v_uint16;
84           return TRUE;
85       case GI_TYPE_TAG_INT32:
86           *c_long_out = arg_in->v_int32;
87           return TRUE;
88       case GI_TYPE_TAG_UINT32:
89           *c_long_out = arg_in->v_uint32;
90           return TRUE;
91       case GI_TYPE_TAG_INT64:
92           *c_long_out = arg_in->v_int64;
93           return TRUE;
94       case GI_TYPE_TAG_UINT64:
95           *c_long_out = arg_in->v_uint64;
96           return TRUE;
97       default:
98           PyErr_Format (PyExc_TypeError,
99                         "Unable to marshal %s to C long",
100                         g_type_tag_to_string (type_tag));
101           return FALSE;
102     }
103 }
104
105 static gboolean
106 _pygi_marshal_from_py_interface_enum (PyGIInvokeState   *state,
107                                       PyGICallableCache *callable_cache,
108                                       PyGIArgCache      *arg_cache,
109                                       PyObject          *py_arg,
110                                       GIArgument        *arg,
111                                       gpointer          *cleanup_data)
112 {
113     PyObject *py_long;
114     long c_long;
115     gint is_instance;
116     PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
117     GIBaseInfo *interface = NULL;
118
119     is_instance = PyObject_IsInstance (py_arg, iface_cache->py_type);
120
121     py_long = PYGLIB_PyNumber_Long (py_arg);
122     if (py_long == NULL) {
123         PyErr_Clear();
124         goto err;
125     }
126
127     c_long = PYGLIB_PyLong_AsLong (py_long);
128     Py_DECREF (py_long);
129
130     /* Write c_long into arg */
131     interface = g_type_info_get_interface (arg_cache->type_info);
132     assert(g_base_info_get_type (interface) == GI_INFO_TYPE_ENUM);
133     if (!gi_argument_from_c_long(arg,
134                                  c_long,
135                                  g_enum_info_get_storage_type ((GIEnumInfo *)interface))) {
136           g_assert_not_reached();
137           g_base_info_unref (interface);
138           return FALSE;
139     }
140
141     /* If this is not an instance of the Enum type that we want
142      * we need to check if the value is equivilant to one of the
143      * Enum's memebers */
144     if (!is_instance) {
145         int i;
146         gboolean is_found = FALSE;
147
148         for (i = 0; i < g_enum_info_get_n_values (iface_cache->interface_info); i++) {
149             GIValueInfo *value_info =
150                 g_enum_info_get_value (iface_cache->interface_info, i);
151             glong enum_value = g_value_info_get_value (value_info);
152             g_base_info_unref ( (GIBaseInfo *)value_info);
153             if (c_long == enum_value) {
154                 is_found = TRUE;
155                 break;
156             }
157         }
158
159         if (!is_found)
160             goto err;
161     }
162
163     g_base_info_unref (interface);
164     return TRUE;
165
166 err:
167     if (interface)
168         g_base_info_unref (interface);
169     PyErr_Format (PyExc_TypeError, "Expected a %s, but got %s",
170                   iface_cache->type_name, py_arg->ob_type->tp_name);
171     return FALSE;
172 }
173
174 static gboolean
175 _pygi_marshal_from_py_interface_flags (PyGIInvokeState   *state,
176                                        PyGICallableCache *callable_cache,
177                                        PyGIArgCache      *arg_cache,
178                                        PyObject          *py_arg,
179                                        GIArgument        *arg,
180                                        gpointer          *cleanup_data)
181 {
182     PyObject *py_long;
183     long c_long;
184     gint is_instance;
185     PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
186     GIBaseInfo *interface;
187
188     is_instance = PyObject_IsInstance (py_arg, iface_cache->py_type);
189
190     py_long = PYGLIB_PyNumber_Long (py_arg);
191     if (py_long == NULL) {
192         PyErr_Clear ();
193         goto err;
194     }
195
196     c_long = PYGLIB_PyLong_AsLong (py_long);
197     Py_DECREF (py_long);
198
199     /* only 0 or argument of type Flag is allowed */
200     if (!is_instance && c_long != 0)
201         goto err;
202
203     /* Write c_long into arg */
204     interface = g_type_info_get_interface (arg_cache->type_info);
205     g_assert (g_base_info_get_type (interface) == GI_INFO_TYPE_FLAGS);
206     if (!gi_argument_from_c_long(arg, c_long,
207                                  g_enum_info_get_storage_type ((GIEnumInfo *)interface))) {
208         g_base_info_unref (interface);
209         return FALSE;
210     }
211
212     g_base_info_unref (interface);
213     return TRUE;
214
215 err:
216     PyErr_Format (PyExc_TypeError, "Expected a %s, but got %s",
217                   iface_cache->type_name, py_arg->ob_type->tp_name);
218     return FALSE;
219
220 }
221
222 static PyObject *
223 _pygi_marshal_to_py_interface_enum (PyGIInvokeState   *state,
224                                     PyGICallableCache *callable_cache,
225                                     PyGIArgCache      *arg_cache,
226                                     GIArgument        *arg)
227 {
228     PyObject *py_obj = NULL;
229     PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
230     GIBaseInfo *interface;
231     long c_long;
232
233     interface = g_type_info_get_interface (arg_cache->type_info);
234     g_assert (g_base_info_get_type (interface) == GI_INFO_TYPE_ENUM);
235
236     if (!gi_argument_to_c_long(arg, &c_long,
237                                g_enum_info_get_storage_type ((GIEnumInfo *)interface))) {
238         return NULL;
239     }
240
241     if (iface_cache->g_type == G_TYPE_NONE) {
242         py_obj = PyObject_CallFunction (iface_cache->py_type, "l", c_long);
243     } else {
244         py_obj = pyg_enum_from_gtype (iface_cache->g_type, c_long);
245     }
246     g_base_info_unref (interface);
247     return py_obj;
248 }
249
250 static PyObject *
251 _pygi_marshal_to_py_interface_flags (PyGIInvokeState   *state,
252                                      PyGICallableCache *callable_cache,
253                                      PyGIArgCache      *arg_cache,
254                                      GIArgument        *arg)
255 {
256     PyObject *py_obj = NULL;
257     PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
258     GIBaseInfo *interface;
259     long c_long;
260
261     interface = g_type_info_get_interface (arg_cache->type_info);
262     g_assert (g_base_info_get_type (interface) == GI_INFO_TYPE_FLAGS);
263
264     if (!gi_argument_to_c_long(arg, &c_long,
265                                g_enum_info_get_storage_type ((GIEnumInfo *)interface))) {
266         g_base_info_unref (interface);
267         return NULL;
268     }
269
270     g_base_info_unref (interface);
271     if (iface_cache->g_type == G_TYPE_NONE) {
272         /* An enum with a GType of None is an enum without GType */
273
274         PyObject *py_type = _pygi_type_import_by_gi_info (iface_cache->interface_info);
275         PyObject *py_args = NULL;
276
277         if (!py_type)
278             return NULL;
279
280         py_args = PyTuple_New (1);
281         if (PyTuple_SetItem (py_args, 0, PyLong_FromLong (c_long)) != 0) {
282             Py_DECREF (py_args);
283             Py_DECREF (py_type);
284             return NULL;
285         }
286
287         py_obj = PyObject_CallFunction (py_type, "l", c_long);
288
289         Py_DECREF (py_args);
290         Py_DECREF (py_type);
291     } else {
292         py_obj = pyg_flags_from_gtype (iface_cache->g_type, c_long);
293     }
294
295     return py_obj;
296 }
297
298 static gboolean
299 pygi_arg_enum_setup_from_info (PyGIArgCache  *arg_cache,
300                                GITypeInfo    *type_info,
301                                GIArgInfo     *arg_info,
302                                GITransfer     transfer,
303                                PyGIDirection  direction)
304 {
305     if (direction & PYGI_DIRECTION_FROM_PYTHON)
306         arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_enum;
307
308     if (direction & PYGI_DIRECTION_TO_PYTHON)
309         arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_enum;
310
311     return TRUE;
312 }
313
314
315 PyGIArgCache *
316 pygi_arg_enum_new_from_info (GITypeInfo      *type_info,
317                              GIArgInfo       *arg_info,
318                              GITransfer       transfer,
319                              PyGIDirection    direction,
320                              GIInterfaceInfo *iface_info)
321 {
322     gboolean res = FALSE;
323     PyGIArgCache *cache = NULL;
324
325     cache = pygi_arg_interface_new_from_info (type_info,
326                                               arg_info,
327                                               transfer,
328                                               direction,
329                                               iface_info);
330     if (cache == NULL)
331         return NULL;
332
333     res = pygi_arg_enum_setup_from_info (cache,
334                                          type_info,
335                                          arg_info,
336                                          transfer,
337                                          direction);
338     if (res) {
339         return cache;
340     } else {
341         pygi_arg_cache_free (cache);
342         return NULL;
343     }
344 }
345
346 static gboolean
347 pygi_arg_flags_setup_from_info (PyGIArgCache  *arg_cache,
348                                 GITypeInfo    *type_info,
349                                 GIArgInfo     *arg_info,
350                                 GITransfer     transfer,
351                                 PyGIDirection  direction)
352 {
353     if (direction & PYGI_DIRECTION_FROM_PYTHON)
354         arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_flags;
355
356     if (direction & PYGI_DIRECTION_TO_PYTHON)
357         arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_flags;
358
359     return TRUE;
360 }
361
362
363 PyGIArgCache *
364 pygi_arg_flags_new_from_info (GITypeInfo      *type_info,
365                               GIArgInfo       *arg_info,
366                               GITransfer       transfer,
367                               PyGIDirection    direction,
368                               GIInterfaceInfo *iface_info)
369 {
370     gboolean res = FALSE;
371     PyGIArgCache *cache = NULL;
372
373     cache = pygi_arg_interface_new_from_info (type_info,
374                                               arg_info,
375                                               transfer,
376                                               direction,
377                                               iface_info);
378     if (cache == NULL)
379         return NULL;
380
381     res = pygi_arg_flags_setup_from_info (cache,
382                                           type_info,
383                                           arg_info,
384                                           transfer,
385                                           direction);
386     if (res) {
387         return cache;
388     } else {
389         pygi_arg_cache_free (cache);
390         return NULL;
391     }
392 }