summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Leech <andrew@alelec.net>2016-09-14 16:56:26 +1000
committerAndrew Leech <andrew@alelec.net>2016-09-14 16:56:26 +1000
commit0a4dd37de202b944707893ae92f51a708b0080f4 (patch)
treeaf543f02482c94be66fdf06b51979e0e71fc978b
parent2e3754a50d9160847e92a688eb16f4da9cfbd3a5 (diff)
downloadcffi-0a4dd37de202b944707893ae92f51a708b0080f4.tar.gz
Detect and mark the final variable array in a varsized struct with BS_VARSIZESTRUCT_ARRAYcalculate_variable_array_length
Use this when returning this field/arrtibute of said struct
-rw-r--r--c/_cffi_backend.c17
-rw-r--r--c/test_c.py2
2 files changed, 11 insertions, 8 deletions
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
index f23ff04..209182f 100644
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -185,14 +185,15 @@ typedef struct cfieldobject_s {
PyObject_HEAD
CTypeDescrObject *cf_type;
Py_ssize_t cf_offset;
- short cf_bitshift; /* >= 0: bitshift; or BS_REGULAR or BS_EMPTY_ARRAY */
+ short cf_bitshift; /* >= 0: bitshift; or BS_REGULAR or BS_EMPTY_ARRAY or BS_VARSIZESTRUCT_ARRAY */
short cf_bitsize;
unsigned char cf_flags; /* BF_... */
struct cfieldobject_s *cf_next;
} CFieldObject;
-#define BS_REGULAR (-1) /* a regular field, not with bitshift */
-#define BS_EMPTY_ARRAY (-2) /* a field which is an array 'type[0]' */
-#define BF_IGNORE_IN_CTOR 0x01 /* union field not in the first place */
+#define BS_REGULAR (-1) /* a regular field, not with bitshift */
+#define BS_EMPTY_ARRAY (-2) /* a field which is an array 'type[0]' */
+#define BS_VARSIZESTRUCT_ARRAY (-3) /* a variable sized struct variable field 'type[]' */
+#define BF_IGNORE_IN_CTOR 0x01 /* union field not in the first place */
static PyTypeObject CTypeDescr_Type;
static PyTypeObject CField_Type;
@@ -2406,8 +2407,7 @@ cdata_getattro(CDataObject *cd, PyObject *attr)
char *data = cd->c_data + cf->cf_offset;
if ((cd->c_type->ct_flags & CT_IS_PTR_TO_OWNED) && // Is owned struct (or union)
- (cf->cf_type->ct_flags & CT_ARRAY) && // field is an array
- (cf->cf_type->ct_size == -1)) { // unknown length array
+ (cf->cf_bitshift == BS_VARSIZESTRUCT_ARRAY)) { // variable length array
/* if reading variable length array from variable length struct, calculate array type from allocated length*/
Py_ssize_t array_len = (((CDataObject_own_structptr *)cd)->length - ct->ct_size) / cf->cf_type->ct_itemdescr->ct_size;
return new_sized_cdata(data, cf->cf_type, array_len);
@@ -3227,6 +3227,7 @@ static PyObject *direct_newp(CTypeDescrObject *ct, PyObject *init,
}
/* store the only reference to cds into cd */
((CDataObject_own_structptr *)cd)->structobj = (PyObject *)cds;
+ /* store information about the allocated size of the struct */
((CDataObject_own_structptr *)cd)->length = datasize;
assert(explicitlength < 0);
@@ -4299,7 +4300,9 @@ static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args)
/* not a bitfield: common case */
int bs_flag;
- if (ftype->ct_flags & CT_ARRAY && ftype->ct_length == 0)
+ if (ftype->ct_flags & CT_ARRAY && ftype->ct_length == -1 && i == nb_fields - 1)
+ bs_flag = BS_VARSIZESTRUCT_ARRAY;
+ else if (ftype->ct_flags & CT_ARRAY && ftype->ct_length == 0)
bs_flag = BS_EMPTY_ARRAY;
else
bs_flag = BS_REGULAR;
diff --git a/c/test_c.py b/c/test_c.py
index 60fcf42..9ec83ff 100644
--- a/c/test_c.py
+++ b/c/test_c.py
@@ -3172,7 +3172,7 @@ def test_struct_array_no_length():
assert d[1][0] == 'y'
assert d[1][1].type is BArray
assert d[1][1].offset == size_of_int()
- assert d[1][1].bitshift == -1
+ assert d[1][1].bitshift == -3
assert d[1][1].bitsize == -1
#
p = newp(new_pointer_type(BStruct))