diff options
author | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2011-11-22 02:59:34 -0600 |
---|---|---|
committer | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2011-11-22 02:59:34 -0600 |
commit | 6c4cc3653e8dd7668295f3e659b7eb4dc571b67c (patch) | |
tree | a559fd71fc982e35a4f984d85a5c9d92b764ae8c /siplib/descriptors.c | |
download | sip4-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.c | 305 |
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; +} |