Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r67887:d2503dcb595a Date: 2013-11-09 09:34 +0100 http://bitbucket.org/pypy/pypy/changeset/d2503dcb595a/
Log: Update to cffi/9ba268ca7739. In-progress. diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py --- a/pypy/module/_cffi_backend/cdataobj.py +++ b/pypy/module/_cffi_backend/cdataobj.py @@ -245,19 +245,22 @@ space = self.space if isinstance(w_other, W_CData): from pypy.module._cffi_backend import ctypeptr, ctypearray + from pypy.module._cffi_backend import ctypevoid ct = w_other.ctype if isinstance(ct, ctypearray.W_CTypeArray): ct = ct.ctptr # if (ct is not self.ctype or not isinstance(ct, ctypeptr.W_CTypePointer) or - ct.ctitem.size <= 0): + (ct.ctitem.size <= 0 and not ct.is_void_ptr)): raise operationerrfmt(space.w_TypeError, "cannot subtract cdata '%s' and cdata '%s'", self.ctype.name, ct.name) # + itemsize = ct.ctitem.size + if itemsize <= 0: itemsize = 1 diff = (rffi.cast(lltype.Signed, self._cdata) - - rffi.cast(lltype.Signed, w_other._cdata)) // ct.ctitem.size + rffi.cast(lltype.Signed, w_other._cdata)) // itemsize return space.wrap(diff) # return self._add_or_sub(w_other, -1) @@ -441,6 +444,7 @@ __getitem__ = interp2app(W_CData.getitem), __setitem__ = interp2app(W_CData.setitem), __add__ = interp2app(W_CData.add), + __radd__ = interp2app(W_CData.add), __sub__ = interp2app(W_CData.sub), __getattr__ = interp2app(W_CData.getattr), __setattr__ = interp2app(W_CData.setattr), diff --git a/pypy/module/_cffi_backend/ctypeptr.py b/pypy/module/_cffi_backend/ctypeptr.py --- a/pypy/module/_cffi_backend/ctypeptr.py +++ b/pypy/module/_cffi_backend/ctypeptr.py @@ -236,11 +236,15 @@ def add(self, cdata, i): space = self.space ctitem = self.ctitem + itemsize = ctitem.size if ctitem.size < 0: - raise operationerrfmt(space.w_TypeError, + if self.is_void_ptr: + itemsize = 1 + else: + raise operationerrfmt(space.w_TypeError, "ctype '%s' points to items of unknown size", self.name) - p = rffi.ptradd(cdata, i * self.ctitem.size) + p = rffi.ptradd(cdata, i * itemsize) return cdataobj.W_CData(space, p, self) def cast(self, w_ob): diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py --- a/pypy/module/_cffi_backend/test/_backend_test_c.py +++ b/pypy/module/_cffi_backend/test/_backend_test_c.py @@ -542,6 +542,7 @@ assert repr(a) == "<cdata 'int[3][5]' owning %d bytes>" % ( 3*5*size_of_int(),) assert repr(a + 0).startswith("<cdata 'int(*)[5]' 0x") + assert 0 + a == a + 0 != 1 + a == a + 1 assert repr(a[0]).startswith("<cdata 'int[5]' 0x") assert repr((a + 0)[0]).startswith("<cdata 'int[5]' 0x") assert repr(a[0] + 0).startswith("<cdata 'int *' 0x") @@ -1631,9 +1632,6 @@ def test_void_errors(): py.test.raises(ValueError, alignof, new_void_type()) py.test.raises(TypeError, newp, new_pointer_type(new_void_type()), None) - x = cast(new_pointer_type(new_void_type()), 42) - py.test.raises(TypeError, "x + 1") - py.test.raises(TypeError, "x - 1") def test_too_many_items(): BChar = new_primitive_type("char") @@ -2952,6 +2950,166 @@ _test_bitfield_details(flag=4) +def test_struct_array_no_length(): + BInt = new_primitive_type("int") + BIntP = new_pointer_type(BInt) + BArray = new_array_type(BIntP, None) + BStruct = new_struct_type("foo") + py.test.raises(TypeError, complete_struct_or_union, + BStruct, [('x', BArray), + ('y', BInt)]) + # + BStruct = new_struct_type("foo") + complete_struct_or_union(BStruct, [('x', BInt), + ('y', BArray)]) + assert sizeof(BStruct) == size_of_int() + d = BStruct.fields + assert len(d) == 2 + assert d[0][0] == 'x' + assert d[0][1].type is BInt + assert d[0][1].offset == 0 + assert d[0][1].bitshift == -1 + assert d[0][1].bitsize == -1 + 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].bitsize == -1 + # + p = newp(new_pointer_type(BStruct)) + p.x = 42 + assert p.x == 42 + assert typeof(p.y) is BIntP + assert p.y == cast(BIntP, p) + 1 + # + p = newp(new_pointer_type(BStruct), [100]) + assert p.x == 100 + # + # Tests for + # ffi.new("struct_with_var_array *", [field.., [the_array_items..]]) + # ffi.new("struct_with_var_array *", [field.., array_size]) + plist = [] + for i in range(20): + if i % 2 == 0: + p = newp(new_pointer_type(BStruct), [100, [200, i, 400]]) + else: + p = newp(new_pointer_type(BStruct), [100, 3]) + p.y[1] = i + p.y[0] = 200 + assert p.y[2] == 0 + p.y[2] = 400 + plist.append(p) + for i in range(20): + p = plist[i] + assert p.x == 100 + assert p.y[0] == 200 + assert p.y[1] == i + assert p.y[2] == 400 + assert list(p.y[0:3]) == [200, i, 400] + # + # the following assignment works, as it normally would, for any array field + p.y = [500, 600] + assert list(p.y[0:3]) == [500, 600, 400] + # + # error cases + py.test.raises(TypeError, "p.y = cast(BIntP, 0)") + py.test.raises(TypeError, "p.y = 15") + py.test.raises(TypeError, "p.y = None") + # + # accepting this may be specified by the C99 standard, + # or a GCC strangeness... + BStruct2 = new_struct_type("bar") + complete_struct_or_union(BStruct2, [('f', BStruct), + ('n', BInt)]) + p = newp(new_pointer_type(BStruct2), {'n': 42}) + assert p.n == 42 + # + # more error cases + py.test.raises(TypeError, newp, new_pointer_type(BStruct), [100, None]) + BArray4 = new_array_type(BIntP, 4) + BStruct4 = new_struct_type("test4") + complete_struct_or_union(BStruct4, [('a', BArray4)]) # not varsized + py.test.raises(TypeError, newp, new_pointer_type(BStruct4), [None]) + py.test.raises(TypeError, newp, new_pointer_type(BStruct4), [4]) + p = newp(new_pointer_type(BStruct4), [[10, 20, 30]]) + assert p.a[0] == 10 + assert p.a[1] == 20 + assert p.a[2] == 30 + assert p.a[3] == 0 + +def test_struct_array_no_length_explicit_position(): + BInt = new_primitive_type("int") + BIntP = new_pointer_type(BInt) + BArray = new_array_type(BIntP, None) + BStruct = new_struct_type("foo") + complete_struct_or_union(BStruct, [('x', BArray, -1, 0), # actually 3 items + ('y', BInt, -1, 12)]) + p = newp(new_pointer_type(BStruct), [[10, 20], 30]) + assert p.x[0] == 10 + assert p.x[1] == 20 + assert p.x[2] == 0 + assert p.y == 30 + p = newp(new_pointer_type(BStruct), {'x': [40], 'y': 50}) + assert p.x[0] == 40 + assert p.x[1] == 0 + assert p.x[2] == 0 + assert p.y == 50 + p = newp(new_pointer_type(BStruct), {'y': 60}) + assert p.x[0] == 0 + assert p.x[1] == 0 + assert p.x[2] == 0 + assert p.y == 60 + # + # This "should" work too, allocating a larger structure + # (a bit strange in this case, but useful in general) + plist = [] + for i in range(20): + p = newp(new_pointer_type(BStruct), [[10, 20, 30, 40, 50, 60, 70]]) + plist.append(p) + for i in range(20): + p = plist[i] + assert p.x[0] == 10 + assert p.x[1] == 20 + assert p.x[2] == 30 + assert p.x[3] == 40 == p.y + assert p.x[4] == 50 + assert p.x[5] == 60 + assert p.x[6] == 70 + +def test_ass_slice(): + BChar = new_primitive_type("char") + BArray = new_array_type(new_pointer_type(BChar), None) + p = newp(BArray, b"foobar") + p[2:5] = [b"*", b"Z", b"T"] + p[1:3] = b"XY" + assert list(p) == [b"f", b"X", b"Y", b"Z", b"T", b"r", b"\x00"] + py.test.raises(TypeError, "p[1:5] = u+'XYZT'") + py.test.raises(TypeError, "p[1:5] = [1, 2, 3, 4]") + # + BUniChar = new_primitive_type("wchar_t") + BArray = new_array_type(new_pointer_type(BUniChar), None) + p = newp(BArray, u+"foobar") + p[2:5] = [u+"*", u+"Z", u+"T"] + p[1:3] = u+"XY" + assert list(p) == [u+"f", u+"X", u+"Y", u+"Z", u+"T", u+"r", u+"\x00"] + py.test.raises(TypeError, "p[1:5] = b'XYZT'") + py.test.raises(TypeError, "p[1:5] = [1, 2, 3, 4]") + +def test_void_p_arithmetic(): + BVoid = new_void_type() + BInt = new_primitive_type("intptr_t") + p = cast(new_pointer_type(BVoid), 100000) + assert int(cast(BInt, p)) == 100000 + assert int(cast(BInt, p + 42)) == 100042 + assert int(cast(BInt, p - (-42))) == 100042 + assert (p + 42) - p == 42 + q = cast(new_pointer_type(new_primitive_type("char")), 100000) + py.test.raises(TypeError, "p - q") + py.test.raises(TypeError, "q - p") + py.test.raises(TypeError, "p + cast(new_primitive_type('int'), 42)") + py.test.raises(TypeError, "p - cast(new_primitive_type('int'), 42)") + + def test_version(): # this test is here mostly for PyPy assert __version__ == "0.7" _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit