ยปCore Development>Code coverage>Modules/_ctypes/stgdict.c

Python code coverage for Modules/_ctypes/stgdict.c

#countcontent
1n/a#include "Python.h"
2n/a#include <ffi.h>
3n/a#ifdef MS_WIN32
4n/a#include <windows.h>
5n/a#include <malloc.h>
6n/a#endif
7n/a#include "ctypes.h"
8n/a
9n/a/******************************************************************/
10n/a/*
11n/a StdDict - a dictionary subclass, containing additional C accessible fields
12n/a
13n/a XXX blabla more
14n/a*/
15n/a
16n/a/* Seems we need this, otherwise we get problems when calling
17n/a * PyDict_SetItem() (ma_lookup is NULL)
18n/a */
19n/astatic int
20n/aPyCStgDict_init(StgDictObject *self, PyObject *args, PyObject *kwds)
21n/a{
22n/a if (PyDict_Type.tp_init((PyObject *)self, args, kwds) < 0)
23n/a return -1;
24n/a self->format = NULL;
25n/a self->ndim = 0;
26n/a self->shape = NULL;
27n/a return 0;
28n/a}
29n/a
30n/astatic int
31n/aPyCStgDict_clear(StgDictObject *self)
32n/a{
33n/a Py_CLEAR(self->proto);
34n/a Py_CLEAR(self->argtypes);
35n/a Py_CLEAR(self->converters);
36n/a Py_CLEAR(self->restype);
37n/a Py_CLEAR(self->checker);
38n/a return 0;
39n/a}
40n/a
41n/astatic void
42n/aPyCStgDict_dealloc(StgDictObject *self)
43n/a{
44n/a PyCStgDict_clear(self);
45n/a PyMem_Free(self->format);
46n/a PyMem_Free(self->shape);
47n/a PyMem_Free(self->ffi_type_pointer.elements);
48n/a PyDict_Type.tp_dealloc((PyObject *)self);
49n/a}
50n/a
51n/aint
52n/aPyCStgDict_clone(StgDictObject *dst, StgDictObject *src)
53n/a{
54n/a char *d, *s;
55n/a Py_ssize_t size;
56n/a
57n/a PyCStgDict_clear(dst);
58n/a PyMem_Free(dst->ffi_type_pointer.elements);
59n/a PyMem_Free(dst->format);
60n/a dst->format = NULL;
61n/a PyMem_Free(dst->shape);
62n/a dst->shape = NULL;
63n/a dst->ffi_type_pointer.elements = NULL;
64n/a
65n/a d = (char *)dst;
66n/a s = (char *)src;
67n/a memcpy(d + sizeof(PyDictObject),
68n/a s + sizeof(PyDictObject),
69n/a sizeof(StgDictObject) - sizeof(PyDictObject));
70n/a
71n/a Py_XINCREF(dst->proto);
72n/a Py_XINCREF(dst->argtypes);
73n/a Py_XINCREF(dst->converters);
74n/a Py_XINCREF(dst->restype);
75n/a Py_XINCREF(dst->checker);
76n/a
77n/a if (src->format) {
78n/a dst->format = PyMem_Malloc(strlen(src->format) + 1);
79n/a if (dst->format == NULL) {
80n/a PyErr_NoMemory();
81n/a return -1;
82n/a }
83n/a strcpy(dst->format, src->format);
84n/a }
85n/a if (src->shape) {
86n/a dst->shape = PyMem_Malloc(sizeof(Py_ssize_t) * src->ndim);
87n/a if (dst->shape == NULL) {
88n/a PyErr_NoMemory();
89n/a return -1;
90n/a }
91n/a memcpy(dst->shape, src->shape,
92n/a sizeof(Py_ssize_t) * src->ndim);
93n/a }
94n/a
95n/a if (src->ffi_type_pointer.elements == NULL)
96n/a return 0;
97n/a size = sizeof(ffi_type *) * (src->length + 1);
98n/a dst->ffi_type_pointer.elements = PyMem_Malloc(size);
99n/a if (dst->ffi_type_pointer.elements == NULL) {
100n/a PyErr_NoMemory();
101n/a return -1;
102n/a }
103n/a memcpy(dst->ffi_type_pointer.elements,
104n/a src->ffi_type_pointer.elements,
105n/a size);
106n/a return 0;
107n/a}
108n/a
109n/aPyTypeObject PyCStgDict_Type = {
110n/a PyVarObject_HEAD_INIT(NULL, 0)
111n/a "StgDict",
112n/a sizeof(StgDictObject),
113n/a 0,
114n/a (destructor)PyCStgDict_dealloc, /* tp_dealloc */
115n/a 0, /* tp_print */
116n/a 0, /* tp_getattr */
117n/a 0, /* tp_setattr */
118n/a 0, /* tp_reserved */
119n/a 0, /* tp_repr */
120n/a 0, /* tp_as_number */
121n/a 0, /* tp_as_sequence */
122n/a 0, /* tp_as_mapping */
123n/a 0, /* tp_hash */
124n/a 0, /* tp_call */
125n/a 0, /* tp_str */
126n/a 0, /* tp_getattro */
127n/a 0, /* tp_setattro */
128n/a 0, /* tp_as_buffer */
129n/a Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
130n/a 0, /* tp_doc */
131n/a 0, /* tp_traverse */
132n/a 0, /* tp_clear */
133n/a 0, /* tp_richcompare */
134n/a 0, /* tp_weaklistoffset */
135n/a 0, /* tp_iter */
136n/a 0, /* tp_iternext */
137n/a 0, /* tp_methods */
138n/a 0, /* tp_members */
139n/a 0, /* tp_getset */
140n/a 0, /* tp_base */
141n/a 0, /* tp_dict */
142n/a 0, /* tp_descr_get */
143n/a 0, /* tp_descr_set */
144n/a 0, /* tp_dictoffset */
145n/a (initproc)PyCStgDict_init, /* tp_init */
146n/a 0, /* tp_alloc */
147n/a 0, /* tp_new */
148n/a 0, /* tp_free */
149n/a};
150n/a
151n/a/* May return NULL, but does not set an exception! */
152n/aStgDictObject *
153n/aPyType_stgdict(PyObject *obj)
154n/a{
155n/a PyTypeObject *type;
156n/a
157n/a if (!PyType_Check(obj))
158n/a return NULL;
159n/a type = (PyTypeObject *)obj;
160n/a if (!type->tp_dict || !PyCStgDict_CheckExact(type->tp_dict))
161n/a return NULL;
162n/a return (StgDictObject *)type->tp_dict;
163n/a}
164n/a
165n/a/* May return NULL, but does not set an exception! */
166n/a/*
167n/a This function should be as fast as possible, so we don't call PyType_stgdict
168n/a above but inline the code, and avoid the PyType_Check().
169n/a*/
170n/aStgDictObject *
171n/aPyObject_stgdict(PyObject *self)
172n/a{
173n/a PyTypeObject *type = self->ob_type;
174n/a if (!type->tp_dict || !PyCStgDict_CheckExact(type->tp_dict))
175n/a return NULL;
176n/a return (StgDictObject *)type->tp_dict;
177n/a}
178n/a
179n/a/* descr is the descriptor for a field marked as anonymous. Get all the
180n/a _fields_ descriptors from descr->proto, create new descriptors with offset
181n/a and index adjusted, and stuff them into type.
182n/a */
183n/astatic int
184n/aMakeFields(PyObject *type, CFieldObject *descr,
185n/a Py_ssize_t index, Py_ssize_t offset)
186n/a{
187n/a Py_ssize_t i;
188n/a PyObject *fields;
189n/a PyObject *fieldlist;
190n/a
191n/a fields = PyObject_GetAttrString(descr->proto, "_fields_");
192n/a if (fields == NULL)
193n/a return -1;
194n/a fieldlist = PySequence_Fast(fields, "_fields_ must be a sequence");
195n/a Py_DECREF(fields);
196n/a if (fieldlist == NULL)
197n/a return -1;
198n/a
199n/a for (i = 0; i < PySequence_Fast_GET_SIZE(fieldlist); ++i) {
200n/a PyObject *pair = PySequence_Fast_GET_ITEM(fieldlist, i); /* borrowed */
201n/a PyObject *fname, *ftype, *bits;
202n/a CFieldObject *fdescr;
203n/a CFieldObject *new_descr;
204n/a /* Convert to PyArg_UnpackTuple... */
205n/a if (!PyArg_ParseTuple(pair, "OO|O", &fname, &ftype, &bits)) {
206n/a Py_DECREF(fieldlist);
207n/a return -1;
208n/a }
209n/a fdescr = (CFieldObject *)PyObject_GetAttr(descr->proto, fname);
210n/a if (fdescr == NULL) {
211n/a Py_DECREF(fieldlist);
212n/a return -1;
213n/a }
214n/a if (Py_TYPE(fdescr) != &PyCField_Type) {
215n/a PyErr_SetString(PyExc_TypeError, "unexpected type");
216n/a Py_DECREF(fdescr);
217n/a Py_DECREF(fieldlist);
218n/a return -1;
219n/a }
220n/a if (fdescr->anonymous) {
221n/a int rc = MakeFields(type, fdescr,
222n/a index + fdescr->index,
223n/a offset + fdescr->offset);
224n/a Py_DECREF(fdescr);
225n/a if (rc == -1) {
226n/a Py_DECREF(fieldlist);
227n/a return -1;
228n/a }
229n/a continue;
230n/a }
231n/a new_descr = (CFieldObject *)_PyObject_CallNoArg((PyObject *)&PyCField_Type);
232n/a if (new_descr == NULL) {
233n/a Py_DECREF(fdescr);
234n/a Py_DECREF(fieldlist);
235n/a return -1;
236n/a }
237n/a assert(Py_TYPE(new_descr) == &PyCField_Type);
238n/a new_descr->size = fdescr->size;
239n/a new_descr->offset = fdescr->offset + offset;
240n/a new_descr->index = fdescr->index + index;
241n/a new_descr->proto = fdescr->proto;
242n/a Py_XINCREF(new_descr->proto);
243n/a new_descr->getfunc = fdescr->getfunc;
244n/a new_descr->setfunc = fdescr->setfunc;
245n/a
246n/a Py_DECREF(fdescr);
247n/a
248n/a if (-1 == PyObject_SetAttr(type, fname, (PyObject *)new_descr)) {
249n/a Py_DECREF(fieldlist);
250n/a Py_DECREF(new_descr);
251n/a return -1;
252n/a }
253n/a Py_DECREF(new_descr);
254n/a }
255n/a Py_DECREF(fieldlist);
256n/a return 0;
257n/a}
258n/a
259n/a/* Iterate over the names in the type's _anonymous_ attribute, if present,
260n/a */
261n/astatic int
262n/aMakeAnonFields(PyObject *type)
263n/a{
264n/a PyObject *anon;
265n/a PyObject *anon_names;
266n/a Py_ssize_t i;
267n/a
268n/a anon = PyObject_GetAttrString(type, "_anonymous_");
269n/a if (anon == NULL) {
270n/a PyErr_Clear();
271n/a return 0;
272n/a }
273n/a anon_names = PySequence_Fast(anon, "_anonymous_ must be a sequence");
274n/a Py_DECREF(anon);
275n/a if (anon_names == NULL)
276n/a return -1;
277n/a
278n/a for (i = 0; i < PySequence_Fast_GET_SIZE(anon_names); ++i) {
279n/a PyObject *fname = PySequence_Fast_GET_ITEM(anon_names, i); /* borrowed */
280n/a CFieldObject *descr = (CFieldObject *)PyObject_GetAttr(type, fname);
281n/a if (descr == NULL) {
282n/a Py_DECREF(anon_names);
283n/a return -1;
284n/a }
285n/a assert(Py_TYPE(descr) == &PyCField_Type);
286n/a descr->anonymous = 1;
287n/a
288n/a /* descr is in the field descriptor. */
289n/a if (-1 == MakeFields(type, (CFieldObject *)descr,
290n/a ((CFieldObject *)descr)->index,
291n/a ((CFieldObject *)descr)->offset)) {
292n/a Py_DECREF(descr);
293n/a Py_DECREF(anon_names);
294n/a return -1;
295n/a }
296n/a Py_DECREF(descr);
297n/a }
298n/a
299n/a Py_DECREF(anon_names);
300n/a return 0;
301n/a}
302n/a
303n/a/*
304n/a Retrive the (optional) _pack_ attribute from a type, the _fields_ attribute,
305n/a and create an StgDictObject. Used for Structure and Union subclasses.
306n/a*/
307n/aint
308n/aPyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct)
309n/a{
310n/a StgDictObject *stgdict, *basedict;
311n/a Py_ssize_t len, offset, size, align, i;
312n/a Py_ssize_t union_size, total_align;
313n/a Py_ssize_t field_size = 0;
314n/a int bitofs;
315n/a PyObject *isPacked;
316n/a int pack = 0;
317n/a Py_ssize_t ffi_ofs;
318n/a int big_endian;
319n/a
320n/a /* HACK Alert: I cannot be bothered to fix ctypes.com, so there has to
321n/a be a way to use the old, broken sematics: _fields_ are not extended
322n/a but replaced in subclasses.
323n/a
324n/a XXX Remove this in ctypes 1.0!
325n/a */
326n/a int use_broken_old_ctypes_semantics;
327n/a
328n/a if (fields == NULL)
329n/a return 0;
330n/a
331n/a#ifdef WORDS_BIGENDIAN
332n/a big_endian = PyObject_HasAttrString(type, "_swappedbytes_") ? 0 : 1;
333n/a#else
334n/a big_endian = PyObject_HasAttrString(type, "_swappedbytes_") ? 1 : 0;
335n/a#endif
336n/a
337n/a use_broken_old_ctypes_semantics = \
338n/a PyObject_HasAttrString(type, "_use_broken_old_ctypes_structure_semantics_");
339n/a
340n/a isPacked = PyObject_GetAttrString(type, "_pack_");
341n/a if (isPacked) {
342n/a pack = _PyLong_AsInt(isPacked);
343n/a if (pack < 0 || PyErr_Occurred()) {
344n/a Py_XDECREF(isPacked);
345n/a PyErr_SetString(PyExc_ValueError,
346n/a "_pack_ must be a non-negative integer");
347n/a return -1;
348n/a }
349n/a Py_DECREF(isPacked);
350n/a } else
351n/a PyErr_Clear();
352n/a
353n/a len = PySequence_Length(fields);
354n/a if (len == -1) {
355n/a PyErr_SetString(PyExc_TypeError,
356n/a "'_fields_' must be a sequence of pairs");
357n/a return -1;
358n/a }
359n/a
360n/a stgdict = PyType_stgdict(type);
361n/a if (!stgdict)
362n/a return -1;
363n/a /* If this structure/union is already marked final we cannot assign
364n/a _fields_ anymore. */
365n/a
366n/a if (stgdict->flags & DICTFLAG_FINAL) {/* is final ? */
367n/a PyErr_SetString(PyExc_AttributeError,
368n/a "_fields_ is final");
369n/a return -1;
370n/a }
371n/a
372n/a if (stgdict->format) {
373n/a PyMem_Free(stgdict->format);
374n/a stgdict->format = NULL;
375n/a }
376n/a
377n/a if (stgdict->ffi_type_pointer.elements)
378n/a PyMem_Free(stgdict->ffi_type_pointer.elements);
379n/a
380n/a basedict = PyType_stgdict((PyObject *)((PyTypeObject *)type)->tp_base);
381n/a if (basedict && !use_broken_old_ctypes_semantics) {
382n/a size = offset = basedict->size;
383n/a align = basedict->align;
384n/a union_size = 0;
385n/a total_align = align ? align : 1;
386n/a stgdict->ffi_type_pointer.type = FFI_TYPE_STRUCT;
387n/a stgdict->ffi_type_pointer.elements = PyMem_New(ffi_type *, basedict->length + len + 1);
388n/a if (stgdict->ffi_type_pointer.elements == NULL) {
389n/a PyErr_NoMemory();
390n/a return -1;
391n/a }
392n/a memset(stgdict->ffi_type_pointer.elements, 0,
393n/a sizeof(ffi_type *) * (basedict->length + len + 1));
394n/a if (basedict->length > 0) {
395n/a memcpy(stgdict->ffi_type_pointer.elements,
396n/a basedict->ffi_type_pointer.elements,
397n/a sizeof(ffi_type *) * (basedict->length));
398n/a }
399n/a ffi_ofs = basedict->length;
400n/a } else {
401n/a offset = 0;
402n/a size = 0;
403n/a align = 0;
404n/a union_size = 0;
405n/a total_align = 1;
406n/a stgdict->ffi_type_pointer.type = FFI_TYPE_STRUCT;
407n/a stgdict->ffi_type_pointer.elements = PyMem_New(ffi_type *, len + 1);
408n/a if (stgdict->ffi_type_pointer.elements == NULL) {
409n/a PyErr_NoMemory();
410n/a return -1;
411n/a }
412n/a memset(stgdict->ffi_type_pointer.elements, 0,
413n/a sizeof(ffi_type *) * (len + 1));
414n/a ffi_ofs = 0;
415n/a }
416n/a
417n/a assert(stgdict->format == NULL);
418n/a if (isStruct && !isPacked) {
419n/a stgdict->format = _ctypes_alloc_format_string(NULL, "T{");
420n/a } else {
421n/a /* PEP3118 doesn't support union, or packed structures (well,
422n/a only standard packing, but we dont support the pep for
423n/a that). Use 'B' for bytes. */
424n/a stgdict->format = _ctypes_alloc_format_string(NULL, "B");
425n/a }
426n/a if (stgdict->format == NULL)
427n/a return -1;
428n/a
429n/a#define realdict ((PyObject *)&stgdict->dict)
430n/a for (i = 0; i < len; ++i) {
431n/a PyObject *name = NULL, *desc = NULL;
432n/a PyObject *pair = PySequence_GetItem(fields, i);
433n/a PyObject *prop;
434n/a StgDictObject *dict;
435n/a int bitsize = 0;
436n/a
437n/a if (!pair || !PyArg_ParseTuple(pair, "UO|i", &name, &desc, &bitsize)) {
438n/a PyErr_SetString(PyExc_TypeError,
439n/a "'_fields_' must be a sequence of (name, C type) pairs");
440n/a Py_XDECREF(pair);
441n/a return -1;
442n/a }
443n/a dict = PyType_stgdict(desc);
444n/a if (dict == NULL) {
445n/a Py_DECREF(pair);
446n/a PyErr_Format(PyExc_TypeError,
447n/a "second item in _fields_ tuple (index %zd) must be a C type",
448n/a i);
449n/a return -1;
450n/a }
451n/a stgdict->ffi_type_pointer.elements[ffi_ofs + i] = &dict->ffi_type_pointer;
452n/a if (dict->flags & (TYPEFLAG_ISPOINTER | TYPEFLAG_HASPOINTER))
453n/a stgdict->flags |= TYPEFLAG_HASPOINTER;
454n/a dict->flags |= DICTFLAG_FINAL; /* mark field type final */
455n/a if (PyTuple_Size(pair) == 3) { /* bits specified */
456n/a switch(dict->ffi_type_pointer.type) {
457n/a case FFI_TYPE_UINT8:
458n/a case FFI_TYPE_UINT16:
459n/a case FFI_TYPE_UINT32:
460n/a case FFI_TYPE_SINT64:
461n/a case FFI_TYPE_UINT64:
462n/a break;
463n/a
464n/a case FFI_TYPE_SINT8:
465n/a case FFI_TYPE_SINT16:
466n/a case FFI_TYPE_SINT32:
467n/a if (dict->getfunc != _ctypes_get_fielddesc("c")->getfunc
468n/a#ifdef CTYPES_UNICODE
469n/a && dict->getfunc != _ctypes_get_fielddesc("u")->getfunc
470n/a#endif
471n/a )
472n/a break;
473n/a /* else fall through */
474n/a default:
475n/a PyErr_Format(PyExc_TypeError,
476n/a "bit fields not allowed for type %s",
477n/a ((PyTypeObject *)desc)->tp_name);
478n/a Py_DECREF(pair);
479n/a return -1;
480n/a }
481n/a if (bitsize <= 0 || bitsize > dict->size * 8) {
482n/a PyErr_SetString(PyExc_ValueError,
483n/a "number of bits invalid for bit field");
484n/a Py_DECREF(pair);
485n/a return -1;
486n/a }
487n/a } else
488n/a bitsize = 0;
489n/a
490n/a if (isStruct && !isPacked) {
491n/a const char *fieldfmt = dict->format ? dict->format : "B";
492n/a const char *fieldname = PyUnicode_AsUTF8(name);
493n/a char *ptr;
494n/a Py_ssize_t len;
495n/a char *buf;
496n/a
497n/a if (fieldname == NULL)
498n/a {
499n/a Py_DECREF(pair);
500n/a return -1;
501n/a }
502n/a
503n/a len = strlen(fieldname) + strlen(fieldfmt);
504n/a
505n/a buf = PyMem_Malloc(len + 2 + 1);
506n/a if (buf == NULL) {
507n/a Py_DECREF(pair);
508n/a PyErr_NoMemory();
509n/a return -1;
510n/a }
511n/a sprintf(buf, "%s:%s:", fieldfmt, fieldname);
512n/a
513n/a ptr = stgdict->format;
514n/a if (dict->shape != NULL) {
515n/a stgdict->format = _ctypes_alloc_format_string_with_shape(
516n/a dict->ndim, dict->shape, stgdict->format, buf);
517n/a } else {
518n/a stgdict->format = _ctypes_alloc_format_string(stgdict->format, buf);
519n/a }
520n/a PyMem_Free(ptr);
521n/a PyMem_Free(buf);
522n/a
523n/a if (stgdict->format == NULL) {
524n/a Py_DECREF(pair);
525n/a return -1;
526n/a }
527n/a }
528n/a
529n/a if (isStruct) {
530n/a prop = PyCField_FromDesc(desc, i,
531n/a &field_size, bitsize, &bitofs,
532n/a &size, &offset, &align,
533n/a pack, big_endian);
534n/a } else /* union */ {
535n/a size = 0;
536n/a offset = 0;
537n/a align = 0;
538n/a prop = PyCField_FromDesc(desc, i,
539n/a &field_size, bitsize, &bitofs,
540n/a &size, &offset, &align,
541n/a pack, big_endian);
542n/a union_size = max(size, union_size);
543n/a }
544n/a total_align = max(align, total_align);
545n/a
546n/a if (!prop) {
547n/a Py_DECREF(pair);
548n/a return -1;
549n/a }
550n/a if (-1 == PyObject_SetAttr(type, name, prop)) {
551n/a Py_DECREF(prop);
552n/a Py_DECREF(pair);
553n/a return -1;
554n/a }
555n/a Py_DECREF(pair);
556n/a Py_DECREF(prop);
557n/a }
558n/a#undef realdict
559n/a
560n/a if (isStruct && !isPacked) {
561n/a char *ptr = stgdict->format;
562n/a stgdict->format = _ctypes_alloc_format_string(stgdict->format, "}");
563n/a PyMem_Free(ptr);
564n/a if (stgdict->format == NULL)
565n/a return -1;
566n/a }
567n/a
568n/a if (!isStruct)
569n/a size = union_size;
570n/a
571n/a /* Adjust the size according to the alignment requirements */
572n/a size = ((size + total_align - 1) / total_align) * total_align;
573n/a
574n/a stgdict->ffi_type_pointer.alignment = Py_SAFE_DOWNCAST(total_align,
575n/a Py_ssize_t,
576n/a unsigned short);
577n/a stgdict->ffi_type_pointer.size = size;
578n/a
579n/a stgdict->size = size;
580n/a stgdict->align = total_align;
581n/a stgdict->length = len; /* ADD ffi_ofs? */
582n/a
583n/a /* We did check that this flag was NOT set above, it must not
584n/a have been set until now. */
585n/a if (stgdict->flags & DICTFLAG_FINAL) {
586n/a PyErr_SetString(PyExc_AttributeError,
587n/a "Structure or union cannot contain itself");
588n/a return -1;
589n/a }
590n/a stgdict->flags |= DICTFLAG_FINAL;
591n/a
592n/a return MakeAnonFields(type);
593n/a}