summaryrefslogtreecommitdiff
path: root/gi/pygi-basictype.c
diff options
context:
space:
mode:
Diffstat (limited to 'gi/pygi-basictype.c')
-rw-r--r--gi/pygi-basictype.c824
1 files changed, 824 insertions, 0 deletions
diff --git a/gi/pygi-basictype.c b/gi/pygi-basictype.c
new file mode 100644
index 00000000..740463f9
--- /dev/null
+++ b/gi/pygi-basictype.c
@@ -0,0 +1,824 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * vim: tabstop=4 shiftwidth=4 expandtab
+ *
+ * Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>
+ * Copyright (C) 2014 Simon Feltman <sfeltman@gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <Python.h>
+#include <pyglib-python-compat.h>
+
+#include "pygi-basictype.h"
+#include "pygi-argument.h"
+#include "pygi-private.h"
+
+
+/*
+ * From Python Marshaling
+ */
+
+static gboolean
+_pygi_marshal_from_py_void (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ GIArgument *arg,
+ gpointer *cleanup_data)
+{
+ g_warn_if_fail (arg_cache->transfer == GI_TRANSFER_NOTHING);
+
+ if (py_arg == Py_None) {
+ arg->v_pointer = NULL;
+ } else if (PYGLIB_CPointer_Check(py_arg)) {
+ arg->v_pointer = PYGLIB_CPointer_GetPointer (py_arg, NULL);
+ } else if (PYGLIB_PyLong_Check(py_arg) || PyLong_Check(py_arg)) {
+ arg->v_pointer = PyLong_AsVoidPtr (py_arg);
+ } else {
+ PyErr_SetString(PyExc_ValueError,
+ "Pointer arguments are restricted to integers, capsules, and None. "
+ "See: https://bugzilla.gnome.org/show_bug.cgi?id=683599");
+ return FALSE;
+ }
+
+ *cleanup_data = arg->v_pointer;
+ return TRUE;
+}
+
+static gboolean
+check_valid_double (double x, double min, double max)
+{
+ char buf[100];
+
+ if ((x < min || x > max) && x != INFINITY && x != -INFINITY && x != NAN) {
+ if (PyErr_Occurred())
+ PyErr_Clear ();
+
+ /* we need this as PyErr_Format() does not support float types */
+ snprintf (buf, sizeof (buf), "%g not in range %g to %g", x, min, max);
+ PyErr_SetString (PyExc_OverflowError, buf);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+_pygi_py_arg_to_double (PyObject *py_arg, double *double_)
+{
+ PyObject *py_float;
+
+ if (!PyNumber_Check (py_arg)) {
+ PyErr_Format (PyExc_TypeError, "Must be number, not %s",
+ py_arg->ob_type->tp_name);
+ return FALSE;
+ }
+
+ py_float = PyNumber_Float (py_arg);
+ if (!py_float)
+ return FALSE;
+
+ *double_ = PyFloat_AsDouble (py_float);
+ Py_DECREF (py_float);
+
+
+ return TRUE;
+}
+
+static gboolean
+_pygi_marshal_from_py_float (PyObject *py_arg,
+ GIArgument *arg)
+{
+ double double_;
+
+ if (!_pygi_py_arg_to_double (py_arg, &double_))
+ return FALSE;
+
+ if (PyErr_Occurred () || !check_valid_double (double_, -G_MAXFLOAT, G_MAXFLOAT))
+ return FALSE;
+
+ arg->v_float = double_;
+ return TRUE;
+}
+
+static gboolean
+_pygi_marshal_from_py_double (PyObject *py_arg,
+ GIArgument *arg)
+{
+ double double_;
+
+ if (!_pygi_py_arg_to_double (py_arg, &double_))
+ return FALSE;
+
+ if (PyErr_Occurred () || !check_valid_double (double_, -G_MAXDOUBLE, G_MAXDOUBLE))
+ return FALSE;
+
+ arg->v_double = double_;
+ return TRUE;
+}
+
+static gboolean
+_pygi_marshal_from_py_unichar (PyObject *py_arg,
+ GIArgument *arg)
+{
+ Py_ssize_t size;
+ gchar *string_;
+
+ if (py_arg == Py_None) {
+ arg->v_uint32 = 0;
+ return FALSE;
+ }
+
+ if (PyUnicode_Check (py_arg)) {
+ PyObject *py_bytes;
+
+ size = PyUnicode_GET_SIZE (py_arg);
+ py_bytes = PyUnicode_AsUTF8String (py_arg);
+ if (!py_bytes)
+ return FALSE;
+
+ string_ = g_strdup(PYGLIB_PyBytes_AsString (py_bytes));
+ Py_DECREF (py_bytes);
+
+#if PY_VERSION_HEX < 0x03000000
+ } else if (PyString_Check (py_arg)) {
+ PyObject *pyuni = PyUnicode_FromEncodedObject (py_arg, "UTF-8", "strict");
+ if (!pyuni)
+ return FALSE;
+
+ size = PyUnicode_GET_SIZE (pyuni);
+ string_ = g_strdup (PyString_AsString(py_arg));
+ Py_DECREF (pyuni);
+#endif
+ } else {
+ PyErr_Format (PyExc_TypeError, "Must be string, not %s",
+ py_arg->ob_type->tp_name);
+ return FALSE;
+ }
+
+ if (size != 1) {
+ PyErr_Format (PyExc_TypeError, "Must be a one character string, not %lld characters",
+ (long long) size);
+ g_free (string_);
+ return FALSE;
+ }
+
+ arg->v_uint32 = g_utf8_get_char (string_);
+ g_free (string_);
+
+ return TRUE;
+}
+
+static gboolean
+_pygi_marshal_from_py_gtype (PyObject *py_arg,
+ GIArgument *arg)
+{
+ long type_ = pyg_type_from_object (py_arg);
+
+ if (type_ == 0) {
+ PyErr_Format (PyExc_TypeError, "Must be gobject.GType, not %s",
+ py_arg->ob_type->tp_name);
+ return FALSE;
+ }
+
+ arg->v_long = type_;
+ return TRUE;
+}
+
+static gboolean
+_pygi_marshal_from_py_utf8 (PyObject *py_arg,
+ GIArgument *arg,
+ gpointer *cleanup_data)
+{
+ gchar *string_;
+
+ if (py_arg == Py_None) {
+ arg->v_pointer = NULL;
+ return TRUE;
+ }
+
+ if (PyUnicode_Check (py_arg)) {
+ PyObject *pystr_obj = PyUnicode_AsUTF8String (py_arg);
+ if (!pystr_obj)
+ return FALSE;
+
+ string_ = g_strdup (PYGLIB_PyBytes_AsString (pystr_obj));
+ Py_DECREF (pystr_obj);
+ }
+#if PY_VERSION_HEX < 0x03000000
+ else if (PyString_Check (py_arg)) {
+ string_ = g_strdup (PyString_AsString (py_arg));
+ }
+#endif
+ else {
+ PyErr_Format (PyExc_TypeError, "Must be string, not %s",
+ py_arg->ob_type->tp_name);
+ return FALSE;
+ }
+
+ arg->v_string = string_;
+ *cleanup_data = arg->v_string;
+ return TRUE;
+}
+
+static gboolean
+_pygi_marshal_from_py_filename (PyObject *py_arg,
+ GIArgument *arg,
+ gpointer *cleanup_data)
+{
+ gchar *string_;
+ GError *error = NULL;
+
+ if (PyUnicode_Check (py_arg)) {
+ PyObject *pystr_obj = PyUnicode_AsUTF8String (py_arg);
+ if (!pystr_obj)
+ return FALSE;
+
+ string_ = g_strdup (PYGLIB_PyBytes_AsString (pystr_obj));
+ Py_DECREF (pystr_obj);
+ }
+#if PY_VERSION_HEX < 0x03000000
+ else if (PyString_Check (py_arg)) {
+ string_ = g_strdup (PyString_AsString (py_arg));
+ }
+#endif
+ else {
+ PyErr_Format (PyExc_TypeError, "Must be string, not %s",
+ py_arg->ob_type->tp_name);
+ return FALSE;
+ }
+
+ arg->v_string = g_filename_from_utf8 (string_, -1, NULL, NULL, &error);
+ g_free (string_);
+
+ if (arg->v_string == NULL) {
+ PyErr_SetString (PyExc_Exception, error->message);
+ g_error_free (error);
+ /* TODO: Convert the error to an exception. */
+ return FALSE;
+ }
+
+ *cleanup_data = arg->v_string;
+ return TRUE;
+}
+
+static gboolean
+_pygi_marshal_from_py_long (PyObject *object, /* in */
+ GIArgument *arg, /* out */
+ GITypeTag type_tag,
+ GITransfer transfer)
+{
+ PyObject *number;
+
+ if (!PyNumber_Check (object)) {
+ PyErr_Format (PyExc_TypeError, "Must be number, not %s",
+ object->ob_type->tp_name);
+ return FALSE;
+ }
+
+#if PY_MAJOR_VERSION < 3
+ {
+ PyObject *tmp = PyNumber_Int (object);
+ if (tmp) {
+ number = PyNumber_Long (tmp);
+ Py_DECREF (tmp);
+ } else {
+ number = PyNumber_Long (object);
+ }
+ }
+#else
+ number = PyNumber_Long (object);
+#endif
+
+ if (number == NULL) {
+ PyErr_SetString (PyExc_TypeError, "expected int argument");
+ return FALSE;
+ }
+
+ switch (type_tag) {
+ case GI_TYPE_TAG_INT8:
+ {
+ long long_value = PyLong_AsLong (number);
+ if (PyErr_Occurred()) {
+ break;
+ } else if (long_value < G_MININT8 || long_value > G_MAXINT8) {
+ PyErr_Format (PyExc_OverflowError, "%ld not in range %ld to %ld",
+ long_value, (long)G_MININT8, (long)G_MAXINT8);
+ } else {
+ arg->v_int8 = long_value;
+ }
+ break;
+ }
+
+ case GI_TYPE_TAG_UINT8:
+ {
+ long long_value = PyLong_AsLong (number);
+ if (PyErr_Occurred()) {
+ break;
+ } else if (long_value < 0 || long_value > G_MAXUINT8) {
+ PyErr_Format (PyExc_OverflowError, "%ld not in range %ld to %ld",
+ long_value, (long)0, (long)G_MAXUINT8);
+ } else {
+ arg->v_uint8 = long_value;
+ }
+ break;
+ }
+
+ case GI_TYPE_TAG_INT16:
+ {
+ long long_value = PyLong_AsLong (number);
+ if (PyErr_Occurred()) {
+ break;
+ } else if (long_value < G_MININT16 || long_value > G_MAXINT16) {
+ PyErr_Format (PyExc_OverflowError, "%ld not in range %ld to %ld",
+ long_value, (long)G_MININT16, (long)G_MAXINT16);
+ } else {
+ arg->v_int16 = long_value;
+ }
+ break;
+ }
+
+ case GI_TYPE_TAG_UINT16:
+ {
+ long long_value = PyLong_AsLong (number);
+ if (PyErr_Occurred()) {
+ break;
+ } else if (long_value < 0 || long_value > G_MAXUINT16) {
+ PyErr_Format (PyExc_OverflowError, "%ld not in range %ld to %ld",
+ long_value, (long)0, (long)G_MAXUINT16);
+ } else {
+ arg->v_uint16 = long_value;
+ }
+ break;
+ }
+
+ case GI_TYPE_TAG_INT32:
+ {
+ long long_value = PyLong_AsLong (number);
+ if (PyErr_Occurred()) {
+ break;
+ } else if (long_value < G_MININT32 || long_value > G_MAXINT32) {
+ PyErr_Format (PyExc_OverflowError, "%ld not in range %ld to %ld",
+ long_value, (long)G_MININT32, (long)G_MAXINT32);
+ } else {
+ arg->v_int32 = long_value;
+ }
+ break;
+ }
+
+ case GI_TYPE_TAG_UINT32:
+ {
+ PY_LONG_LONG long_value = PyLong_AsLongLong (number);
+ if (PyErr_Occurred()) {
+ break;
+ } else if (long_value < 0 || long_value > G_MAXUINT32) {
+ PyErr_Format (PyExc_OverflowError, "%lld not in range %ld to %lu",
+ long_value, (long)0, (unsigned long)G_MAXUINT32);
+ } else {
+ arg->v_uint32 = long_value;
+ }
+ break;
+ }
+
+ case GI_TYPE_TAG_INT64:
+ {
+ /* Rely on Python overflow error and convert to ValueError for 64 bit values */
+ arg->v_int64 = PyLong_AsLongLong (number);
+ break;
+ }
+
+ case GI_TYPE_TAG_UINT64:
+ {
+ /* Rely on Python overflow error and convert to ValueError for 64 bit values */
+ arg->v_uint64 = PyLong_AsUnsignedLongLong (number);
+ break;
+ }
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ Py_DECREF (number);
+
+ if (PyErr_Occurred())
+ return FALSE;
+ return TRUE;
+}
+
+gboolean
+_pygi_marshal_from_py_basic_type (PyObject *object, /* in */
+ GIArgument *arg, /* out */
+ GITypeTag type_tag,
+ GITransfer transfer,
+ gpointer *cleanup_data /* out */)
+{
+ switch (type_tag) {
+ case GI_TYPE_TAG_VOID:
+ g_warn_if_fail (transfer == GI_TRANSFER_NOTHING);
+ if (object == Py_None) {
+ arg->v_pointer = NULL;
+ } else if (!PYGLIB_PyLong_Check(object) && !PyLong_Check(object)) {
+ PyErr_SetString(PyExc_TypeError,
+ "Pointer assignment is restricted to integer values. "
+ "See: https://bugzilla.gnome.org/show_bug.cgi?id=683599");
+ } else {
+ arg->v_pointer = PyLong_AsVoidPtr (object);
+ *cleanup_data = arg->v_pointer;
+ }
+ break;
+ case GI_TYPE_TAG_INT8:
+ case GI_TYPE_TAG_UINT8:
+ if (PYGLIB_PyBytes_Check (object)) {
+ if (PYGLIB_PyBytes_Size (object) != 1) {
+ PyErr_Format (PyExc_TypeError, "Must be a single character");
+ return FALSE;
+ }
+ if (type_tag == GI_TYPE_TAG_INT8) {
+ arg->v_int8 = (gint8)(PYGLIB_PyBytes_AsString (object)[0]);
+ } else {
+ arg->v_uint8 = (guint8)(PYGLIB_PyBytes_AsString (object)[0]);
+ }
+ } else {
+ return _pygi_marshal_from_py_long (object, arg, type_tag, transfer);
+ }
+ break;
+ case GI_TYPE_TAG_INT16:
+ case GI_TYPE_TAG_UINT16:
+ case GI_TYPE_TAG_INT32:
+ case GI_TYPE_TAG_UINT32:
+ case GI_TYPE_TAG_INT64:
+ case GI_TYPE_TAG_UINT64:
+ return _pygi_marshal_from_py_long (object, arg, type_tag, transfer);
+
+ case GI_TYPE_TAG_BOOLEAN:
+ arg->v_boolean = PyObject_IsTrue (object);
+ break;
+
+ case GI_TYPE_TAG_FLOAT:
+ return _pygi_marshal_from_py_float (object, arg);
+
+ case GI_TYPE_TAG_DOUBLE:
+ return _pygi_marshal_from_py_double (object, arg);
+
+ case GI_TYPE_TAG_GTYPE:
+ return _pygi_marshal_from_py_gtype (object, arg);
+
+ case GI_TYPE_TAG_UNICHAR:
+ return _pygi_marshal_from_py_unichar (object, arg);
+
+ case GI_TYPE_TAG_UTF8:
+ return _pygi_marshal_from_py_utf8 (object, arg, cleanup_data);
+
+ case GI_TYPE_TAG_FILENAME:
+ return _pygi_marshal_from_py_filename (object, arg, cleanup_data);
+
+ default:
+ return FALSE;
+ }
+
+ if (PyErr_Occurred())
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+_pygi_marshal_from_py_basic_type_cache_adapter (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ GIArgument *arg,
+ gpointer *cleanup_data)
+{
+ return _pygi_marshal_from_py_basic_type (py_arg,
+ arg,
+ arg_cache->type_tag,
+ arg_cache->transfer,
+ cleanup_data);
+}
+
+static void
+_pygi_marshal_cleanup_from_py_utf8 (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ gpointer data,
+ gboolean was_processed)
+{
+ /* We strdup strings so free unless ownership is transferred to C. */
+ if (was_processed && arg_cache->transfer == GI_TRANSFER_NOTHING)
+ g_free (data);
+}
+
+static void
+_arg_cache_from_py_void_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_void;
+}
+
+
+static void
+_arg_cache_from_py_basic_type_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_basic_type_cache_adapter;
+}
+
+static void
+_arg_cache_from_py_utf8_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->from_py_marshaller = _pygi_marshal_from_py_basic_type_cache_adapter;
+ arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_utf8;
+}
+
+
+/*
+ * To Python Marshaling
+ */
+
+
+static PyObject *
+_pygi_marshal_to_py_void (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ GIArgument *arg)
+{
+ if (arg_cache->is_pointer) {
+ return PyLong_FromVoidPtr (arg->v_pointer);
+ }
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+_pygi_marshal_to_py_unichar (GIArgument *arg)
+{
+ PyObject *py_obj = NULL;
+
+ /* Preserve the bidirectional mapping between 0 and "" */
+ if (arg->v_uint32 == 0) {
+ py_obj = PYGLIB_PyUnicode_FromString ("");
+ } else if (g_unichar_validate (arg->v_uint32)) {
+ gchar utf8[6];
+ gint bytes;
+
+ bytes = g_unichar_to_utf8 (arg->v_uint32, utf8);
+ py_obj = PYGLIB_PyUnicode_FromStringAndSize ((char*)utf8, bytes);
+ } else {
+ /* TODO: Convert the error to an exception. */
+ PyErr_Format (PyExc_TypeError,
+ "Invalid unicode codepoint %" G_GUINT32_FORMAT,
+ arg->v_uint32);
+ }
+
+ return py_obj;
+}
+
+static PyObject *
+_pygi_marshal_to_py_utf8 (GIArgument *arg)
+{
+ PyObject *py_obj = NULL;
+ if (arg->v_string == NULL) {
+ Py_RETURN_NONE;
+ }
+
+ py_obj = PYGLIB_PyUnicode_FromString (arg->v_string);
+ return py_obj;
+}
+
+static PyObject *
+_pygi_marshal_to_py_filename (GIArgument *arg)
+{
+ gchar *string = NULL;
+ PyObject *py_obj = NULL;
+ GError *error = NULL;
+
+ if (arg->v_string == NULL) {
+ Py_RETURN_NONE;
+ }
+
+ string = g_filename_to_utf8 (arg->v_string, -1, NULL, NULL, &error);
+ if (string == NULL) {
+ PyErr_SetString (PyExc_Exception, error->message);
+ /* TODO: Convert the error to an exception. */
+ return NULL;
+ }
+
+ py_obj = PYGLIB_PyUnicode_FromString (string);
+ g_free (string);
+
+ return py_obj;
+}
+
+
+/**
+ * _pygi_marshal_to_py_basic_type:
+ * @arg: The argument to convert to an object.
+ * @type_tag: Type tag for @arg
+ * @transfer: Transfer annotation
+ *
+ * Convert the given argument to a Python object. This function
+ * is restricted to simple types that only require the GITypeTag
+ * and GITransfer. For a more complete conversion routine, use:
+ * _pygi_argument_to_object.
+ *
+ * Returns: A PyObject representing @arg or NULL if it cannot convert
+ * the argument.
+ */
+PyObject *
+_pygi_marshal_to_py_basic_type (GIArgument *arg,
+ GITypeTag type_tag,
+ GITransfer transfer)
+{
+ switch (type_tag) {
+ case GI_TYPE_TAG_BOOLEAN:
+ return PyBool_FromLong (arg->v_boolean);
+
+ case GI_TYPE_TAG_INT8:
+ return PYGLIB_PyLong_FromLong (arg->v_int8);
+
+ case GI_TYPE_TAG_UINT8:
+ return PYGLIB_PyLong_FromLong (arg->v_uint8);
+
+ case GI_TYPE_TAG_INT16:
+ return PYGLIB_PyLong_FromLong (arg->v_int16);
+
+ case GI_TYPE_TAG_UINT16:
+ return PYGLIB_PyLong_FromLong (arg->v_uint16);
+
+ case GI_TYPE_TAG_INT32:
+ return PYGLIB_PyLong_FromLong (arg->v_int32);
+
+ case GI_TYPE_TAG_UINT32:
+ return PyLong_FromLongLong (arg->v_uint32);
+
+ case GI_TYPE_TAG_INT64:
+ return PyLong_FromLongLong (arg->v_int64);
+
+ case GI_TYPE_TAG_UINT64:
+ return PyLong_FromUnsignedLongLong (arg->v_uint64);
+
+ case GI_TYPE_TAG_FLOAT:
+ return PyFloat_FromDouble (arg->v_float);
+
+ case GI_TYPE_TAG_DOUBLE:
+ return PyFloat_FromDouble (arg->v_double);
+
+ case GI_TYPE_TAG_GTYPE:
+ return pyg_type_wrapper_new ( (GType) arg->v_long);
+
+ case GI_TYPE_TAG_UNICHAR:
+ return _pygi_marshal_to_py_unichar (arg);
+
+ case GI_TYPE_TAG_UTF8:
+ return _pygi_marshal_to_py_utf8 (arg);
+
+ case GI_TYPE_TAG_FILENAME:
+ return _pygi_marshal_to_py_filename (arg);
+
+ default:
+ return NULL;
+ }
+ return NULL;
+}
+
+static PyObject *
+_pygi_marshal_to_py_basic_type_cache_adapter (PyGIInvokeState *state,
+ PyGICallableCache *callable_cache,
+ PyGIArgCache *arg_cache,
+ GIArgument *arg)
+{
+ return _pygi_marshal_to_py_basic_type (arg,
+ arg_cache->type_tag,
+ arg_cache->transfer);
+}
+
+static void
+_pygi_marshal_cleanup_to_py_utf8 (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ PyObject *dummy,
+ gpointer data,
+ gboolean was_processed)
+{
+ /* Python copies the string so we need to free it
+ if the interface is transfering ownership,
+ whether or not it has been processed yet */
+ if (arg_cache->transfer == GI_TRANSFER_EVERYTHING)
+ g_free (data);
+}
+
+
+
+static void
+_arg_cache_to_py_basic_type_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_basic_type_cache_adapter;
+}
+
+static void
+_arg_cache_to_py_void_setup (PyGIArgCache *arg_cache)
+{
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_void;
+}
+
+static void
+_arg_cache_to_py_utf8_setup (PyGIArgCache *arg_cache,
+ GITransfer transfer)
+{
+ arg_cache->to_py_marshaller = _pygi_marshal_to_py_basic_type_cache_adapter;
+ arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_utf8;
+}
+
+/*
+ * Basic Type Interface
+ */
+
+static gboolean
+pygi_arg_basic_type_setup_from_info (PyGIArgCache *arg_cache,
+ GITypeInfo *type_info,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ PyGIDirection direction)
+{
+ GITypeTag type_tag = g_type_info_get_tag (type_info);
+
+ if (!pygi_arg_base_setup (arg_cache, type_info, arg_info, transfer, direction))
+ return FALSE;
+
+ switch (type_tag) {
+ case GI_TYPE_TAG_VOID:
+ if (direction & PYGI_DIRECTION_FROM_PYTHON)
+ _arg_cache_from_py_void_setup (arg_cache);
+
+ if (direction & PYGI_DIRECTION_TO_PYTHON)
+ _arg_cache_to_py_void_setup (arg_cache);
+
+ break;
+ case GI_TYPE_TAG_BOOLEAN:
+ case GI_TYPE_TAG_INT8:
+ case GI_TYPE_TAG_UINT8:
+ case GI_TYPE_TAG_INT16:
+ case GI_TYPE_TAG_UINT16:
+ case GI_TYPE_TAG_INT32:
+ case GI_TYPE_TAG_UINT32:
+ case GI_TYPE_TAG_INT64:
+ case GI_TYPE_TAG_UINT64:
+ case GI_TYPE_TAG_FLOAT:
+ case GI_TYPE_TAG_DOUBLE:
+ case GI_TYPE_TAG_UNICHAR:
+ case GI_TYPE_TAG_GTYPE:
+ if (direction & PYGI_DIRECTION_FROM_PYTHON)
+ _arg_cache_from_py_basic_type_setup (arg_cache);
+
+ if (direction & PYGI_DIRECTION_TO_PYTHON)
+ _arg_cache_to_py_basic_type_setup (arg_cache);
+
+ break;
+ case GI_TYPE_TAG_UTF8:
+ case GI_TYPE_TAG_FILENAME:
+ if (direction & PYGI_DIRECTION_FROM_PYTHON)
+ _arg_cache_from_py_utf8_setup (arg_cache, transfer);
+
+ if (direction & PYGI_DIRECTION_TO_PYTHON)
+ _arg_cache_to_py_utf8_setup (arg_cache, transfer);
+
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ return TRUE;
+}
+
+PyGIArgCache *
+pygi_arg_basic_type_new_from_info (GITypeInfo *type_info,
+ GIArgInfo *arg_info,
+ GITransfer transfer,
+ PyGIDirection direction)
+{
+ gboolean res = FALSE;
+ PyGIArgCache *arg_cache = _arg_cache_alloc ();
+ if (arg_cache == NULL)
+ return NULL;
+
+ res = pygi_arg_basic_type_setup_from_info (arg_cache,
+ type_info,
+ arg_info,
+ transfer,
+ direction);
+ if (res) {
+ return arg_cache;
+ } else {
+ _pygi_arg_cache_free (arg_cache);
+ return NULL;
+ }
+}