Imported Upstream version 3.21.92
[platform/upstream/pygobject2.git] / gi / pygi-hashtable.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 "pygi-hashtable.h"
23 #include "pygi-argument.h"
24 #include "pygi-util.h"
25
26 typedef struct _PyGIHashCache
27 {
28     PyGIArgCache arg_cache;
29     PyGIArgCache *key_cache;
30     PyGIArgCache *value_cache;
31 } PyGIHashCache;
32
33
34 static void
35 _hash_cache_free_func (PyGIHashCache *cache)
36 {
37     if (cache != NULL) {
38         pygi_arg_cache_free (cache->key_cache);
39         pygi_arg_cache_free (cache->value_cache);
40         g_slice_free (PyGIHashCache, cache);
41     }
42 }
43
44 static gboolean
45 _pygi_marshal_from_py_ghash (PyGIInvokeState   *state,
46                              PyGICallableCache *callable_cache,
47                              PyGIArgCache      *arg_cache,
48                              PyObject          *py_arg,
49                              GIArgument        *arg,
50                              gpointer          *cleanup_data)
51 {
52     PyGIMarshalFromPyFunc key_from_py_marshaller;
53     PyGIMarshalFromPyFunc value_from_py_marshaller;
54
55     int i;
56     Py_ssize_t length;
57     PyObject *py_keys, *py_values;
58
59     GHashFunc hash_func;
60     GEqualFunc equal_func;
61
62     GHashTable *hash_ = NULL;
63     PyGIHashCache *hash_cache = (PyGIHashCache *)arg_cache;
64
65     if (py_arg == Py_None) {
66         arg->v_pointer = NULL;
67         return TRUE;
68     }
69
70     py_keys = PyMapping_Keys (py_arg);
71     if (py_keys == NULL) {
72         PyErr_Format (PyExc_TypeError, "Must be mapping, not %s",
73                       py_arg->ob_type->tp_name);
74         return FALSE;
75     }
76
77     length = PyMapping_Length (py_arg);
78     if (length < 0) {
79         Py_DECREF (py_keys);
80         return FALSE;
81     }
82
83     py_values = PyMapping_Values (py_arg);
84     if (py_values == NULL) {
85         Py_DECREF (py_keys);
86         return FALSE;
87     }
88
89     key_from_py_marshaller = hash_cache->key_cache->from_py_marshaller;
90     value_from_py_marshaller = hash_cache->value_cache->from_py_marshaller;
91
92     switch (hash_cache->key_cache->type_tag) {
93         case GI_TYPE_TAG_UTF8:
94         case GI_TYPE_TAG_FILENAME:
95             hash_func = g_str_hash;
96             equal_func = g_str_equal;
97             break;
98         default:
99             hash_func = NULL;
100             equal_func = NULL;
101     }
102
103     hash_ = g_hash_table_new (hash_func, equal_func);
104     if (hash_ == NULL) {
105         PyErr_NoMemory ();
106         Py_DECREF (py_keys);
107         Py_DECREF (py_values);
108         return FALSE;
109     }
110
111     for (i = 0; i < length; i++) {
112         GIArgument key, value;
113         gpointer key_cleanup_data = NULL;
114         gpointer value_cleanup_data = NULL;
115         PyObject *py_key = PyList_GET_ITEM (py_keys, i);
116         PyObject *py_value = PyList_GET_ITEM (py_values, i);
117         if (py_key == NULL || py_value == NULL)
118             goto err;
119
120         if (!key_from_py_marshaller ( state,
121                                       callable_cache,
122                                       hash_cache->key_cache,
123                                       py_key,
124                                      &key,
125                                      &key_cleanup_data))
126             goto err;
127
128         if (!value_from_py_marshaller ( state,
129                                         callable_cache,
130                                         hash_cache->value_cache,
131                                         py_value,
132                                        &value,
133                                        &value_cleanup_data))
134             goto err;
135
136         g_hash_table_insert (hash_,
137                              _pygi_arg_to_hash_pointer (&key, hash_cache->key_cache->type_info),
138                              _pygi_arg_to_hash_pointer (&value, hash_cache->value_cache->type_info));
139         continue;
140 err:
141         /* FIXME: cleanup hash keys and values */
142         Py_XDECREF (py_key);
143         Py_XDECREF (py_value);
144         Py_DECREF (py_keys);
145         Py_DECREF (py_values);
146         g_hash_table_unref (hash_);
147         _PyGI_ERROR_PREFIX ("Item %i: ", i);
148         return FALSE;
149     }
150
151     arg->v_pointer = hash_;
152
153     if (arg_cache->transfer == GI_TRANSFER_NOTHING) {
154         /* Free everything in cleanup. */
155         *cleanup_data = arg->v_pointer;
156     } else if (arg_cache->transfer == GI_TRANSFER_CONTAINER) {
157         /* Make a shallow copy so we can free the elements later in cleanup
158          * because it is possible invoke will free the list before our cleanup. */
159         *cleanup_data = g_hash_table_ref (arg->v_pointer);
160     } else { /* GI_TRANSFER_EVERYTHING */
161         /* No cleanup, everything is given to the callee.
162          * Note that the keys and values will leak for transfer everything because
163          * we do not use g_hash_table_new_full and set key/value_destroy_func. */
164         *cleanup_data = NULL;
165     }
166
167     return TRUE;
168 }
169
170 static void
171 _pygi_marshal_cleanup_from_py_ghash  (PyGIInvokeState *state,
172                                       PyGIArgCache    *arg_cache,
173                                       PyObject        *py_arg,
174                                       gpointer         data,
175                                       gboolean         was_processed)
176 {
177     if (data == NULL)
178         return;
179
180     if (was_processed) {
181         GHashTable *hash_;
182         PyGIHashCache *hash_cache = (PyGIHashCache *)arg_cache;
183
184         hash_ = (GHashTable *)data;
185
186         /* clean up keys and values first */
187         if (hash_cache->key_cache->from_py_cleanup != NULL ||
188                 hash_cache->value_cache->from_py_cleanup != NULL) {
189             GHashTableIter hiter;
190             gpointer key;
191             gpointer value;
192
193             PyGIMarshalCleanupFunc key_cleanup_func =
194                 hash_cache->key_cache->from_py_cleanup;
195             PyGIMarshalCleanupFunc value_cleanup_func =
196                 hash_cache->value_cache->from_py_cleanup;
197
198             g_hash_table_iter_init (&hiter, hash_);
199             while (g_hash_table_iter_next (&hiter, &key, &value)) {
200                 if (key != NULL && key_cleanup_func != NULL)
201                     key_cleanup_func (state,
202                                       hash_cache->key_cache,
203                                       NULL,
204                                       key,
205                                       TRUE);
206                 if (value != NULL && value_cleanup_func != NULL)
207                     value_cleanup_func (state,
208                                         hash_cache->value_cache,
209                                         NULL,
210                                         value,
211                                         TRUE);
212             }
213         }
214
215         g_hash_table_unref (hash_);
216     }
217 }
218
219 static PyObject *
220 _pygi_marshal_to_py_ghash (PyGIInvokeState   *state,
221                            PyGICallableCache *callable_cache,
222                            PyGIArgCache      *arg_cache,
223                            GIArgument        *arg)
224 {
225     GHashTable *hash_;
226     GHashTableIter hash_table_iter;
227
228     PyGIMarshalToPyFunc key_to_py_marshaller;
229     PyGIMarshalToPyFunc value_to_py_marshaller;
230
231     PyGIArgCache *key_arg_cache;
232     PyGIArgCache *value_arg_cache;
233     PyGIHashCache *hash_cache = (PyGIHashCache *)arg_cache;
234
235     GIArgument key_arg;
236     GIArgument value_arg;
237
238     PyObject *py_obj = NULL;
239
240     hash_ = arg->v_pointer;
241
242     if (hash_ == NULL) {
243         py_obj = Py_None;
244         Py_INCREF (py_obj);
245         return py_obj;
246     }
247
248     py_obj = PyDict_New ();
249     if (py_obj == NULL)
250         return NULL;
251
252     key_arg_cache = hash_cache->key_cache;
253     key_to_py_marshaller = key_arg_cache->to_py_marshaller;
254
255     value_arg_cache = hash_cache->value_cache;
256     value_to_py_marshaller = value_arg_cache->to_py_marshaller;
257
258     g_hash_table_iter_init (&hash_table_iter, hash_);
259     while (g_hash_table_iter_next (&hash_table_iter,
260                                    &key_arg.v_pointer,
261                                    &value_arg.v_pointer)) {
262         PyObject *py_key;
263         PyObject *py_value;
264         int retval;
265
266
267         _pygi_hash_pointer_to_arg (&key_arg, hash_cache->key_cache->type_info);
268         py_key = key_to_py_marshaller ( state,
269                                       callable_cache,
270                                       key_arg_cache,
271                                      &key_arg);
272
273         if (py_key == NULL) {
274             Py_CLEAR (py_obj);
275             return NULL;
276         }
277
278         _pygi_hash_pointer_to_arg (&value_arg, hash_cache->value_cache->type_info);
279         py_value = value_to_py_marshaller ( state,
280                                           callable_cache,
281                                           value_arg_cache,
282                                          &value_arg);
283
284         if (py_value == NULL) {
285             Py_CLEAR (py_obj);
286             Py_DECREF(py_key);
287             return NULL;
288         }
289
290         retval = PyDict_SetItem (py_obj, py_key, py_value);
291
292         Py_DECREF (py_key);
293         Py_DECREF (py_value);
294
295         if (retval < 0) {
296             Py_CLEAR (py_obj);
297             return NULL;
298         }
299     }
300
301     return py_obj;
302 }
303
304 static void
305 _pygi_marshal_cleanup_to_py_ghash (PyGIInvokeState *state,
306                                    PyGIArgCache    *arg_cache,
307                                    PyObject        *dummy,
308                                    gpointer         data,
309                                    gboolean         was_processed)
310 {
311     if (data == NULL)
312         return;
313
314     /* assume hashtable has boxed key and value */
315     if (arg_cache->transfer == GI_TRANSFER_EVERYTHING || arg_cache->transfer == GI_TRANSFER_CONTAINER)
316         g_hash_table_unref ( (GHashTable *)data);
317 }
318
319 static void
320 _arg_cache_from_py_ghash_setup (PyGIArgCache *arg_cache)
321 {
322     arg_cache->from_py_marshaller = _pygi_marshal_from_py_ghash;
323     arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_ghash;
324 }
325
326 static void
327 _arg_cache_to_py_ghash_setup (PyGIArgCache *arg_cache)
328 {
329     arg_cache->to_py_marshaller = _pygi_marshal_to_py_ghash;
330     arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_ghash;
331 }
332
333 static gboolean
334 pygi_arg_hash_table_setup_from_info (PyGIHashCache      *hc,
335                                      GITypeInfo         *type_info,
336                                      GIArgInfo          *arg_info,
337                                      GITransfer          transfer,
338                                      PyGIDirection       direction,
339                                      PyGICallableCache  *callable_cache)
340 {
341     GITypeInfo *key_type_info;
342     GITypeInfo *value_type_info;
343     GITransfer item_transfer;
344
345     if (!pygi_arg_base_setup ((PyGIArgCache *)hc, type_info, arg_info, transfer, direction))
346         return FALSE;
347
348     ( (PyGIArgCache *)hc)->destroy_notify = (GDestroyNotify)_hash_cache_free_func;
349     key_type_info = g_type_info_get_param_type (type_info, 0);
350     value_type_info = g_type_info_get_param_type (type_info, 1);
351
352     item_transfer =
353         transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer;
354
355     hc->key_cache = pygi_arg_cache_new (key_type_info,
356                                         NULL,
357                                         item_transfer,
358                                         direction,
359                                         callable_cache,
360                                         0, 0);
361
362     if (hc->key_cache == NULL) {
363         return FALSE;
364     }
365
366     hc->value_cache = pygi_arg_cache_new (value_type_info,
367                                           NULL,
368                                           item_transfer,
369                                           direction,
370                                           callable_cache,
371                                           0, 0);
372
373     if (hc->value_cache == NULL) {
374         return FALSE;
375     }
376
377     g_base_info_unref( (GIBaseInfo *)key_type_info);
378     g_base_info_unref( (GIBaseInfo *)value_type_info);
379
380     if (direction & PYGI_DIRECTION_FROM_PYTHON) {
381         _arg_cache_from_py_ghash_setup ((PyGIArgCache *)hc);
382     }
383
384     if (direction & PYGI_DIRECTION_TO_PYTHON) {
385         _arg_cache_to_py_ghash_setup ((PyGIArgCache *)hc);
386     }
387
388     return TRUE;
389 }
390
391 PyGIArgCache *
392 pygi_arg_hash_table_new_from_info (GITypeInfo         *type_info,
393                                    GIArgInfo          *arg_info,
394                                    GITransfer          transfer,
395                                    PyGIDirection       direction,
396                                    PyGICallableCache  *callable_cache)
397 {
398     gboolean res = FALSE;
399     PyGIHashCache *hc = NULL;
400
401     hc = g_slice_new0 (PyGIHashCache);
402     if (hc == NULL)
403         return NULL;
404
405     res = pygi_arg_hash_table_setup_from_info (hc,
406                                                type_info,
407                                                arg_info,
408                                                transfer,
409                                                direction,
410                                                callable_cache);
411     if (res) {
412         return (PyGIArgCache *)hc;
413     } else {
414         pygi_arg_cache_free ((PyGIArgCache *)hc);
415         return NULL;
416     }
417 }