From c1a2a86a7b51f4dc5a5da9f8808552c38acadf9d Mon Sep 17 00:00:00 2001 From: Simon Feltman Date: Fri, 11 Oct 2013 20:12:01 -0700 Subject: cache refactoring: Move basic type arg setup and marshaling into new file Move all basic type arg caching and marshaling fragments into an isolated file where most functions are made static. pygi-basictype.h exposes: pygi_arg_basic_type_new_from_info, _pygi_marshal_from_py_basic_type, and _pygi_marshal_to_py_basic_type which allows continued use for all marshaling code paths. https://bugzilla.gnome.org/show_bug.cgi?id=709700 --- gi/Makefile.am | 2 + gi/pygi-argument.c | 1 + gi/pygi-basictype.c | 824 ++++++++++++++++++++++++++++++++++++++++++++++ gi/pygi-basictype.h | 42 +++ gi/pygi-cache.c | 82 +---- gi/pygi-cache.h | 1 + gi/pygi-marshal-cleanup.c | 26 -- gi/pygi-marshal-cleanup.h | 10 - gi/pygi-marshal-from-py.c | 478 --------------------------- gi/pygi-marshal-from-py.h | 18 - gi/pygi-marshal-to-py.c | 155 --------- gi/pygi-marshal-to-py.h | 11 - 12 files changed, 880 insertions(+), 770 deletions(-) create mode 100644 gi/pygi-basictype.c create mode 100644 gi/pygi-basictype.h diff --git a/gi/Makefile.am b/gi/Makefile.am index c2fcd5c9..91817d73 100644 --- a/gi/Makefile.am +++ b/gi/Makefile.am @@ -103,6 +103,8 @@ _gi_la_SOURCES = \ pygi-marshal-to-py.h \ pygi-marshal-cleanup.c \ pygi-marshal-cleanup.h \ + pygi-basictype.c \ + pygi-basictype.h \ pygi-hashtable.c \ pygi-hashtable.h _gi_la_CFLAGS = \ diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c index 67367a02..c58afa37 100644 --- a/gi/pygi-argument.c +++ b/gi/pygi-argument.c @@ -33,6 +33,7 @@ #include "pygi-marshal-from-py.h" #include "pygi-marshal-to-py.h" +#include "pygi-basictype.h" static gboolean 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 + * Copyright (C) 2014 Simon Feltman + * + * 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 . + */ + +#include +#include + +#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; + } +} diff --git a/gi/pygi-basictype.h b/gi/pygi-basictype.h new file mode 100644 index 00000000..7207e542 --- /dev/null +++ b/gi/pygi-basictype.h @@ -0,0 +1,42 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * vim: tabstop=4 shiftwidth=4 expandtab + * + * Copyright (C) 2014 Simon Feltman + * + * 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 . + */ + +#ifndef __PYGI_ARG_BASICTYPE_H__ +#define __PYGI_ARG_BASICTYPE_H__ + +#include +#include "pygi-cache.h" + +G_BEGIN_DECLS + +gboolean _pygi_marshal_from_py_basic_type (PyObject *object, /* in */ + GIArgument *arg, /* out */ + GITypeTag type_tag, + GITransfer transfer, + gpointer *cleanup_data); +PyObject *_pygi_marshal_to_py_basic_type (GIArgument *arg, /* in */ + GITypeTag type_tag, + GITransfer transfer); +PyGIArgCache *pygi_arg_basic_type_new_from_info (GITypeInfo *type_info, + GIArgInfo *arg_info, /* may be null */ + GITransfer transfer, + PyGIDirection direction); +G_END_DECLS + +#endif /*__PYGI_ARG_BASICTYPE_H__*/ diff --git a/gi/pygi-cache.c b/gi/pygi-cache.c index 0c6b94c5..9793ffee 100644 --- a/gi/pygi-cache.c +++ b/gi/pygi-cache.c @@ -28,6 +28,7 @@ #include "pygi-marshal-cleanup.h" #include "pygi-type.h" #include "pygi-hashtable.h" +#include "pygi-basictype.h" PyGIArgCache * _arg_cache_new_for_interface (GIInterfaceInfo *iface_info, @@ -269,51 +270,12 @@ _callback_cache_new (GIArgInfo *arg_info, return cc; } -static PyGIArgCache * +PyGIArgCache * _arg_cache_alloc (void) { return g_slice_new0 (PyGIArgCache); } -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_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_from_py_void_setup (PyGIArgCache *arg_cache) -{ - arg_cache->from_py_marshaller = _pygi_marshal_from_py_void; -} - -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_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; -} - -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; -} static PyGIArgCache* _arg_cache_array_len_arg_setup (PyGIArgCache *arg_cache, @@ -718,17 +680,6 @@ _arg_cache_new (GITypeInfo *type_info, switch (type_tag) { case GI_TYPE_TAG_VOID: - arg_cache = _arg_cache_alloc (); - if (arg_cache == NULL) - break; - - 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: @@ -742,30 +693,17 @@ _arg_cache_new (GITypeInfo *type_info, case GI_TYPE_TAG_DOUBLE: case GI_TYPE_TAG_UNICHAR: case GI_TYPE_TAG_GTYPE: - arg_cache = _arg_cache_alloc (); - if (arg_cache == NULL) - break; - - 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: - arg_cache = _arg_cache_alloc (); - if (arg_cache == NULL) - break; - - 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); + arg_cache = pygi_arg_basic_type_new_from_info (type_info, arg_info, transfer, direction); + if (arg_cache) { + arg_cache->py_arg_index = py_arg_index; + arg_cache->c_arg_index = c_arg_index; + return arg_cache; + } else { + return NULL; + } - break; case GI_TYPE_TAG_ARRAY: { PyGISequenceCache *seq_cache = diff --git a/gi/pygi-cache.h b/gi/pygi-cache.h index e1b0649e..82e25197 100644 --- a/gi/pygi-cache.h +++ b/gi/pygi-cache.h @@ -211,6 +211,7 @@ pygi_arg_interface_setup (PyGIInterfaceCache *iface_cache, PyGIDirection direction, GIInterfaceInfo *iface_info); +PyGIArgCache * _arg_cache_alloc (void); PyGIArgCache * _arg_cache_new (GITypeInfo *type_info, GIArgInfo *arg_info, GITransfer transfer, diff --git a/gi/pygi-marshal-cleanup.c b/gi/pygi-marshal-cleanup.c index 38783d90..0bf08a9c 100644 --- a/gi/pygi-marshal-cleanup.c +++ b/gi/pygi-marshal-cleanup.c @@ -206,32 +206,6 @@ pygi_marshal_cleanup_args_to_py_parameter_fail (PyGIInvokeState *state, state->failed = TRUE; } -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); -} - -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); -} - void _pygi_marshal_cleanup_from_py_interface_object (PyGIInvokeState *state, PyGIArgCache *arg_cache, diff --git a/gi/pygi-marshal-cleanup.h b/gi/pygi-marshal-cleanup.h index 70a91c87..878716e3 100644 --- a/gi/pygi-marshal-cleanup.h +++ b/gi/pygi-marshal-cleanup.h @@ -40,16 +40,6 @@ void pygi_marshal_cleanup_args_to_py_parameter_fail (PyGIInvokeState *state, PyGICallableCache *cache, gssize failed_to_py_arg_index); -void _pygi_marshal_cleanup_from_py_utf8 (PyGIInvokeState *state, - PyGIArgCache *arg_cache, - PyObject *py_arg, - gpointer data, - gboolean was_processed); -void _pygi_marshal_cleanup_to_py_utf8 (PyGIInvokeState *state, - PyGIArgCache *arg_cache, - PyObject *dummy, - gpointer data, - gboolean was_processed); void _pygi_marshal_cleanup_from_py_interface_struct_gvalue (PyGIInvokeState *state, PyGIArgCache *arg_cache, PyObject *py_arg, diff --git a/gi/pygi-marshal-from-py.c b/gi/pygi-marshal-from-py.c index e3b8ae8e..b143727c 100644 --- a/gi/pygi-marshal-from-py.c +++ b/gi/pygi-marshal-from-py.c @@ -242,484 +242,6 @@ _is_union_member (GIInterfaceInfo *interface_info, PyObject *py_arg) { return is_member; } -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; -} - -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); -} - gboolean _pygi_marshal_from_py_array (PyGIInvokeState *state, PyGICallableCache *callable_cache, diff --git a/gi/pygi-marshal-from-py.h b/gi/pygi-marshal-from-py.h index 83d074a2..b1e56387 100644 --- a/gi/pygi-marshal-from-py.h +++ b/gi/pygi-marshal-from-py.h @@ -33,12 +33,6 @@ G_BEGIN_DECLS gboolean _pygi_marshal_from_py_ssize_t (PyGIArgCache *arg_cache, Py_ssize_t size, GIArgument *arg); -gboolean _pygi_marshal_from_py_void (PyGIInvokeState *state, - PyGICallableCache *callable_cache, - PyGIArgCache *arg_cache, - PyObject *py_arg, - GIArgument *arg, - gpointer *cleanup_data); gboolean _pygi_marshal_from_py_array (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, @@ -107,18 +101,6 @@ gboolean _pygi_marshal_from_py_interface_union (PyGIInvokeState *state, gpointer *cleanup_data); /* Simplified marshalers shared between vfunc/closure and direct function calls. */ -gboolean _pygi_marshal_from_py_basic_type (PyObject *object, /* in */ - GIArgument *arg, /* out */ - GITypeTag type_tag, - GITransfer transfer, - gpointer *cleanup_data); -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); - gboolean _pygi_marshal_from_py_gobject (PyObject *py_arg, /*in*/ GIArgument *arg, /*out*/ GITransfer transfer); diff --git a/gi/pygi-marshal-to-py.c b/gi/pygi-marshal-to-py.c index 3c7d69e6..292f9628 100644 --- a/gi/pygi-marshal-to-py.c +++ b/gi/pygi-marshal-to-py.c @@ -112,161 +112,6 @@ gi_argument_to_gsize (GIArgument *arg_in, } } -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; -} - -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); -} - PyObject * _pygi_marshal_to_py_array (PyGIInvokeState *state, PyGICallableCache *callable_cache, diff --git a/gi/pygi-marshal-to-py.h b/gi/pygi-marshal-to-py.h index 48f1aa26..a6c62e8d 100644 --- a/gi/pygi-marshal-to-py.h +++ b/gi/pygi-marshal-to-py.h @@ -22,17 +22,6 @@ #ifndef __PYGI_MARSHAL_TO_PY_H__ #define __PYGI_MARSHAL_TO_PY_H__ -PyObject *_pygi_marshal_to_py_basic_type (GIArgument *arg, - GITypeTag type_tag, - GITransfer transfer); -PyObject *_pygi_marshal_to_py_basic_type_cache_adapter (PyGIInvokeState *state, - PyGICallableCache *callable_cache, - PyGIArgCache *arg_cache, - GIArgument *arg); -PyObject *_pygi_marshal_to_py_void (PyGIInvokeState *state, - PyGICallableCache *callable_cache, - PyGIArgCache *arg_cache, - GIArgument *arg); PyObject *_pygi_marshal_to_py_array (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, -- cgit v1.2.1