[pygobject] cache refactoring: Move enum and flags arg setup and marshaling to new file



commit c2d5857e9b964427190e1230be32ae7919e86bc0
Author: Simon Feltman <sfeltman src gnome org>
Date:   Sat Oct 12 21:26:55 2013 -0700

    cache refactoring: Move enum and flags arg setup and marshaling to new file
    
    Move enum and flags argument cache setup and marshaling fragments into
    isolated file: pygi-enum-marshal.c. Remove pygi-marshal-from/to files.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=709700

 gi/Makefile.am            |    6 +-
 gi/pygi-argument.c        |    2 -
 gi/pygi-cache.c           |   74 ++-------
 gi/pygi-enum-marshal.c    |  408 +++++++++++++++++++++++++++++++++++++++++++++
 gi/pygi-enum-marshal.h    |   42 +++++
 gi/pygi-marshal-from-py.c |  206 -----------------------
 gi/pygi-marshal-from-py.h |   57 -------
 gi/pygi-marshal-to-py.c   |  152 -----------------
 gi/pygi-marshal-to-py.h   |   34 ----
 9 files changed, 464 insertions(+), 517 deletions(-)
---
diff --git a/gi/Makefile.am b/gi/Makefile.am
index 9c34c03..2a2473d 100644
--- a/gi/Makefile.am
+++ b/gi/Makefile.am
@@ -97,10 +97,6 @@ _gi_la_SOURCES = \
        pygi-invoke-state-struct.h \
        pygi-cache.h \
        pygi-cache.c \
-       pygi-marshal-from-py.c \
-       pygi-marshal-from-py.h \
-       pygi-marshal-to-py.c \
-       pygi-marshal-to-py.h \
        pygi-marshal-cleanup.c \
        pygi-marshal-cleanup.h \
        pygi-basictype.c \
@@ -113,6 +109,8 @@ _gi_la_SOURCES = \
        pygi-error.h \
        pygi-object.c \
        pygi-object.h \
+       pygi-enum-marshal.c \
+       pygi-enum-marshal.h \
        pygi-struct-marshal.c \
        pygi-struct-marshal.h \
        pygi-hashtable.c \
diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c
index f88ff62..5da8398 100644
--- a/gi/pygi-argument.c
+++ b/gi/pygi-argument.c
@@ -31,8 +31,6 @@
 #include <pyglib-python-compat.h>
 #include <pyglib.h>
 
-#include "pygi-marshal-from-py.h"
-#include "pygi-marshal-to-py.h"
 #include "pygi-basictype.h"
 #include "pygi-object.h"
 #include "pygi-struct-marshal.h"
diff --git a/gi/pygi-cache.c b/gi/pygi-cache.c
index aab2534..012ebcb 100644
--- a/gi/pygi-cache.c
+++ b/gi/pygi-cache.c
@@ -24,8 +24,6 @@
 
 #include "pygi-info.h"
 #include "pygi-cache.h"
-#include "pygi-marshal-to-py.h"
-#include "pygi-marshal-from-py.h"
 #include "pygi-marshal-cleanup.h"
 #include "pygi-type.h"
 #include "pygi-hashtable.h"
@@ -36,6 +34,7 @@
 #include "pygi-error.h"
 #include "pygi-object.h"
 #include "pygi-struct-marshal.h"
+#include "pygi-enum-marshal.h"
 
 
 /* _arg_info_default_value
@@ -252,35 +251,6 @@ _arg_cache_alloc (void)
     return g_slice_new0 (PyGIArgCache);
 }
 
-static void
-_arg_cache_from_py_interface_enum_setup (PyGIArgCache *arg_cache,
-                                         GITransfer transfer)
-{
-    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_enum;
-}
-
-static void
-_arg_cache_to_py_interface_enum_setup (PyGIArgCache *arg_cache,
-                                       GITransfer transfer)
-{
-    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_enum;
-}
-
-static void
-_arg_cache_from_py_interface_flags_setup (PyGIArgCache *arg_cache,
-                                          GITransfer transfer)
-{
-    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_flags;
-}
-
-static void
-_arg_cache_to_py_interface_flags_setup (PyGIArgCache *arg_cache,
-                                        GITransfer transfer)
-{
-    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_flags;
-}
-
-
 static PyGIArgCache *
 _arg_cache_new_for_interface (GIInterfaceInfo   *iface_info,
                               GITypeInfo        *type_info,
@@ -289,21 +259,18 @@ _arg_cache_new_for_interface (GIInterfaceInfo   *iface_info,
                               PyGIDirection      direction,
                               PyGICallableCache *callable_cache)
 {
-    PyGIArgCache *arg_cache = NULL;
     GIInfoType info_type;
 
     info_type = g_base_info_get_type ( (GIBaseInfo *)iface_info);
 
     switch (info_type) {
         case GI_INFO_TYPE_CALLBACK:
-        {
             return pygi_arg_callback_new_from_info (type_info,
                                                     arg_info,
                                                     transfer,
                                                     direction,
                                                     iface_info,
                                                     callable_cache);
-        }
         case GI_INFO_TYPE_OBJECT:
         case GI_INFO_TYPE_INTERFACE:
             return pygi_arg_gobject_new_from_info (type_info,
@@ -319,40 +286,23 @@ _arg_cache_new_for_interface (GIInterfaceInfo   *iface_info,
                                                   transfer,
                                                   direction,
                                                   iface_info);
-        default:
-            ;  /* pass through to old model of setup */
-    }
-
-    arg_cache = pygi_arg_interface_new_from_info (type_info,
-                                                  arg_info,
-                                                  transfer,
-                                                  direction,
-                                                  iface_info);
-    if (arg_cache == NULL)
-        return NULL;
-
-    switch (info_type) {
         case GI_INFO_TYPE_ENUM:
-            if (direction & PYGI_DIRECTION_FROM_PYTHON)
-               _arg_cache_from_py_interface_enum_setup (arg_cache, transfer);
-
-            if (direction & PYGI_DIRECTION_TO_PYTHON)
-               _arg_cache_to_py_interface_enum_setup (arg_cache, transfer);
-
-            break;
+            return pygi_arg_enum_new_from_info (type_info,
+                                                arg_info,
+                                                transfer,
+                                                direction,
+                                                iface_info);
         case GI_INFO_TYPE_FLAGS:
-            if (direction & PYGI_DIRECTION_FROM_PYTHON)
-               _arg_cache_from_py_interface_flags_setup (arg_cache, transfer);
-
-            if (direction & PYGI_DIRECTION_TO_PYTHON)
-               _arg_cache_to_py_interface_flags_setup (arg_cache, transfer);
-
-            break;
+            return pygi_arg_flags_new_from_info (type_info,
+                                                 arg_info,
+                                                 transfer,
+                                                 direction,
+                                                 iface_info);
         default:
             g_assert_not_reached ();
     }
 
-    return arg_cache;
+    return NULL;
 }
 
 PyGIArgCache *
diff --git a/gi/pygi-enum-marshal.c b/gi/pygi-enum-marshal.c
new file mode 100644
index 0000000..0a8e7e4
--- /dev/null
+++ b/gi/pygi-enum-marshal.c
@@ -0,0 +1,408 @@
+/* -*- 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 <glib.h>
+#include <Python.h>
+#include <pyglib-python-compat.h>
+
+#include "pygi-enum-marshal.h"
+#include "pygi-private.h"
+
+#ifdef _WIN32
+#ifdef _MSC_VER
+#include <math.h>
+
+#ifndef NAN
+static const unsigned long __nan[2] = {0xffffffff, 0x7fffffff};
+#define NAN (*(const float *) __nan)
+#endif
+
+#ifndef INFINITY
+#define INFINITY HUGE_VAL
+#endif
+
+#endif
+#endif
+
+static gboolean
+gi_argument_from_c_long (GIArgument *arg_out,
+                         long        c_long_in,
+                         GITypeTag   type_tag)
+{
+    switch (type_tag) {
+      case GI_TYPE_TAG_INT8:
+          arg_out->v_int8 = c_long_in;
+          return TRUE;
+      case GI_TYPE_TAG_UINT8:
+          arg_out->v_uint8 = c_long_in;
+          return TRUE;
+      case GI_TYPE_TAG_INT16:
+          arg_out->v_int16 = c_long_in;
+          return TRUE;
+      case GI_TYPE_TAG_UINT16:
+          arg_out->v_uint16 = c_long_in;
+          return TRUE;
+      case GI_TYPE_TAG_INT32:
+          arg_out->v_int32 = c_long_in;
+          return TRUE;
+      case GI_TYPE_TAG_UINT32:
+          arg_out->v_uint32 = c_long_in;
+          return TRUE;
+      case GI_TYPE_TAG_INT64:
+          arg_out->v_int64 = c_long_in;
+          return TRUE;
+      case GI_TYPE_TAG_UINT64:
+          arg_out->v_uint64 = c_long_in;
+          return TRUE;
+      default:
+          PyErr_Format (PyExc_TypeError,
+                        "Unable to marshal C long %ld to %s",
+                        c_long_in,
+                        g_type_tag_to_string (type_tag));
+          return FALSE;
+    }
+}
+
+static gboolean
+gi_argument_to_c_long (GIArgument *arg_in,
+                       long *c_long_out,
+                       GITypeTag type_tag)
+{
+    switch (type_tag) {
+      case GI_TYPE_TAG_INT8:
+          *c_long_out = arg_in->v_int8;
+          return TRUE;
+      case GI_TYPE_TAG_UINT8:
+          *c_long_out = arg_in->v_uint8;
+          return TRUE;
+      case GI_TYPE_TAG_INT16:
+          *c_long_out = arg_in->v_int16;
+          return TRUE;
+      case GI_TYPE_TAG_UINT16:
+          *c_long_out = arg_in->v_uint16;
+          return TRUE;
+      case GI_TYPE_TAG_INT32:
+          *c_long_out = arg_in->v_int32;
+          return TRUE;
+      case GI_TYPE_TAG_UINT32:
+          *c_long_out = arg_in->v_uint32;
+          return TRUE;
+      case GI_TYPE_TAG_INT64:
+          *c_long_out = arg_in->v_int64;
+          return TRUE;
+      case GI_TYPE_TAG_UINT64:
+          *c_long_out = arg_in->v_uint64;
+          return TRUE;
+      default:
+          PyErr_Format (PyExc_TypeError,
+                        "Unable to marshal %s to C long",
+                        g_type_tag_to_string (type_tag));
+          return FALSE;
+    }
+}
+
+static gboolean
+_pygi_marshal_from_py_interface_enum (PyGIInvokeState   *state,
+                                      PyGICallableCache *callable_cache,
+                                      PyGIArgCache      *arg_cache,
+                                      PyObject          *py_arg,
+                                      GIArgument        *arg,
+                                      gpointer          *cleanup_data)
+{
+    PyObject *py_long;
+    long c_long;
+    gint is_instance;
+    PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
+    GIBaseInfo *interface = NULL;
+
+    is_instance = PyObject_IsInstance (py_arg, iface_cache->py_type);
+
+    py_long = PYGLIB_PyNumber_Long (py_arg);
+    if (py_long == NULL) {
+        PyErr_Clear();
+        goto err;
+    }
+
+    c_long = PYGLIB_PyLong_AsLong (py_long);
+    Py_DECREF (py_long);
+
+    /* Write c_long into arg */
+    interface = g_type_info_get_interface (arg_cache->type_info);
+    assert(g_base_info_get_type (interface) == GI_INFO_TYPE_ENUM);
+    if (!gi_argument_from_c_long(arg,
+                                 c_long,
+                                 g_enum_info_get_storage_type ((GIEnumInfo *)interface))) {
+          g_assert_not_reached();
+          g_base_info_unref (interface);
+          return FALSE;
+    }
+
+    /* If this is not an instance of the Enum type that we want
+     * we need to check if the value is equivilant to one of the
+     * Enum's memebers */
+    if (!is_instance) {
+        int i;
+        gboolean is_found = FALSE;
+
+        for (i = 0; i < g_enum_info_get_n_values (iface_cache->interface_info); i++) {
+            GIValueInfo *value_info =
+                g_enum_info_get_value (iface_cache->interface_info, i);
+            glong enum_value = g_value_info_get_value (value_info);
+            g_base_info_unref ( (GIBaseInfo *)value_info);
+            if (c_long == enum_value) {
+                is_found = TRUE;
+                break;
+            }
+        }
+
+        if (!is_found)
+            goto err;
+    }
+
+    g_base_info_unref (interface);
+    return TRUE;
+
+err:
+    if (interface)
+        g_base_info_unref (interface);
+    PyErr_Format (PyExc_TypeError, "Expected a %s, but got %s",
+                  iface_cache->type_name, py_arg->ob_type->tp_name);
+    return FALSE;
+}
+
+static gboolean
+_pygi_marshal_from_py_interface_flags (PyGIInvokeState   *state,
+                                       PyGICallableCache *callable_cache,
+                                       PyGIArgCache      *arg_cache,
+                                       PyObject          *py_arg,
+                                       GIArgument        *arg,
+                                       gpointer          *cleanup_data)
+{
+    PyObject *py_long;
+    long c_long;
+    gint is_instance;
+    PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
+    GIBaseInfo *interface;
+
+    is_instance = PyObject_IsInstance (py_arg, iface_cache->py_type);
+
+    py_long = PYGLIB_PyNumber_Long (py_arg);
+    if (py_long == NULL) {
+        PyErr_Clear ();
+        goto err;
+    }
+
+    c_long = PYGLIB_PyLong_AsLong (py_long);
+    Py_DECREF (py_long);
+
+    /* only 0 or argument of type Flag is allowed */
+    if (!is_instance && c_long != 0)
+        goto err;
+
+    /* Write c_long into arg */
+    interface = g_type_info_get_interface (arg_cache->type_info);
+    g_assert (g_base_info_get_type (interface) == GI_INFO_TYPE_FLAGS);
+    if (!gi_argument_from_c_long(arg, c_long,
+                                 g_enum_info_get_storage_type ((GIEnumInfo *)interface))) {
+        g_base_info_unref (interface);
+        return FALSE;
+    }
+
+    g_base_info_unref (interface);
+    return TRUE;
+
+err:
+    PyErr_Format (PyExc_TypeError, "Expected a %s, but got %s",
+                  iface_cache->type_name, py_arg->ob_type->tp_name);
+    return FALSE;
+
+}
+
+static PyObject *
+_pygi_marshal_to_py_interface_enum (PyGIInvokeState   *state,
+                                    PyGICallableCache *callable_cache,
+                                    PyGIArgCache      *arg_cache,
+                                    GIArgument        *arg)
+{
+    PyObject *py_obj = NULL;
+    PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
+    GIBaseInfo *interface;
+    long c_long;
+
+    interface = g_type_info_get_interface (arg_cache->type_info);
+    g_assert (g_base_info_get_type (interface) == GI_INFO_TYPE_ENUM);
+
+    if (!gi_argument_to_c_long(arg, &c_long,
+                               g_enum_info_get_storage_type ((GIEnumInfo *)interface))) {
+        return NULL;
+    }
+
+    if (iface_cache->g_type == G_TYPE_NONE) {
+        py_obj = PyObject_CallFunction (iface_cache->py_type, "l", c_long);
+    } else {
+        py_obj = pyg_enum_from_gtype (iface_cache->g_type, c_long);
+    }
+    g_base_info_unref (interface);
+    return py_obj;
+}
+
+static PyObject *
+_pygi_marshal_to_py_interface_flags (PyGIInvokeState   *state,
+                                     PyGICallableCache *callable_cache,
+                                     PyGIArgCache      *arg_cache,
+                                     GIArgument        *arg)
+{
+    PyObject *py_obj = NULL;
+    PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
+    GIBaseInfo *interface;
+    long c_long;
+
+    interface = g_type_info_get_interface (arg_cache->type_info);
+    g_assert (g_base_info_get_type (interface) == GI_INFO_TYPE_FLAGS);
+
+    if (!gi_argument_to_c_long(arg, &c_long,
+                               g_enum_info_get_storage_type ((GIEnumInfo *)interface))) {
+        g_base_info_unref (interface);
+        return NULL;
+    }
+
+    g_base_info_unref (interface);
+    if (iface_cache->g_type == G_TYPE_NONE) {
+        /* An enum with a GType of None is an enum without GType */
+
+        PyObject *py_type = _pygi_type_import_by_gi_info (iface_cache->interface_info);
+        PyObject *py_args = NULL;
+
+        if (!py_type)
+            return NULL;
+
+        py_args = PyTuple_New (1);
+        if (PyTuple_SetItem (py_args, 0, PyLong_FromLong (c_long)) != 0) {
+            Py_DECREF (py_args);
+            Py_DECREF (py_type);
+            return NULL;
+        }
+
+        py_obj = PyObject_CallFunction (py_type, "l", c_long);
+
+        Py_DECREF (py_args);
+        Py_DECREF (py_type);
+    } else {
+        py_obj = pyg_flags_from_gtype (iface_cache->g_type, c_long);
+    }
+
+    return py_obj;
+}
+
+static gboolean
+pygi_arg_enum_setup_from_info (PyGIArgCache  *arg_cache,
+                               GITypeInfo    *type_info,
+                               GIArgInfo     *arg_info,
+                               GITransfer     transfer,
+                               PyGIDirection  direction)
+{
+    if (direction & PYGI_DIRECTION_FROM_PYTHON)
+        arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_enum;
+
+    if (direction & PYGI_DIRECTION_TO_PYTHON)
+        arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_enum;
+
+    return TRUE;
+}
+
+
+PyGIArgCache *
+pygi_arg_enum_new_from_info (GITypeInfo      *type_info,
+                             GIArgInfo       *arg_info,
+                             GITransfer       transfer,
+                             PyGIDirection    direction,
+                             GIInterfaceInfo *iface_info)
+{
+    gboolean res = FALSE;
+    PyGIArgCache *cache = NULL;
+
+    cache = pygi_arg_interface_new_from_info (type_info,
+                                              arg_info,
+                                              transfer,
+                                              direction,
+                                              iface_info);
+    if (cache == NULL)
+        return NULL;
+
+    res = pygi_arg_enum_setup_from_info (cache,
+                                         type_info,
+                                         arg_info,
+                                         transfer,
+                                         direction);
+    if (res) {
+        return cache;
+    } else {
+        _pygi_arg_cache_free (cache);
+        return NULL;
+    }
+}
+
+static gboolean
+pygi_arg_flags_setup_from_info (PyGIArgCache  *arg_cache,
+                                GITypeInfo    *type_info,
+                                GIArgInfo     *arg_info,
+                                GITransfer     transfer,
+                                PyGIDirection  direction)
+{
+    if (direction & PYGI_DIRECTION_FROM_PYTHON)
+        arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_flags;
+
+    if (direction & PYGI_DIRECTION_TO_PYTHON)
+        arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_flags;
+
+    return TRUE;
+}
+
+
+PyGIArgCache *
+pygi_arg_flags_new_from_info (GITypeInfo      *type_info,
+                              GIArgInfo       *arg_info,
+                              GITransfer       transfer,
+                              PyGIDirection    direction,
+                              GIInterfaceInfo *iface_info)
+{
+    gboolean res = FALSE;
+    PyGIArgCache *cache = NULL;
+
+    cache = pygi_arg_interface_new_from_info (type_info,
+                                              arg_info,
+                                              transfer,
+                                              direction,
+                                              iface_info);
+    if (cache == NULL)
+        return NULL;
+
+    res = pygi_arg_flags_setup_from_info (cache,
+                                          type_info,
+                                          arg_info,
+                                          transfer,
+                                          direction);
+    if (res) {
+        return cache;
+    } else {
+        _pygi_arg_cache_free (cache);
+        return NULL;
+    }
+}
diff --git a/gi/pygi-enum-marshal.h b/gi/pygi-enum-marshal.h
new file mode 100644
index 0000000..2fdcbc4
--- /dev/null
+++ b/gi/pygi-enum-marshal.h
@@ -0,0 +1,42 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * vim: tabstop=4 shiftwidth=4 expandtab
+ *
+ * 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/>.
+ */
+
+#ifndef __PYGI_ENUM_MARSHAL_H__
+#define __PYGI_ENUM_MARSHAL_H__
+
+#include <girepository.h>
+#include "pygi-cache.h"
+
+G_BEGIN_DECLS
+
+PyGIArgCache *pygi_arg_enum_new_from_info   (GITypeInfo      *type_info,
+                                             GIArgInfo       *arg_info,   /* may be null */
+                                             GITransfer       transfer,
+                                             PyGIDirection    direction,
+                                             GIInterfaceInfo *iface_info);
+
+PyGIArgCache *pygi_arg_flags_new_from_info  (GITypeInfo      *type_info,
+                                             GIArgInfo       *arg_info,   /* may be null */
+                                             GITransfer       transfer,
+                                             PyGIDirection    direction,
+                                             GIInterfaceInfo *iface_info);
+
+G_END_DECLS
+
+#endif /*__PYGI_ENUM_MARSHAL_H__*/


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]