summaryrefslogtreecommitdiffstats
path: root/siplib/descriptors.c
diff options
context:
space:
mode:
authorTimothy Pearson <kb9vqf@pearsoncomputing.net>2011-11-22 02:59:34 -0600
committerTimothy Pearson <kb9vqf@pearsoncomputing.net>2011-11-22 02:59:34 -0600
commit6c4cc3653e8dd7668295f3e659b7eb4dc571b67c (patch)
treea559fd71fc982e35a4f984d85a5c9d92b764ae8c /siplib/descriptors.c
downloadsip4-tqt-6c4cc3653e8dd7668295f3e659b7eb4dc571b67c.tar.gz
sip4-tqt-6c4cc3653e8dd7668295f3e659b7eb4dc571b67c.zip
Initial import of SIP4 for Qt3
Diffstat (limited to 'siplib/descriptors.c')
-rw-r--r--siplib/descriptors.c305
1 files changed, 305 insertions, 0 deletions
diff --git a/siplib/descriptors.c b/siplib/descriptors.c
new file mode 100644
index 0000000..29277c5
--- /dev/null
+++ b/siplib/descriptors.c
@@ -0,0 +1,305 @@
+/*
+ * The implementation of the different descriptors.
+ *
+ * Copyright (c) 2010 Riverbank Computing Limited <info@riverbankcomputing.com>
+ *
+ * This file is part of SIP.
+ *
+ * This copy of SIP is licensed for use under the terms of the SIP License
+ * Agreement. See the file LICENSE for more details.
+ *
+ * This copy of SIP may also used under the terms of the GNU General Public
+ * License v2 or v3 as published by the Free Software Foundation which can be
+ * found in the files LICENSE-GPL2 and LICENSE-GPL3 included in this package.
+ *
+ * SIP is supplied WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+#include <Python.h>
+
+#include "sip.h"
+#include "sipint.h"
+
+
+/*****************************************************************************
+ * A method descriptor. We don't use the similar Python descriptor because it
+ * doesn't support a method having static and non-static overloads.
+ *****************************************************************************/
+
+
+/* Forward declarations of slots. */
+static PyObject *sipMethodDescr_descr_get(PyObject *self, PyObject *obj,
+ PyObject *type);
+static PyObject *sipMethodDescr_repr(PyObject *self);
+
+
+/*
+ * The object data structure.
+ */
+typedef struct _sipMethodDescr {
+ PyObject_HEAD
+
+ /* The method definition. */
+ PyMethodDef *pmd;
+} sipMethodDescr;
+
+
+/*
+ * The type data structure.
+ */
+PyTypeObject sipMethodDescr_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "sip.methoddescriptor", /* tp_name */
+ sizeof (sipMethodDescr), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ sipMethodDescr_repr, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ sipMethodDescr_descr_get, /* tp_descr_get */
+};
+
+
+/*
+ * Return a new method descriptor for the given method.
+ */
+PyObject *sipMethodDescr_New(PyMethodDef *pmd)
+{
+ PyObject *descr = PyType_GenericAlloc(&sipMethodDescr_Type, 0);
+
+ if (descr != NULL)
+ ((sipMethodDescr *)descr)->pmd = pmd;
+
+ return descr;
+}
+
+
+/*
+ * The descriptor's descriptor get slot.
+ */
+static PyObject *sipMethodDescr_descr_get(PyObject *self, PyObject *obj,
+ PyObject *type)
+{
+ sipMethodDescr *md = (sipMethodDescr *)self;
+
+ if (obj == Py_None)
+ obj = NULL;
+
+ return PyCFunction_New(md->pmd, obj);
+}
+
+
+/*
+ * The descriptor's repr slot. This is for the benefit of cProfile which seems
+ * to determine attribute names differently to the rest of Python.
+ */
+static PyObject *sipMethodDescr_repr(PyObject *self)
+{
+ sipMethodDescr *md = (sipMethodDescr *)self;
+
+ return
+#if PY_MAJOR_VERSION >= 3
+ PyUnicode_FromFormat
+#else
+ PyString_FromFormat
+#endif
+ ("<built-in method %s>", md->pmd->ml_name);
+}
+
+
+/*****************************************************************************
+ * A variable descriptor. We don't use the similar Python descriptor because
+ * it doesn't support static variables.
+ *****************************************************************************/
+
+
+/* Forward declarations of slots. */
+static PyObject *sipVariableDescr_descr_get(PyObject *self, PyObject *obj,
+ PyObject *type);
+static int sipVariableDescr_descr_set(PyObject *self, PyObject *obj,
+ PyObject *value);
+
+
+/*
+ * The object data structure.
+ */
+typedef struct _sipVariableDescr {
+ PyObject_HEAD
+
+ /* The getter/setter definition. */
+ sipVariableDef *vd;
+
+ /* The generated type definition. */
+ const sipTypeDef *td;
+
+ /* The generated container definition. */
+ const sipContainerDef *cod;
+} sipVariableDescr;
+
+
+/*
+ * The type data structure.
+ */
+PyTypeObject sipVariableDescr_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "sip.variabledescriptor", /* tp_name */
+ sizeof (sipVariableDescr), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ sipVariableDescr_descr_get, /* tp_descr_get */
+ sipVariableDescr_descr_set, /* tp_descr_set */
+};
+
+
+/* Forward declarations. */
+static int get_instance_address(sipVariableDescr *vd, PyObject *obj,
+ void **addrp);
+
+
+/*
+ * Return a new method descriptor for the given getter/setter.
+ */
+PyObject *sipVariableDescr_New(sipVariableDef *vd, const sipTypeDef *td,
+ const sipContainerDef *cod)
+{
+ PyObject *descr = PyType_GenericAlloc(&sipVariableDescr_Type, 0);
+
+ if (descr != NULL)
+ {
+ ((sipVariableDescr *)descr)->vd = vd;
+ ((sipVariableDescr *)descr)->td = td;
+ ((sipVariableDescr *)descr)->cod = cod;
+ }
+
+ return descr;
+}
+
+
+/*
+ * The descriptor's descriptor get slot.
+ */
+static PyObject *sipVariableDescr_descr_get(PyObject *self, PyObject *obj,
+ PyObject *type)
+{
+ sipVariableDescr *vd = (sipVariableDescr *)self;
+ void *addr;
+
+ if (get_instance_address(vd, obj, &addr) < 0)
+ return NULL;
+
+ return vd->vd->vd_getter(addr, type);
+}
+
+
+/*
+ * The descriptor's descriptor set slot.
+ */
+static int sipVariableDescr_descr_set(PyObject *self, PyObject *obj,
+ PyObject *value)
+{
+ sipVariableDescr *vd = (sipVariableDescr *)self;
+ void *addr;
+
+ /* Check that the value isn't const. */
+ if (vd->vd->vd_setter == NULL)
+ {
+ PyErr_Format(PyExc_AttributeError,
+ "'%s' object attribute '%s' is read-only",
+ sipPyNameOfContainer(vd->cod, vd->td), vd->vd->vd_name);
+
+ return -1;
+ }
+
+ if (get_instance_address(vd, obj, &addr) < 0)
+ return -1;
+
+ return vd->vd->vd_setter(addr, value, obj);
+}
+
+
+/*
+ * Return the C/C++ address of any instance.
+ */
+static int get_instance_address(sipVariableDescr *vd, PyObject *obj,
+ void **addrp)
+{
+ void *addr;
+
+ if (vd->vd->vd_is_static)
+ {
+ addr = NULL;
+ }
+ else
+ {
+ /* Check that access was via an instance. */
+ if (obj == NULL || obj == Py_None)
+ {
+ PyErr_Format(PyExc_AttributeError,
+ "'%s' object attribute '%s' is an instance attribute",
+ sipPyNameOfContainer(vd->cod, vd->td), vd->vd->vd_name);
+
+ return -1;
+ }
+
+ /* Get the C++ instance. */
+ if ((addr = sip_api_get_cpp_ptr((sipSimpleWrapper *)obj, vd->td)) == NULL)
+ return -1;
+ }
+
+ *addrp = addr;
+
+ return 0;
+}