Back to index

python3.2  3.2.2
Defines | Functions | Variables
stgdict.c File Reference
#include "Python.h"
#include <ffi.h>
#include "ctypes.h"

Go to the source code of this file.

Defines

#define realdict   ((PyObject *)&stgdict->dict)

Functions

static int PyCStgDict_init (StgDictObject *self, PyObject *args, PyObject *kwds)
static int PyCStgDict_clear (StgDictObject *self)
static void PyCStgDict_dealloc (StgDictObject *self)
int PyCStgDict_clone (StgDictObject *dst, StgDictObject *src)
StgDictObjectPyType_stgdict (PyObject *obj)
StgDictObjectPyObject_stgdict (PyObject *self)
static int MakeFields (PyObject *type, CFieldObject *descr, Py_ssize_t index, Py_ssize_t offset)
static int MakeAnonFields (PyObject *type)
int PyCStructUnionType_update_stgdict (PyObject *type, PyObject *fields, int isStruct)

Variables

PyTypeObject PyCStgDict_Type

Define Documentation

#define realdict   ((PyObject *)&stgdict->dict)

Function Documentation

static int MakeAnonFields ( PyObject type) [static]

Definition at line 258 of file stgdict.c.

{
    PyObject *anon;
    PyObject *anon_names;
    Py_ssize_t i;

    anon = PyObject_GetAttrString(type, "_anonymous_");
    if (anon == NULL) {
        PyErr_Clear();
        return 0;
    }
    anon_names = PySequence_Fast(anon, "_anonymous_ must be a sequence");
    Py_DECREF(anon);
    if (anon_names == NULL)
        return -1;

    for (i = 0; i < PySequence_Fast_GET_SIZE(anon_names); ++i) {
        PyObject *fname = PySequence_Fast_GET_ITEM(anon_names, i); /* borrowed */
        CFieldObject *descr = (CFieldObject *)PyObject_GetAttr(type, fname);
        if (descr == NULL) {
            Py_DECREF(anon_names);
            return -1;
        }
        assert(Py_TYPE(descr) == &PyCField_Type);
        descr->anonymous = 1;

        /* descr is in the field descriptor. */
        if (-1 == MakeFields(type, (CFieldObject *)descr,
                             ((CFieldObject *)descr)->index,
                             ((CFieldObject *)descr)->offset)) {
            Py_DECREF(descr);
            Py_DECREF(anon_names);
            return -1;
        }
        Py_DECREF(descr);
    }

    Py_DECREF(anon_names);
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int MakeFields ( PyObject type,
CFieldObject descr,
Py_ssize_t  index,
Py_ssize_t  offset 
) [static]

Definition at line 180 of file stgdict.c.

{
    Py_ssize_t i;
    PyObject *fields;
    PyObject *fieldlist;

    fields = PyObject_GetAttrString(descr->proto, "_fields_");
    if (fields == NULL)
        return -1;
    fieldlist = PySequence_Fast(fields, "_fields_ must be a sequence");
    Py_DECREF(fields);
    if (fieldlist == NULL)
        return -1;

    for (i = 0; i < PySequence_Fast_GET_SIZE(fieldlist); ++i) {
        PyObject *pair = PySequence_Fast_GET_ITEM(fieldlist, i); /* borrowed */
        PyObject *fname, *ftype, *bits;
        CFieldObject *fdescr;
        CFieldObject *new_descr;
        /* Convert to PyArg_UnpackTuple... */
        if (!PyArg_ParseTuple(pair, "OO|O", &fname, &ftype, &bits)) {
            Py_DECREF(fieldlist);
            return -1;
        }
        fdescr = (CFieldObject *)PyObject_GetAttr(descr->proto, fname);
        if (fdescr == NULL) {
            Py_DECREF(fieldlist);
            return -1;
        }
        if (Py_TYPE(fdescr) != &PyCField_Type) {
            PyErr_SetString(PyExc_TypeError, "unexpected type");
            Py_DECREF(fdescr);
            Py_DECREF(fieldlist);
            return -1;
        }
        if (fdescr->anonymous) {
            int rc = MakeFields(type, fdescr,
                                index + fdescr->index,
                                offset + fdescr->offset);
            Py_DECREF(fdescr);
            if (rc == -1) {
                Py_DECREF(fieldlist);
                return -1;
            }
            continue;
        }
        new_descr = (CFieldObject *)PyObject_CallObject((PyObject *)&PyCField_Type, NULL);
        if (new_descr == NULL) {
            Py_DECREF(fdescr);
            Py_DECREF(fieldlist);
            return -1;
        }
        assert(Py_TYPE(new_descr) == &PyCField_Type);
        new_descr->size = fdescr->size;
        new_descr->offset = fdescr->offset + offset;
        new_descr->index = fdescr->index + index;
        new_descr->proto = fdescr->proto;
        Py_XINCREF(new_descr->proto);
        new_descr->getfunc = fdescr->getfunc;
        new_descr->setfunc = fdescr->setfunc;

        Py_DECREF(fdescr);

        if (-1 == PyObject_SetAttr(type, fname, (PyObject *)new_descr)) {
            Py_DECREF(fieldlist);
            Py_DECREF(new_descr);
            return -1;
        }
        Py_DECREF(new_descr);
    }
    Py_DECREF(fieldlist);
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int PyCStgDict_clear ( StgDictObject self) [static]

Definition at line 31 of file stgdict.c.

{
    Py_CLEAR(self->proto);
    Py_CLEAR(self->argtypes);
    Py_CLEAR(self->converters);
    Py_CLEAR(self->restype);
    Py_CLEAR(self->checker);
    return 0;
}

Here is the caller graph for this function:

Definition at line 52 of file stgdict.c.

{
    char *d, *s;
    Py_ssize_t size;

    PyCStgDict_clear(dst);
    PyMem_Free(dst->ffi_type_pointer.elements);
    PyMem_Free(dst->format);
    dst->format = NULL;
    PyMem_Free(dst->shape);
    dst->shape = NULL;
    dst->ffi_type_pointer.elements = NULL;

    d = (char *)dst;
    s = (char *)src;
    memcpy(d + sizeof(PyDictObject),
           s + sizeof(PyDictObject),
           sizeof(StgDictObject) - sizeof(PyDictObject));

    Py_XINCREF(dst->proto);
    Py_XINCREF(dst->argtypes);
    Py_XINCREF(dst->converters);
    Py_XINCREF(dst->restype);
    Py_XINCREF(dst->checker);

    if (src->format) {
        dst->format = PyMem_Malloc(strlen(src->format) + 1);
        if (dst->format == NULL)
            return -1;
        strcpy(dst->format, src->format);
    }
    if (src->shape) {
        dst->shape = PyMem_Malloc(sizeof(Py_ssize_t) * src->ndim);
        if (dst->shape == NULL)
            return -1;
        memcpy(dst->shape, src->shape,
               sizeof(Py_ssize_t) * src->ndim);
    }

    if (src->ffi_type_pointer.elements == NULL)
        return 0;
    size = sizeof(ffi_type *) * (src->length + 1);
    dst->ffi_type_pointer.elements = PyMem_Malloc(size);
    if (dst->ffi_type_pointer.elements == NULL) {
        PyErr_NoMemory();
        return -1;
    }
    memcpy(dst->ffi_type_pointer.elements,
           src->ffi_type_pointer.elements,
           size);
    return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void PyCStgDict_dealloc ( StgDictObject self) [static]

Definition at line 42 of file stgdict.c.

Here is the call graph for this function:

static int PyCStgDict_init ( StgDictObject self,
PyObject args,
PyObject kwds 
) [static]

Definition at line 20 of file stgdict.c.

{
    if (PyDict_Type.tp_init((PyObject *)self, args, kwds) < 0)
        return -1;
    self->format = NULL;
    self->ndim = 0;
    self->shape = NULL;
    return 0;
}
int PyCStructUnionType_update_stgdict ( PyObject type,
PyObject fields,
int  isStruct 
)

Definition at line 304 of file stgdict.c.

{
    StgDictObject *stgdict, *basedict;
    Py_ssize_t len, offset, size, align, i;
    Py_ssize_t union_size, total_align;
    Py_ssize_t field_size = 0;
    int bitofs;
    PyObject *isPacked;
    int pack = 0;
    Py_ssize_t ffi_ofs;
    int big_endian;

    /* HACK Alert: I cannot be bothered to fix ctypes.com, so there has to
       be a way to use the old, broken sematics: _fields_ are not extended
       but replaced in subclasses.

       XXX Remove this in ctypes 1.0!
    */
    int use_broken_old_ctypes_semantics;

    if (fields == NULL)
        return 0;

#ifdef WORDS_BIGENDIAN
    big_endian = PyObject_HasAttrString(type, "_swappedbytes_") ? 0 : 1;
#else
    big_endian = PyObject_HasAttrString(type, "_swappedbytes_") ? 1 : 0;
#endif

    use_broken_old_ctypes_semantics = \
        PyObject_HasAttrString(type, "_use_broken_old_ctypes_structure_semantics_");

    isPacked = PyObject_GetAttrString(type, "_pack_");
    if (isPacked) {
        pack = PyLong_AsLong(isPacked);
        if (pack < 0 || PyErr_Occurred()) {
            Py_XDECREF(isPacked);
            PyErr_SetString(PyExc_ValueError,
                            "_pack_ must be a non-negative integer");
            return -1;
        }
        Py_DECREF(isPacked);
    } else
        PyErr_Clear();

    len = PySequence_Length(fields);
    if (len == -1) {
        PyErr_SetString(PyExc_TypeError,
                        "'_fields_' must be a sequence of pairs");
        return -1;
    }

    stgdict = PyType_stgdict(type);
    if (!stgdict)
        return -1;
    /* If this structure/union is already marked final we cannot assign
       _fields_ anymore. */

    if (stgdict->flags & DICTFLAG_FINAL) {/* is final ? */
        PyErr_SetString(PyExc_AttributeError,
                        "_fields_ is final");
        return -1;
    }

    if (stgdict->format) {
        PyMem_Free(stgdict->format);
        stgdict->format = NULL;
    }

    if (stgdict->ffi_type_pointer.elements)
        PyMem_Free(stgdict->ffi_type_pointer.elements);

    basedict = PyType_stgdict((PyObject *)((PyTypeObject *)type)->tp_base);
    if (basedict && !use_broken_old_ctypes_semantics) {
        size = offset = basedict->size;
        align = basedict->align;
        union_size = 0;
        total_align = align ? align : 1;
        stgdict->ffi_type_pointer.type = FFI_TYPE_STRUCT;
        stgdict->ffi_type_pointer.elements = PyMem_Malloc(sizeof(ffi_type *) * (basedict->length + len + 1));
        if (stgdict->ffi_type_pointer.elements == NULL) {
            PyErr_NoMemory();
            return -1;
        }
        memset(stgdict->ffi_type_pointer.elements, 0,
               sizeof(ffi_type *) * (basedict->length + len + 1));
        memcpy(stgdict->ffi_type_pointer.elements,
               basedict->ffi_type_pointer.elements,
               sizeof(ffi_type *) * (basedict->length));
        ffi_ofs = basedict->length;
    } else {
        offset = 0;
        size = 0;
        align = 0;
        union_size = 0;
        total_align = 1;
        stgdict->ffi_type_pointer.type = FFI_TYPE_STRUCT;
        stgdict->ffi_type_pointer.elements = PyMem_Malloc(sizeof(ffi_type *) * (len + 1));
        if (stgdict->ffi_type_pointer.elements == NULL) {
            PyErr_NoMemory();
            return -1;
        }
        memset(stgdict->ffi_type_pointer.elements, 0,
               sizeof(ffi_type *) * (len + 1));
        ffi_ofs = 0;
    }

    assert(stgdict->format == NULL);
    if (isStruct && !isPacked) {
        stgdict->format = _ctypes_alloc_format_string(NULL, "T{");
    } else {
        /* PEP3118 doesn't support union, or packed structures (well,
           only standard packing, but we dont support the pep for
           that). Use 'B' for bytes. */
        stgdict->format = _ctypes_alloc_format_string(NULL, "B");
    }

#define realdict ((PyObject *)&stgdict->dict)
    for (i = 0; i < len; ++i) {
        PyObject *name = NULL, *desc = NULL;
        PyObject *pair = PySequence_GetItem(fields, i);
        PyObject *prop;
        StgDictObject *dict;
        int bitsize = 0;

        if (!pair || !PyArg_ParseTuple(pair, "OO|i", &name, &desc, &bitsize)) {
            PyErr_SetString(PyExc_AttributeError,
                            "'_fields_' must be a sequence of pairs");
            Py_XDECREF(pair);
            return -1;
        }
        dict = PyType_stgdict(desc);
        if (dict == NULL) {
            Py_DECREF(pair);
            PyErr_Format(PyExc_TypeError,
                         "second item in _fields_ tuple (index %zd) must be a C type",
                         i);
            return -1;
        }
        stgdict->ffi_type_pointer.elements[ffi_ofs + i] = &dict->ffi_type_pointer;
        if (dict->flags & (TYPEFLAG_ISPOINTER | TYPEFLAG_HASPOINTER))
            stgdict->flags |= TYPEFLAG_HASPOINTER;
        dict->flags |= DICTFLAG_FINAL; /* mark field type final */
        if (PyTuple_Size(pair) == 3) { /* bits specified */
            switch(dict->ffi_type_pointer.type) {
            case FFI_TYPE_UINT8:
            case FFI_TYPE_UINT16:
            case FFI_TYPE_UINT32:
            case FFI_TYPE_SINT64:
            case FFI_TYPE_UINT64:
                break;

            case FFI_TYPE_SINT8:
            case FFI_TYPE_SINT16:
            case FFI_TYPE_SINT32:
                if (dict->getfunc != _ctypes_get_fielddesc("c")->getfunc
#ifdef CTYPES_UNICODE
                    && dict->getfunc != _ctypes_get_fielddesc("u")->getfunc
#endif
                    )
                    break;
                /* else fall through */
            default:
                PyErr_Format(PyExc_TypeError,
                             "bit fields not allowed for type %s",
                             ((PyTypeObject *)desc)->tp_name);
                Py_DECREF(pair);
                return -1;
            }
            if (bitsize <= 0 || bitsize > dict->size * 8) {
                PyErr_SetString(PyExc_ValueError,
                                "number of bits invalid for bit field");
                Py_DECREF(pair);
                return -1;
            }
        } else
            bitsize = 0;
        if (isStruct && !isPacked) {
            char *fieldfmt = dict->format ? dict->format : "B";
            char *fieldname = _PyUnicode_AsString(name);
            char *ptr;
            Py_ssize_t len = strlen(fieldname) + strlen(fieldfmt);
            char *buf = alloca(len + 2 + 1);

            sprintf(buf, "%s:%s:", fieldfmt, fieldname);

            ptr = stgdict->format;
            stgdict->format = _ctypes_alloc_format_string(stgdict->format, buf);
            PyMem_Free(ptr);

            if (stgdict->format == NULL) {
                Py_DECREF(pair);
                return -1;
            }
        }
        if (isStruct) {
            prop = PyCField_FromDesc(desc, i,
                                   &field_size, bitsize, &bitofs,
                                   &size, &offset, &align,
                                   pack, big_endian);
        } else /* union */ {
            size = 0;
            offset = 0;
            align = 0;
            prop = PyCField_FromDesc(desc, i,
                                   &field_size, bitsize, &bitofs,
                                   &size, &offset, &align,
                                   pack, big_endian);
            union_size = max(size, union_size);
        }
        total_align = max(align, total_align);

        if (!prop) {
            Py_DECREF(pair);
            return -1;
        }
        if (-1 == PyObject_SetAttr(type, name, prop)) {
            Py_DECREF(prop);
            Py_DECREF(pair);
            return -1;
        }
        Py_DECREF(pair);
        Py_DECREF(prop);
    }
#undef realdict

    if (isStruct && !isPacked) {
        char *ptr = stgdict->format;
        stgdict->format = _ctypes_alloc_format_string(stgdict->format, "}");
        PyMem_Free(ptr);
        if (stgdict->format == NULL)
            return -1;
    }

    if (!isStruct)
        size = union_size;

    /* Adjust the size according to the alignment requirements */
    size = ((size + total_align - 1) / total_align) * total_align;

    stgdict->ffi_type_pointer.alignment = Py_SAFE_DOWNCAST(total_align,
                                                           Py_ssize_t,
                                                           unsigned short);
    stgdict->ffi_type_pointer.size = size;

    stgdict->size = size;
    stgdict->align = total_align;
    stgdict->length = len;      /* ADD ffi_ofs? */

    /* We did check that this flag was NOT set above, it must not
       have been set until now. */
    if (stgdict->flags & DICTFLAG_FINAL) {
        PyErr_SetString(PyExc_AttributeError,
                        "Structure or union cannot contain itself");
        return -1;
    }
    stgdict->flags |= DICTFLAG_FINAL;

    return MakeAnonFields(type);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 167 of file stgdict.c.

{
    PyTypeObject *type = self->ob_type;
    if (!type->tp_dict || !PyCStgDict_CheckExact(type->tp_dict))
        return NULL;
    return (StgDictObject *)type->tp_dict;
}

Here is the caller graph for this function:

Definition at line 149 of file stgdict.c.

{
    PyTypeObject *type;

    if (!PyType_Check(obj))
        return NULL;
    type = (PyTypeObject *)obj;
    if (!type->tp_dict || !PyCStgDict_CheckExact(type->tp_dict))
        return NULL;
    return (StgDictObject *)type->tp_dict;
}

Variable Documentation

Definition at line 105 of file stgdict.c.