[pypy-commit] cffi calculate_variable_array_length: Detect and mark the final variable array in a varsized struct with BS_VARSIZESTRUCT_ARRAY

coronafire pypy.commits at gmail.com
Wed Oct 19 02:53:35 EDT 2016


Author: Andrew Leech <andrew at alelec.net>
Branch: calculate_variable_array_length
Changeset: r2791:3a9e42446693
Date: 2016-09-14 16:56 +1000
http://bitbucket.org/cffi/cffi/changeset/3a9e42446693/

Log:	Detect and mark the final variable array in a varsized struct with
	BS_VARSIZESTRUCT_ARRAY Use this when returning this field/arrtibute
	of said struct

diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -185,14 +185,15 @@
     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 @@
                 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 @@
         }
         /* 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 @@
             /* 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
--- a/c/test_c.py
+++ b/c/test_c.py
@@ -3172,7 +3172,7 @@
     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))


More information about the pypy-commit mailing list