Commits

Armin Rigo committed 61cbe88

Good, we can now declare array fields without specifying the length,
and let verify() fill that in.

  • Participants
  • Parent commits a964b08
  • Branches cpy-extension

Comments (0)

Files changed (2)

         self.item = item
         self.length = length
 
+    def resolve_length(self, newlength):
+        return ArrayType(self.item, newlength)
+
     def get_c_name(self, replace_with=''):
         if self.length is None:
             brackets = '[]'
         if self.fixedlayout is None:
             lst = zip(self.fldnames, fldtypes, self.fldbitsize)
             ffi._backend.complete_struct_or_union(BType, lst, self)
+            #
         else:
             fieldofs, fieldsize, totalsize, totalalignment = self.fixedlayout
-            for fname, ftype, fsize in zip(self.fldnames, fldtypes, fieldsize):
-                if ffi.sizeof(ftype) != fsize:
-                    from .ffiplatform import VerificationError
-                    raise VerificationError, (
+            for i in range(len(self.fldnames)):
+                fsize = fieldsize[i]
+                ftype = self.fldtypes[i]
+                #
+                if isinstance(ftype, ArrayType) and ftype.length is None:
+                    # fix the length to match the total size
+                    BItemType = ffi._get_cached_btype(ftype.item)
+                    nlen, nrest = divmod(fsize, ffi.sizeof(BItemType))
+                    if nrest != 0:
+                        self._verification_error(
+                            "field '%s.%s' has a bogus size?" % (
+                            self.name, self.fldnames[i]))
+                    ftype = ftype.resolve_length(nlen)
+                    self.fldtypes = (self.fldtypes[:i] + (ftype,) +
+                                     self.fldtypes[i+1:])
+                    BArrayType = ffi._get_cached_btype(ftype)
+                    fldtypes = (fldtypes[:i] + (BArrayType,) +
+                                fldtypes[i+1:])
+                    continue
+                #
+                bitemsize = ffi.sizeof(fldtypes[i])
+                if bitemsize != fsize:
+                    self._verification_error(
                         "field '%s.%s' is declared as %d bytes, but is "
-                        "really %d bytes" % (self.name, fname,
-                                             ffi.sizeof(ftype), fsize))
+                        "really %d bytes" % (self.name, self.fldnames[i],
+                                             bitemsize, fsize))
             lst = zip(self.fldnames, fldtypes, self.fldbitsize, fieldofs)
             ffi._backend.complete_struct_or_union(BType, lst, self,
                                                   totalsize, totalalignment)
         return BType
 
+    def _verification_error(self, msg):
+        from .ffiplatform import VerificationError
+        raise VerificationError(msg)
+
 
 class StructType(StructOrUnion):
     kind = 'struct'

testing/test_verify.py

     assert ffi.sizeof(s.a) == 17 * ffi.sizeof('int')
 
 def test_struct_array_guess_length():
-    py.test.skip("in-progress")
     ffi = FFI()
-    ffi.cdef("struct foo_s { int a[]; ...; };")
+    ffi.cdef("struct foo_s { int a[]; ...; };")    # <= no declared length
     ffi.verify("struct foo_s { int x; int a[17]; int y; };")
     assert ffi.sizeof('struct foo_s') == 19 * ffi.sizeof('int')
     s = ffi.new("struct foo_s")