blob: 716d1e9e8eb5df76d10078afff02072e9ecd71db [file] [log] [blame]
Thomas Hellerd4c93202006-03-08 19:35:11 +00001#include "Python.h"
2#include <ffi.h>
3#ifdef MS_WIN32
4#include <windows.h>
Thomas Hellerb041fda2008-04-30 17:11:46 +00005#include <malloc.h>
Thomas Hellerd4c93202006-03-08 19:35:11 +00006#endif
7#include "ctypes.h"
8
9/******************************************************************/
10/*
11 StdDict - a dictionary subclass, containing additional C accessible fields
12
13 XXX blabla more
14*/
15
16/* Seems we need this, otherwise we get problems when calling
17 * PyDict_SetItem() (ma_lookup is NULL)
18 */
19static int
Thomas Heller34596a92009-04-24 20:50:00 +000020PyCStgDict_init(StgDictObject *self, PyObject *args, PyObject *kwds)
Thomas Hellerd4c93202006-03-08 19:35:11 +000021{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000022 if (PyDict_Type.tp_init((PyObject *)self, args, kwds) < 0)
23 return -1;
24 self->format = NULL;
25 self->ndim = 0;
26 self->shape = NULL;
27 return 0;
Thomas Hellerd4c93202006-03-08 19:35:11 +000028}
29
30static int
Thomas Heller34596a92009-04-24 20:50:00 +000031PyCStgDict_clear(StgDictObject *self)
Thomas Hellerd4c93202006-03-08 19:35:11 +000032{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000033 Py_CLEAR(self->proto);
34 Py_CLEAR(self->argtypes);
35 Py_CLEAR(self->converters);
36 Py_CLEAR(self->restype);
37 Py_CLEAR(self->checker);
38 return 0;
Thomas Hellerd4c93202006-03-08 19:35:11 +000039}
40
41static void
Thomas Heller34596a92009-04-24 20:50:00 +000042PyCStgDict_dealloc(StgDictObject *self)
Thomas Hellerd4c93202006-03-08 19:35:11 +000043{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000044 PyCStgDict_clear(self);
45 PyMem_Free(self->format);
46 PyMem_Free(self->shape);
47 PyMem_Free(self->ffi_type_pointer.elements);
48 PyDict_Type.tp_dealloc((PyObject *)self);
Thomas Hellerd4c93202006-03-08 19:35:11 +000049}
50
51int
Thomas Heller34596a92009-04-24 20:50:00 +000052PyCStgDict_clone(StgDictObject *dst, StgDictObject *src)
Thomas Hellerd4c93202006-03-08 19:35:11 +000053{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000054 char *d, *s;
55 Py_ssize_t size;
Thomas Hellerd4c93202006-03-08 19:35:11 +000056
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000057 PyCStgDict_clear(dst);
58 PyMem_Free(dst->ffi_type_pointer.elements);
59 PyMem_Free(dst->format);
60 dst->format = NULL;
61 PyMem_Free(dst->shape);
62 dst->shape = NULL;
63 dst->ffi_type_pointer.elements = NULL;
Thomas Hellerd4c93202006-03-08 19:35:11 +000064
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000065 d = (char *)dst;
66 s = (char *)src;
67 memcpy(d + sizeof(PyDictObject),
68 s + sizeof(PyDictObject),
69 sizeof(StgDictObject) - sizeof(PyDictObject));
Thomas Hellerd4c93202006-03-08 19:35:11 +000070
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000071 Py_XINCREF(dst->proto);
72 Py_XINCREF(dst->argtypes);
73 Py_XINCREF(dst->converters);
74 Py_XINCREF(dst->restype);
75 Py_XINCREF(dst->checker);
Thomas Hellerd4c93202006-03-08 19:35:11 +000076
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000077 if (src->format) {
78 dst->format = PyMem_Malloc(strlen(src->format) + 1);
Serhiy Storchaka1a1ff292015-02-16 13:28:22 +020079 if (dst->format == NULL) {
80 PyErr_NoMemory();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000081 return -1;
Serhiy Storchaka1a1ff292015-02-16 13:28:22 +020082 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000083 strcpy(dst->format, src->format);
84 }
85 if (src->shape) {
86 dst->shape = PyMem_Malloc(sizeof(Py_ssize_t) * src->ndim);
Serhiy Storchaka1a1ff292015-02-16 13:28:22 +020087 if (dst->shape == NULL) {
88 PyErr_NoMemory();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000089 return -1;
Serhiy Storchaka1a1ff292015-02-16 13:28:22 +020090 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000091 memcpy(dst->shape, src->shape,
92 sizeof(Py_ssize_t) * src->ndim);
93 }
Thomas Hellerb041fda2008-04-30 17:11:46 +000094
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000095 if (src->ffi_type_pointer.elements == NULL)
96 return 0;
97 size = sizeof(ffi_type *) * (src->length + 1);
98 dst->ffi_type_pointer.elements = PyMem_Malloc(size);
99 if (dst->ffi_type_pointer.elements == NULL) {
100 PyErr_NoMemory();
101 return -1;
102 }
103 memcpy(dst->ffi_type_pointer.elements,
104 src->ffi_type_pointer.elements,
105 size);
106 return 0;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000107}
108
Thomas Heller34596a92009-04-24 20:50:00 +0000109PyTypeObject PyCStgDict_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000110 PyVarObject_HEAD_INIT(NULL, 0)
111 "StgDict",
112 sizeof(StgDictObject),
113 0,
114 (destructor)PyCStgDict_dealloc, /* tp_dealloc */
115 0, /* tp_print */
116 0, /* tp_getattr */
117 0, /* tp_setattr */
118 0, /* tp_reserved */
119 0, /* tp_repr */
120 0, /* tp_as_number */
121 0, /* tp_as_sequence */
122 0, /* tp_as_mapping */
123 0, /* tp_hash */
124 0, /* tp_call */
125 0, /* tp_str */
126 0, /* tp_getattro */
127 0, /* tp_setattro */
128 0, /* tp_as_buffer */
129 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
130 0, /* tp_doc */
131 0, /* tp_traverse */
132 0, /* tp_clear */
133 0, /* tp_richcompare */
134 0, /* tp_weaklistoffset */
135 0, /* tp_iter */
136 0, /* tp_iternext */
137 0, /* tp_methods */
138 0, /* tp_members */
139 0, /* tp_getset */
140 0, /* tp_base */
141 0, /* tp_dict */
142 0, /* tp_descr_get */
143 0, /* tp_descr_set */
144 0, /* tp_dictoffset */
145 (initproc)PyCStgDict_init, /* tp_init */
146 0, /* tp_alloc */
147 0, /* tp_new */
148 0, /* tp_free */
Thomas Hellerd4c93202006-03-08 19:35:11 +0000149};
150
151/* May return NULL, but does not set an exception! */
152StgDictObject *
153PyType_stgdict(PyObject *obj)
154{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000155 PyTypeObject *type;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000156
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000157 if (!PyType_Check(obj))
158 return NULL;
159 type = (PyTypeObject *)obj;
160 if (!type->tp_dict || !PyCStgDict_CheckExact(type->tp_dict))
161 return NULL;
162 return (StgDictObject *)type->tp_dict;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000163}
164
165/* May return NULL, but does not set an exception! */
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000166/*
167 This function should be as fast as possible, so we don't call PyType_stgdict
168 above but inline the code, and avoid the PyType_Check().
169*/
Thomas Hellerd4c93202006-03-08 19:35:11 +0000170StgDictObject *
171PyObject_stgdict(PyObject *self)
172{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000173 PyTypeObject *type = self->ob_type;
174 if (!type->tp_dict || !PyCStgDict_CheckExact(type->tp_dict))
175 return NULL;
176 return (StgDictObject *)type->tp_dict;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000177}
178
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000179/* descr is the descriptor for a field marked as anonymous. Get all the
180 _fields_ descriptors from descr->proto, create new descriptors with offset
181 and index adjusted, and stuff them into type.
182 */
183static int
184MakeFields(PyObject *type, CFieldObject *descr,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000185 Py_ssize_t index, Py_ssize_t offset)
Thomas Hellerd4c93202006-03-08 19:35:11 +0000186{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000187 Py_ssize_t i;
188 PyObject *fields;
189 PyObject *fieldlist;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000190
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000191 fields = PyObject_GetAttrString(descr->proto, "_fields_");
192 if (fields == NULL)
193 return -1;
194 fieldlist = PySequence_Fast(fields, "_fields_ must be a sequence");
195 Py_DECREF(fields);
196 if (fieldlist == NULL)
197 return -1;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000198
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000199 for (i = 0; i < PySequence_Fast_GET_SIZE(fieldlist); ++i) {
200 PyObject *pair = PySequence_Fast_GET_ITEM(fieldlist, i); /* borrowed */
201 PyObject *fname, *ftype, *bits;
202 CFieldObject *fdescr;
203 CFieldObject *new_descr;
204 /* Convert to PyArg_UnpackTuple... */
205 if (!PyArg_ParseTuple(pair, "OO|O", &fname, &ftype, &bits)) {
206 Py_DECREF(fieldlist);
207 return -1;
208 }
209 fdescr = (CFieldObject *)PyObject_GetAttr(descr->proto, fname);
210 if (fdescr == NULL) {
211 Py_DECREF(fieldlist);
212 return -1;
213 }
214 if (Py_TYPE(fdescr) != &PyCField_Type) {
215 PyErr_SetString(PyExc_TypeError, "unexpected type");
216 Py_DECREF(fdescr);
217 Py_DECREF(fieldlist);
218 return -1;
219 }
220 if (fdescr->anonymous) {
221 int rc = MakeFields(type, fdescr,
222 index + fdescr->index,
223 offset + fdescr->offset);
224 Py_DECREF(fdescr);
225 if (rc == -1) {
226 Py_DECREF(fieldlist);
227 return -1;
228 }
229 continue;
230 }
231 new_descr = (CFieldObject *)PyObject_CallObject((PyObject *)&PyCField_Type, NULL);
232 if (new_descr == NULL) {
233 Py_DECREF(fdescr);
234 Py_DECREF(fieldlist);
235 return -1;
236 }
237 assert(Py_TYPE(new_descr) == &PyCField_Type);
238 new_descr->size = fdescr->size;
239 new_descr->offset = fdescr->offset + offset;
240 new_descr->index = fdescr->index + index;
241 new_descr->proto = fdescr->proto;
242 Py_XINCREF(new_descr->proto);
243 new_descr->getfunc = fdescr->getfunc;
244 new_descr->setfunc = fdescr->setfunc;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000245
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000246 Py_DECREF(fdescr);
247
248 if (-1 == PyObject_SetAttr(type, fname, (PyObject *)new_descr)) {
249 Py_DECREF(fieldlist);
250 Py_DECREF(new_descr);
251 return -1;
252 }
253 Py_DECREF(new_descr);
254 }
255 Py_DECREF(fieldlist);
256 return 0;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000257}
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000258
259/* Iterate over the names in the type's _anonymous_ attribute, if present,
260 */
261static int
262MakeAnonFields(PyObject *type)
263{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000264 PyObject *anon;
265 PyObject *anon_names;
266 Py_ssize_t i;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000267
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000268 anon = PyObject_GetAttrString(type, "_anonymous_");
269 if (anon == NULL) {
270 PyErr_Clear();
271 return 0;
272 }
273 anon_names = PySequence_Fast(anon, "_anonymous_ must be a sequence");
274 Py_DECREF(anon);
275 if (anon_names == NULL)
276 return -1;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000277
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000278 for (i = 0; i < PySequence_Fast_GET_SIZE(anon_names); ++i) {
279 PyObject *fname = PySequence_Fast_GET_ITEM(anon_names, i); /* borrowed */
280 CFieldObject *descr = (CFieldObject *)PyObject_GetAttr(type, fname);
281 if (descr == NULL) {
282 Py_DECREF(anon_names);
283 return -1;
284 }
285 assert(Py_TYPE(descr) == &PyCField_Type);
286 descr->anonymous = 1;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000287
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000288 /* descr is in the field descriptor. */
289 if (-1 == MakeFields(type, (CFieldObject *)descr,
290 ((CFieldObject *)descr)->index,
291 ((CFieldObject *)descr)->offset)) {
292 Py_DECREF(descr);
293 Py_DECREF(anon_names);
294 return -1;
295 }
296 Py_DECREF(descr);
297 }
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000298
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000299 Py_DECREF(anon_names);
300 return 0;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000301}
Thomas Hellerd4c93202006-03-08 19:35:11 +0000302
303/*
304 Retrive the (optional) _pack_ attribute from a type, the _fields_ attribute,
305 and create an StgDictObject. Used for Structure and Union subclasses.
306*/
307int
Thomas Heller34596a92009-04-24 20:50:00 +0000308PyCStructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct)
Thomas Hellerd4c93202006-03-08 19:35:11 +0000309{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000310 StgDictObject *stgdict, *basedict;
311 Py_ssize_t len, offset, size, align, i;
312 Py_ssize_t union_size, total_align;
313 Py_ssize_t field_size = 0;
314 int bitofs;
315 PyObject *isPacked;
316 int pack = 0;
317 Py_ssize_t ffi_ofs;
318 int big_endian;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000319
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000320 /* HACK Alert: I cannot be bothered to fix ctypes.com, so there has to
321 be a way to use the old, broken sematics: _fields_ are not extended
322 but replaced in subclasses.
Thomas Hellerd4c93202006-03-08 19:35:11 +0000323
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000324 XXX Remove this in ctypes 1.0!
325 */
326 int use_broken_old_ctypes_semantics;
327
328 if (fields == NULL)
329 return 0;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000330
331#ifdef WORDS_BIGENDIAN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000332 big_endian = PyObject_HasAttrString(type, "_swappedbytes_") ? 0 : 1;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000333#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000334 big_endian = PyObject_HasAttrString(type, "_swappedbytes_") ? 1 : 0;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000335#endif
336
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000337 use_broken_old_ctypes_semantics = \
338 PyObject_HasAttrString(type, "_use_broken_old_ctypes_structure_semantics_");
Thomas Hellerd4c93202006-03-08 19:35:11 +0000339
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000340 isPacked = PyObject_GetAttrString(type, "_pack_");
341 if (isPacked) {
Serhiy Storchaka78980432013-01-15 01:12:17 +0200342 pack = _PyLong_AsInt(isPacked);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000343 if (pack < 0 || PyErr_Occurred()) {
344 Py_XDECREF(isPacked);
345 PyErr_SetString(PyExc_ValueError,
346 "_pack_ must be a non-negative integer");
347 return -1;
348 }
349 Py_DECREF(isPacked);
350 } else
351 PyErr_Clear();
Thomas Hellerd4c93202006-03-08 19:35:11 +0000352
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000353 len = PySequence_Length(fields);
354 if (len == -1) {
355 PyErr_SetString(PyExc_TypeError,
356 "'_fields_' must be a sequence of pairs");
357 return -1;
358 }
Thomas Hellerd4c93202006-03-08 19:35:11 +0000359
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000360 stgdict = PyType_stgdict(type);
361 if (!stgdict)
362 return -1;
363 /* If this structure/union is already marked final we cannot assign
364 _fields_ anymore. */
Thomas Wouters89f507f2006-12-13 04:49:30 +0000365
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000366 if (stgdict->flags & DICTFLAG_FINAL) {/* is final ? */
367 PyErr_SetString(PyExc_AttributeError,
368 "_fields_ is final");
369 return -1;
370 }
Thomas Hellerd4c93202006-03-08 19:35:11 +0000371
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000372 if (stgdict->format) {
373 PyMem_Free(stgdict->format);
374 stgdict->format = NULL;
375 }
Thomas Hellerb041fda2008-04-30 17:11:46 +0000376
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000377 if (stgdict->ffi_type_pointer.elements)
378 PyMem_Free(stgdict->ffi_type_pointer.elements);
Thomas Hellerd4c93202006-03-08 19:35:11 +0000379
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000380 basedict = PyType_stgdict((PyObject *)((PyTypeObject *)type)->tp_base);
381 if (basedict && !use_broken_old_ctypes_semantics) {
382 size = offset = basedict->size;
383 align = basedict->align;
384 union_size = 0;
385 total_align = align ? align : 1;
386 stgdict->ffi_type_pointer.type = FFI_TYPE_STRUCT;
Serhiy Storchaka1a1ff292015-02-16 13:28:22 +0200387 stgdict->ffi_type_pointer.elements = PyMem_New(ffi_type *, basedict->length + len + 1);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000388 if (stgdict->ffi_type_pointer.elements == NULL) {
389 PyErr_NoMemory();
390 return -1;
391 }
392 memset(stgdict->ffi_type_pointer.elements, 0,
393 sizeof(ffi_type *) * (basedict->length + len + 1));
Martin Panterbe8da9c2016-09-07 11:04:41 +0000394 if (basedict->length > 0) {
395 memcpy(stgdict->ffi_type_pointer.elements,
396 basedict->ffi_type_pointer.elements,
397 sizeof(ffi_type *) * (basedict->length));
398 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000399 ffi_ofs = basedict->length;
400 } else {
401 offset = 0;
402 size = 0;
403 align = 0;
404 union_size = 0;
405 total_align = 1;
406 stgdict->ffi_type_pointer.type = FFI_TYPE_STRUCT;
Serhiy Storchaka1a1ff292015-02-16 13:28:22 +0200407 stgdict->ffi_type_pointer.elements = PyMem_New(ffi_type *, len + 1);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000408 if (stgdict->ffi_type_pointer.elements == NULL) {
409 PyErr_NoMemory();
410 return -1;
411 }
412 memset(stgdict->ffi_type_pointer.elements, 0,
413 sizeof(ffi_type *) * (len + 1));
414 ffi_ofs = 0;
415 }
Thomas Hellerd4c93202006-03-08 19:35:11 +0000416
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000417 assert(stgdict->format == NULL);
418 if (isStruct && !isPacked) {
419 stgdict->format = _ctypes_alloc_format_string(NULL, "T{");
420 } else {
421 /* PEP3118 doesn't support union, or packed structures (well,
422 only standard packing, but we dont support the pep for
423 that). Use 'B' for bytes. */
424 stgdict->format = _ctypes_alloc_format_string(NULL, "B");
425 }
Victor Stinnerdd371b92013-10-29 03:50:45 +0100426 if (stgdict->format == NULL)
427 return -1;
Thomas Hellerb041fda2008-04-30 17:11:46 +0000428
Thomas Hellerd4c93202006-03-08 19:35:11 +0000429#define realdict ((PyObject *)&stgdict->dict)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000430 for (i = 0; i < len; ++i) {
431 PyObject *name = NULL, *desc = NULL;
432 PyObject *pair = PySequence_GetItem(fields, i);
433 PyObject *prop;
434 StgDictObject *dict;
435 int bitsize = 0;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000436
Amaury Forgeot d'Arc842d9212011-09-02 23:07:54 +0200437 if (!pair || !PyArg_ParseTuple(pair, "UO|i", &name, &desc, &bitsize)) {
438 PyErr_SetString(PyExc_TypeError,
439 "'_fields_' must be a sequence of (name, C type) pairs");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000440 Py_XDECREF(pair);
441 return -1;
442 }
443 dict = PyType_stgdict(desc);
444 if (dict == NULL) {
445 Py_DECREF(pair);
446 PyErr_Format(PyExc_TypeError,
447 "second item in _fields_ tuple (index %zd) must be a C type",
448 i);
449 return -1;
450 }
451 stgdict->ffi_type_pointer.elements[ffi_ofs + i] = &dict->ffi_type_pointer;
452 if (dict->flags & (TYPEFLAG_ISPOINTER | TYPEFLAG_HASPOINTER))
453 stgdict->flags |= TYPEFLAG_HASPOINTER;
454 dict->flags |= DICTFLAG_FINAL; /* mark field type final */
455 if (PyTuple_Size(pair) == 3) { /* bits specified */
456 switch(dict->ffi_type_pointer.type) {
457 case FFI_TYPE_UINT8:
458 case FFI_TYPE_UINT16:
459 case FFI_TYPE_UINT32:
460 case FFI_TYPE_SINT64:
461 case FFI_TYPE_UINT64:
462 break;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000463
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000464 case FFI_TYPE_SINT8:
465 case FFI_TYPE_SINT16:
466 case FFI_TYPE_SINT32:
467 if (dict->getfunc != _ctypes_get_fielddesc("c")->getfunc
Thomas Hellerd4c93202006-03-08 19:35:11 +0000468#ifdef CTYPES_UNICODE
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000469 && dict->getfunc != _ctypes_get_fielddesc("u")->getfunc
Thomas Hellerd4c93202006-03-08 19:35:11 +0000470#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000471 )
472 break;
473 /* else fall through */
474 default:
475 PyErr_Format(PyExc_TypeError,
476 "bit fields not allowed for type %s",
477 ((PyTypeObject *)desc)->tp_name);
478 Py_DECREF(pair);
479 return -1;
480 }
481 if (bitsize <= 0 || bitsize > dict->size * 8) {
482 PyErr_SetString(PyExc_ValueError,
483 "number of bits invalid for bit field");
484 Py_DECREF(pair);
485 return -1;
486 }
487 } else
488 bitsize = 0;
Amaury Forgeot d'Arc842d9212011-09-02 23:07:54 +0200489
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000490 if (isStruct && !isPacked) {
491 char *fieldfmt = dict->format ? dict->format : "B";
Serhiy Storchaka06515832016-11-20 09:13:07 +0200492 char *fieldname = PyUnicode_AsUTF8(name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000493 char *ptr;
Victor Stinnerdd371b92013-10-29 03:50:45 +0100494 Py_ssize_t len;
Amaury Forgeot d'Arc02dd5392011-09-02 20:39:40 +0200495 char *buf;
496
497 if (fieldname == NULL)
498 {
Amaury Forgeot d'Arc02dd5392011-09-02 20:39:40 +0200499 Py_DECREF(pair);
500 return -1;
501 }
502
503 len = strlen(fieldname) + strlen(fieldfmt);
Thomas Hellerb041fda2008-04-30 17:11:46 +0000504
Meador Inge1efb33a2011-10-03 21:44:22 -0500505 buf = PyMem_Malloc(len + 2 + 1);
506 if (buf == NULL) {
507 Py_DECREF(pair);
508 PyErr_NoMemory();
509 return -1;
510 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000511 sprintf(buf, "%s:%s:", fieldfmt, fieldname);
Thomas Hellerb041fda2008-04-30 17:11:46 +0000512
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000513 ptr = stgdict->format;
Benjamin Peterson5eb6b392014-05-17 14:59:12 -0700514 if (dict->shape != NULL) {
515 stgdict->format = _ctypes_alloc_format_string_with_shape(
516 dict->ndim, dict->shape, stgdict->format, buf);
517 } else {
518 stgdict->format = _ctypes_alloc_format_string(stgdict->format, buf);
519 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000520 PyMem_Free(ptr);
Meador Inge1efb33a2011-10-03 21:44:22 -0500521 PyMem_Free(buf);
Thomas Hellerb041fda2008-04-30 17:11:46 +0000522
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000523 if (stgdict->format == NULL) {
524 Py_DECREF(pair);
525 return -1;
526 }
527 }
Amaury Forgeot d'Arc842d9212011-09-02 23:07:54 +0200528
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000529 if (isStruct) {
530 prop = PyCField_FromDesc(desc, i,
531 &field_size, bitsize, &bitofs,
532 &size, &offset, &align,
533 pack, big_endian);
534 } else /* union */ {
535 size = 0;
536 offset = 0;
537 align = 0;
538 prop = PyCField_FromDesc(desc, i,
539 &field_size, bitsize, &bitofs,
540 &size, &offset, &align,
541 pack, big_endian);
542 union_size = max(size, union_size);
543 }
544 total_align = max(align, total_align);
Thomas Hellerd4c93202006-03-08 19:35:11 +0000545
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000546 if (!prop) {
547 Py_DECREF(pair);
548 return -1;
549 }
550 if (-1 == PyObject_SetAttr(type, name, prop)) {
551 Py_DECREF(prop);
552 Py_DECREF(pair);
553 return -1;
554 }
555 Py_DECREF(pair);
556 Py_DECREF(prop);
557 }
Thomas Hellerd4c93202006-03-08 19:35:11 +0000558#undef realdict
Thomas Hellerb041fda2008-04-30 17:11:46 +0000559
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000560 if (isStruct && !isPacked) {
561 char *ptr = stgdict->format;
562 stgdict->format = _ctypes_alloc_format_string(stgdict->format, "}");
563 PyMem_Free(ptr);
564 if (stgdict->format == NULL)
565 return -1;
566 }
Thomas Hellerb041fda2008-04-30 17:11:46 +0000567
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000568 if (!isStruct)
569 size = union_size;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000570
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000571 /* Adjust the size according to the alignment requirements */
572 size = ((size + total_align - 1) / total_align) * total_align;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000573
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000574 stgdict->ffi_type_pointer.alignment = Py_SAFE_DOWNCAST(total_align,
575 Py_ssize_t,
576 unsigned short);
577 stgdict->ffi_type_pointer.size = size;
Thomas Hellerd4c93202006-03-08 19:35:11 +0000578
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000579 stgdict->size = size;
580 stgdict->align = total_align;
581 stgdict->length = len; /* ADD ffi_ofs? */
Thomas Wouters89f507f2006-12-13 04:49:30 +0000582
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000583 /* We did check that this flag was NOT set above, it must not
584 have been set until now. */
585 if (stgdict->flags & DICTFLAG_FINAL) {
586 PyErr_SetString(PyExc_AttributeError,
587 "Structure or union cannot contain itself");
588 return -1;
589 }
590 stgdict->flags |= DICTFLAG_FINAL;
Thomas Wouters89f507f2006-12-13 04:49:30 +0000591
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000592 return MakeAnonFields(type);
Thomas Hellerd4c93202006-03-08 19:35:11 +0000593}