Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r514:9824c8551f0d Date: 2012-06-25 23:35 +0200 http://bitbucket.org/cffi/cffi/changeset/9824c8551f0d/
Log: Tweak the API with respect to None: it no longer means "NULL". diff --git a/c/_ffi_backend.c b/c/_ffi_backend.c --- a/c/_ffi_backend.c +++ b/c/_ffi_backend.c @@ -550,13 +550,7 @@ /* non-primitive types (check done just for performance) */ if (ct->ct_flags & (CT_POINTER|CT_FUNCTIONPTR)) { char *ptrdata = *(char **)data; - if (ptrdata != NULL) { - return new_simple_cdata(ptrdata, ct); - } - else { - Py_INCREF(Py_None); - return Py_None; - } + return new_simple_cdata(ptrdata, ct); } else if (ct->ct_flags & CT_IS_OPAQUE) { PyErr_Format(PyExc_TypeError, "cannot return a cdata '%s'", @@ -759,21 +753,17 @@ char *ptrdata; CTypeDescrObject *ctinit; - if (init != Py_None) { - expected = "compatible pointer"; - if (!CData_Check(init)) - goto cannot_convert; - ctinit = ((CDataObject *)init)->c_type; - if (!(ctinit->ct_flags & (CT_POINTER|CT_FUNCTIONPTR|CT_ARRAY))) - goto cannot_convert; - if (ctinit->ct_itemdescr != ct->ct_itemdescr && - !(ct->ct_itemdescr->ct_flags & CT_CAST_ANYTHING)) - goto cannot_convert; - ptrdata = ((CDataObject *)init)->c_data; - } - else { - ptrdata = NULL; - } + expected = "compatible pointer"; + if (!CData_Check(init)) + goto cannot_convert; + ctinit = ((CDataObject *)init)->c_type; + if (!(ctinit->ct_flags & (CT_POINTER|CT_FUNCTIONPTR|CT_ARRAY))) + goto cannot_convert; + if (ctinit->ct_itemdescr != ct->ct_itemdescr && + !(ct->ct_itemdescr->ct_flags & CT_CAST_ANYTHING)) + goto cannot_convert; + ptrdata = ((CDataObject *)init)->c_data; + *(char **)data = ptrdata; return 0; } @@ -1027,7 +1017,32 @@ static PyObject *cdata_repr(CDataObject *cd) { - return PyString_FromFormat("<cdata '%s'>", cd->c_type->ct_name); + char *p; + PyObject *result, *s = NULL; + + if (cd->c_type->ct_flags & CT_PRIMITIVE_ANY) { + PyObject *o = convert_to_object(cd->c_data, cd->c_type); + if (o == NULL) + return NULL; + s = PyObject_Repr(o); + Py_DECREF(o); + if (s == NULL) + return NULL; + p = PyString_AS_STRING(s); + } + else { + if (cd->c_data != NULL) { + s = PyString_FromFormat("%p", cd->c_data); + if (s == NULL) + return NULL; + p = PyString_AS_STRING(s); + } + else + p = "NULL"; + } + result = PyString_FromFormat("<cdata '%s' %s>", cd->c_type->ct_name, p); + Py_XDECREF(s); + return result; } static PyObject *cdata_str(CDataObject *cd) @@ -1145,30 +1160,21 @@ static PyObject *cdata_richcompare(PyObject *v, PyObject *w, int op) { - int res, full_order; + int res; PyObject *pyres; char *v_cdata, *w_cdata; - full_order = (op != Py_EQ && op != Py_NE); - assert(CData_Check(v)); + if (!CData_Check(w)) + goto Unimplemented; + v_cdata = ((CDataObject *)v)->c_data; - if (full_order && - (((CDataObject *)v)->c_type->ct_flags & CT_PRIMITIVE_ANY)) + w_cdata = ((CDataObject *)w)->c_data; + if ((op != Py_EQ && op != Py_NE) && + ((((CDataObject *)v)->c_type->ct_flags & CT_PRIMITIVE_ANY) || + (((CDataObject *)w)->c_type->ct_flags & CT_PRIMITIVE_ANY))) goto Error; - if (w == Py_None) { - w_cdata = NULL; - } - else if (CData_Check(w)) { - w_cdata = ((CDataObject *)w)->c_data; - if (full_order && - (((CDataObject *)w)->c_type->ct_flags & CT_PRIMITIVE_ANY)) - goto Error; - } - else - goto Unimplemented; - switch (op) { case Py_EQ: res = (v_cdata == w_cdata); break; case Py_NE: res = (v_cdata != w_cdata); break; @@ -1735,9 +1741,9 @@ { CTypeDescrObject *ct, *ctitem; CDataObject_own_base *cdb; - PyObject *init; + PyObject *init = Py_None; Py_ssize_t dataoffset, datasize, explicitlength; - if (!PyArg_ParseTuple(args, "O!O:newp", &CTypeDescr_Type, &ct, &init)) + if (!PyArg_ParseTuple(args, "O!|O:newp", &CTypeDescr_Type, &ct, &init)) return NULL; explicitlength = -1; @@ -1854,9 +1860,6 @@ value = (unsigned char)PyString_AS_STRING(ob)[0]; } } - else if (ob == Py_None) { - value = 0; - } else { value = _my_PyLong_AsUnsignedLongLong(ob, 0); if (value == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred()) @@ -1887,14 +1890,9 @@ return new_simple_cdata(cdsrc->c_data, ct); } } - if (ob == Py_None) { - value = 0; - } - else { - value = _my_PyLong_AsUnsignedLongLong(ob, 0); - if (value == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred()) - return NULL; - } + value = _my_PyLong_AsUnsignedLongLong(ob, 0); + if (value == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred()) + return NULL; return new_simple_cdata((char *)(Py_intptr_t)value, ct); } else if (ct->ct_flags & (CT_PRIMITIVE_SIGNED|CT_PRIMITIVE_UNSIGNED @@ -1928,9 +1926,6 @@ } value = (unsigned char)PyString_AS_STRING(io)[0]; } - else if (io == Py_None) { - value = 0.0; - } else { value = PyFloat_AsDouble(io); } @@ -3419,9 +3414,6 @@ if (PyString_Check(obj)) { return PyString_AS_STRING(obj); } - if (obj == Py_None) { - return NULL; - } if (CData_Check(obj)) { return ((CDataObject *)obj)->c_data; } diff --git a/c/test_c.py b/c/test_c.py --- a/c/test_c.py +++ b/c/test_c.py @@ -48,11 +48,11 @@ def test_cast_to_signed_char(): p = new_primitive_type("signed char") x = cast(p, -65 + 17*256) - assert repr(x) == "<cdata 'signed char'>" + assert repr(x) == "<cdata 'signed char' -65>" assert repr(type(x)) == "<type '_ffi_backend.CData'>" assert int(x) == -65 x = cast(p, -66 + (1<<199)*256) - assert repr(x) == "<cdata 'signed char'>" + assert repr(x) == "<cdata 'signed char' -66>" assert int(x) == -66 assert (x == cast(p, -66)) is False assert (x != cast(p, -66)) is True @@ -75,7 +75,7 @@ assert int(cast(p, max)) == max assert int(cast(p, min - 1)) == max assert int(cast(p, max + 1)) == min - assert int(cast(p, None)) == 0 + py.test.raises(TypeError, cast, p, None) assert long(cast(p, min - 1)) == max for name in ['char', 'short', 'int', 'long', 'long long']: p = new_primitive_type('unsigned ' + name) @@ -118,7 +118,7 @@ assert repr(float(cast(p, -0.0))) == '-0.0' assert float(cast(p, '\x09')) == 9.0 assert float(cast(p, True)) == 1.0 - assert float(cast(p, None)) == 0.0 + py.test.raises(TypeError, cast, p, None) def test_character_type(): p = new_primitive_type("char") @@ -142,22 +142,23 @@ def test_pointer_to_int(): BInt = new_primitive_type("int") + py.test.raises(TypeError, newp, BInt) py.test.raises(TypeError, newp, BInt, None) BPtr = new_pointer_type(BInt) + p = newp(BPtr) + assert repr(p) == "<cdata 'int *' owning %d bytes>" % size_of_int() p = newp(BPtr, None) assert repr(p) == "<cdata 'int *' owning %d bytes>" % size_of_int() p = newp(BPtr, 5000) assert repr(p) == "<cdata 'int *' owning %d bytes>" % size_of_int() q = cast(BPtr, p) - assert repr(q) == "<cdata 'int *'>" + assert repr(q).startswith("<cdata 'int *' 0x") assert p == q assert hash(p) == hash(q) def test_pointer_bool(): BInt = new_primitive_type("int") BPtr = new_pointer_type(BInt) - p = cast(BPtr, None) - assert bool(p) is False p = cast(BPtr, 0) assert bool(p) is False p = cast(BPtr, 42) @@ -232,6 +233,29 @@ assert str(cast(BChar, 'A')) == 'A' py.test.raises(TypeError, cast, BChar, 'foo') +def test_reading_pointer_to_pointer(): + BVoidP = new_pointer_type(new_void_type()) + BCharP = new_pointer_type(new_primitive_type("char")) + BInt = new_primitive_type("int") + BIntPtr = new_pointer_type(BInt) + BIntPtrPtr = new_pointer_type(BIntPtr) + q = newp(BIntPtr, 42) + assert q[0] == 42 + p = newp(BIntPtrPtr, None) + assert p[0] is not None + assert p[0] == cast(BVoidP, 0) + assert p[0] == cast(BCharP, 0) + assert p[0] != None + assert repr(p[0]) == "<cdata 'int *' NULL>" + p[0] = q + assert p[0] != cast(BVoidP, 0) + assert p[0] != cast(BCharP, 0) + assert p[0][0] == 42 + q[0] += 1 + assert p[0][0] == 43 + p = newp(BIntPtrPtr, q) + assert p[0][0] == 43 + def test_hash_differences(): BChar = new_primitive_type("char") BInt = new_primitive_type("int") @@ -375,10 +399,10 @@ a = newp(p2, [range(n, n+5) for n in [100, 200, 300]]) assert repr(a) == "<cdata 'int[3][5]' owning %d bytes>" % ( 3*5*size_of_int(),) - assert repr(a + 0) == "<cdata 'int(*)[5]'>" - assert repr(a[0]) == "<cdata 'int[5]'>" - assert repr((a + 0)[0]) == "<cdata 'int[5]'>" - assert repr(a[0] + 0) == "<cdata 'int *'>" + assert repr(a + 0).startswith("<cdata 'int(*)[5]' 0x") + 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") assert type(a[0][0]) is int assert type((a[0] + 0)[0]) is int @@ -459,12 +483,11 @@ f = cast(BIntP, int(d)) assert f[3] == 43 # - for null in [0, None]: - b = cast(BShortP, null) - assert not b - c = cast(BIntP, b) - assert not c - assert int(cast(BLongLong, c)) == 0 + b = cast(BShortP, 0) + assert not b + c = cast(BIntP, b) + assert not c + assert int(cast(BLongLong, c)) == 0 def test_alignof(): BInt = new_primitive_type("int") @@ -538,7 +561,7 @@ BInt = new_primitive_type("int") BStruct = new_struct_type("foo") BStructPtr = new_pointer_type(BStruct) - p = cast(BStructPtr, None) + p = cast(BStructPtr, 0) py.test.raises(AttributeError, "p.a1") # opaque complete_struct_or_union(BStruct, [('a1', BInt, -1), ('a2', BInt, -1)]) @@ -553,6 +576,15 @@ py.test.raises(AttributeError, "p.foobar") py.test.raises(AttributeError, "s.foobar") +def test_union_instance(): + BInt = new_primitive_type("int") + BUInt = new_primitive_type("unsigned int") + BUnion = new_union_type("bar") + complete_struct_or_union(BUnion, [('a1', BInt, -1), ('a2', BUInt, -1)]) + p = newp(new_pointer_type(BUnion), -42) + assert p.a1 == -42 + assert p.a2 == -42 + (1 << (8*size_of_int())) + def test_struct_pointer(): BInt = new_primitive_type("int") BStruct = new_struct_type("foo") @@ -566,23 +598,33 @@ assert p.a2 == 123 def test_struct_init_list(): + BVoidP = new_pointer_type(new_void_type()) BInt = new_primitive_type("int") BStruct = new_struct_type("foo") BStructPtr = new_pointer_type(BStruct) complete_struct_or_union(BStruct, [('a1', BInt, -1), ('a2', BInt, -1), - ('a3', BInt, -1)]) + ('a3', BInt, -1), + ('p4', new_pointer_type(BInt), -1)]) s = newp(BStructPtr, [123, 456]) assert s.a1 == 123 assert s.a2 == 456 assert s.a3 == 0 + assert s.p4 == cast(BVoidP, 0) # s = newp(BStructPtr, {'a2': 41122, 'a3': -123}) assert s.a1 == 0 assert s.a2 == 41122 assert s.a3 == -123 + assert s.p4 == cast(BVoidP, 0) # py.test.raises(KeyError, newp, BStructPtr, {'foobar': 0}) + # + p = newp(new_pointer_type(BInt), 14141) + s = newp(BStructPtr, [12, 34, 56, p]) + assert s.p4 == p + # + py.test.raises(TypeError, newp, BStructPtr, [12, 34, 56, None]) def test_array_in_struct(): BInt = new_primitive_type("int") @@ -591,7 +633,7 @@ complete_struct_or_union(BStruct, [('a1', BArrayInt5, -1)]) s = newp(new_pointer_type(BStruct), [[20, 24, 27, 29, 30]]) assert s.a1[2] == 27 - assert repr(s.a1) == "<cdata 'int[5]'>" + assert repr(s.a1).startswith("<cdata 'int[5]' 0x") def test_offsetof(): BInt = new_primitive_type("int") @@ -760,8 +802,9 @@ BVoidP = new_pointer_type(new_void_type()) ll = find_and_load_library('c') stderr = ll.read_variable(BVoidP, "stderr") - ll.write_variable(BVoidP, "stderr", None) - assert ll.read_variable(BVoidP, "stderr") is None + ll.write_variable(BVoidP, "stderr", cast(BVoidP, 0)) + assert ll.read_variable(BVoidP, "stderr") is not None + assert not ll.read_variable(BVoidP, "stderr") ll.write_variable(BVoidP, "stderr", stderr) assert ll.read_variable(BVoidP, "stderr") == stderr @@ -798,7 +841,7 @@ def test_cast_to_enum(): BEnum = new_enum_type("foo", ('def', 'c', 'ab'), (0, 1, -20)) e = cast(BEnum, 0) - assert repr(e) == "<cdata 'enum foo'>" + assert repr(e) == "<cdata 'enum foo' 'def'>" assert str(e) == 'def' assert str(cast(BEnum, -20)) == 'ab' assert str(cast(BEnum, 'c')) == 'c' @@ -807,6 +850,8 @@ assert int(cast(BEnum, -242 + 2**128)) == -242 assert str(cast(BEnum, -242 + 2**128)) == '#-242' assert str(cast(BEnum, '#-20')) == 'ab' + assert repr(cast(BEnum, '#-20')) == "<cdata 'enum foo' 'ab'>" + assert repr(cast(BEnum, '#-21')) == "<cdata 'enum foo' '#-21'>" def test_enum_in_struct(): BEnum = new_enum_type("foo", ('def', 'c', 'ab'), (0, 1, -20)) _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit