[pypy-commit] creflect default: copy cdata_as_number from _cffi_backend
arigo
noreply at buildbot.pypy.org
Fri Dec 5 21:41:57 CET 2014
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r182:7f8cb0c71de4
Date: 2014-12-05 21:42 +0100
http://bitbucket.org/cffi/creflect/changeset/7f8cb0c71de4/
Log: copy cdata_as_number from _cffi_backend
diff --git a/zeffir/cdata.c b/zeffir/cdata.c
--- a/zeffir/cdata.c
+++ b/zeffir/cdata.c
@@ -1050,6 +1050,85 @@
}
}
+//1699
+static int cdata_nonzero(CDataObject *cd)
+{
+ return cd->c_data != NULL;
+}
+
+
+//1751
+static PyObject *cdata_float(CDataObject *cd)
+{
+ if (cd->c_type->ct_flags & CT_PRIMITIVE_FLOAT) {
+ double value;
+ /*READ(cd->c_data, cd->c_type->ct_size)*/
+ if (!(cd->c_type->ct_flags & CT_IS_LONGDOUBLE)) {
+ value = read_raw_float_data(cd->c_data, cd->c_type->ct_size);
+ }
+ else {
+ value = (double)read_raw_longdouble_data(cd->c_data);
+ }
+ return PyFloat_FromDouble(value);
+ }
+ PyErr_Format(PyExc_TypeError, "float() not supported on cdata '%s'",
+ cd->c_type->ct_name);
+ return NULL;
+}
+
+//1700
+static PyObject *cdata_int(CDataObject *cd)
+{
+ if ((cd->c_type->ct_flags & (CT_PRIMITIVE_SIGNED|CT_PRIMITIVE_FITS_LONG))
+ == (CT_PRIMITIVE_SIGNED|CT_PRIMITIVE_FITS_LONG)) {
+ /* this case is to handle enums, but also serves as a slight
+ performance improvement for some other primitive types */
+ long value;
+ /*READ(cd->c_data, cd->c_type->ct_size)*/
+ value = (long)read_raw_signed_data(cd->c_data, cd->c_type->ct_size);
+ return PyInt_FromLong(value);
+ }
+ if (cd->c_type->ct_flags & (CT_PRIMITIVE_SIGNED|CT_PRIMITIVE_UNSIGNED)) {
+ return convert_to_object(cd->c_data, cd->c_type);
+ }
+ else if (cd->c_type->ct_flags & CT_PRIMITIVE_CHAR) {
+ /*READ(cd->c_data, cd->c_type->ct_size)*/
+ if (cd->c_type->ct_size == sizeof(char))
+ return PyInt_FromLong((unsigned char)cd->c_data[0]);
+#ifdef HAVE_WCHAR_H
+ else
+ return PyInt_FromLong((long)*(wchar_t *)cd->c_data);
+#endif
+ }
+ else if (cd->c_type->ct_flags & CT_PRIMITIVE_FLOAT) {
+ PyObject *o = cdata_float(cd);
+#if PY_MAJOR_VERSION < 3
+ PyObject *r = o ? PyNumber_Int(o) : NULL;
+#else
+ PyObject *r = o ? PyNumber_Long(o) : NULL;
+#endif
+ Py_XDECREF(o);
+ return r;
+ }
+ PyErr_Format(PyExc_TypeError, "int() not supported on cdata '%s'",
+ cd->c_type->ct_name);
+ return NULL;
+}
+
+#if PY_MAJOR_VERSION < 3
+//1739
+static PyObject *cdata_long(CDataObject *cd)
+{
+ PyObject *res = cdata_int(cd);
+ if (res != NULL && PyInt_CheckExact(res)) {
+ PyObject *o = PyLong_FromLong(PyInt_AS_LONG(res));
+ Py_DECREF(res);
+ res = o;
+ }
+ return res;
+}
+#endif
+
//1769
static PyObject *cdata_richcompare(PyObject *v, PyObject *w, int op)
{
@@ -1337,6 +1416,97 @@
return convert_from_object(c, ctitem, v);
}
+//2081
+static PyObject *_cdata_add_or_sub(PyObject *v, PyObject *w, int sign)
+{
+ Py_ssize_t i, itemsize;
+ CDataObject *cd;
+ CTypeDescrObject *ctptr;
+
+ if (!CData_Check(v)) {
+ PyObject *swap;
+ assert(CData_Check(w));
+ if (sign != 1)
+ goto not_implemented;
+ swap = v;
+ v = w;
+ w = swap;
+ }
+
+ i = PyNumber_AsSsize_t(w, PyExc_OverflowError);
+ if (i == -1 && PyErr_Occurred())
+ return NULL;
+ i *= sign;
+
+ cd = (CDataObject *)v;
+ if (cd->c_type->ct_flags & CT_POINTER)
+ ctptr = cd->c_type;
+ else if (cd->c_type->ct_flags & CT_ARRAY) {
+ ctptr = (CTypeDescrObject *)cd->c_type->ct_stuff;
+ }
+ else {
+ PyErr_Format(PyExc_TypeError, "cannot add a cdata '%s' and a number",
+ cd->c_type->ct_name);
+ return NULL;
+ }
+ itemsize = ctptr->ct_itemdescr->ct_size;
+ if (itemsize < 0) {
+ if (ctptr->ct_flags & CT_IS_VOID_PTR) {
+ itemsize = 1;
+ }
+ else {
+ PyErr_Format(PyExc_TypeError,
+ "ctype '%s' points to items of unknown size",
+ cd->c_type->ct_name);
+ return NULL;
+ }
+ }
+ return new_simple_cdata(cd->c_data + i * itemsize, ctptr);
+
+ not_implemented:
+ Py_INCREF(Py_NotImplemented);
+ return Py_NotImplemented;
+}
+
+//2133
+static PyObject *cdata_add(PyObject *v, PyObject *w)
+{
+ return _cdata_add_or_sub(v, w, +1);
+}
+
+//2139
+static PyObject *cdata_sub(PyObject *v, PyObject *w)
+{
+ if (CData_Check(v) && CData_Check(w)) {
+ CDataObject *cdv = (CDataObject *)v;
+ CDataObject *cdw = (CDataObject *)w;
+ CTypeDescrObject *ct = cdw->c_type;
+ Py_ssize_t diff, itemsize;
+
+ if (ct->ct_flags & CT_ARRAY) /* ptr_to_T - array_of_T: ok */
+ ct = (CTypeDescrObject *)ct->ct_stuff;
+
+ if (ct != cdv->c_type || !(ct->ct_flags & CT_POINTER) ||
+ (ct->ct_itemdescr->ct_size <= 0 &&
+ !(ct->ct_flags & CT_IS_VOID_PTR))) {
+ PyErr_Format(PyExc_TypeError,
+ "cannot subtract cdata '%s' and cdata '%s'",
+ cdv->c_type->ct_name, ct->ct_name);
+ return NULL;
+ }
+ itemsize = ct->ct_itemdescr->ct_size;
+ if (itemsize <= 0) itemsize = 1;
+ diff = (cdv->c_data - cdw->c_data) / itemsize;
+#if PY_MAJOR_VERSION < 3
+ return PyInt_FromSsize_t(diff);
+#else
+ return PyLong_FromSsize_t(diff);
+#endif
+ }
+
+ return _cdata_add_or_sub(v, w, -1);
+}
+
//2172
static PyObject *cdata_getattro(CDataObject *cd, PyObject *attr)
{
@@ -1390,6 +1560,40 @@
}
+static PyNumberMethods CData_as_number = {
+ (binaryfunc)cdata_add, /*nb_add*/
+ (binaryfunc)cdata_sub, /*nb_subtract*/
+ 0, /*nb_multiply*/
+#if PY_MAJOR_VERSION < 3
+ 0, /*nb_divide*/
+#endif
+ 0, /*nb_remainder*/
+ 0, /*nb_divmod*/
+ 0, /*nb_power*/
+ 0, /*nb_negative*/
+ 0, /*nb_positive*/
+ 0, /*nb_absolute*/
+ (inquiry)cdata_nonzero, /*nb_nonzero*/
+ 0, /*nb_invert*/
+ 0, /*nb_lshift*/
+ 0, /*nb_rshift*/
+ 0, /*nb_and*/
+ 0, /*nb_xor*/
+ 0, /*nb_or*/
+#if PY_MAJOR_VERSION < 3
+ 0, /*nb_coerce*/
+#endif
+ (unaryfunc)cdata_int, /*nb_int*/
+#if PY_MAJOR_VERSION < 3
+ (unaryfunc)cdata_long, /*nb_long*/
+#else
+ 0,
+#endif
+ (unaryfunc)cdata_float, /*nb_float*/
+ 0, /*nb_oct*/
+ 0, /*nb_hex*/
+};
+
static PyMappingMethods CData_as_mapping = {
(lenfunc)cdata_length, /*mp_length*/
(binaryfunc)cdata_subscript, /*mp_subscript*/
@@ -1407,7 +1611,7 @@
0, /* tp_setattr */
0, /* tp_compare */
(reprfunc)cdata_repr, /* tp_repr */
- 0,//&CData_as_number, /* tp_as_number */
+ &CData_as_number, /* tp_as_number */
0, /* tp_as_sequence */
&CData_as_mapping, /* tp_as_mapping */
(hashfunc)cdata_hash, /* tp_hash */
diff --git a/zeffir/test/test_cdata.py b/zeffir/test/test_cdata.py
--- a/zeffir/test/test_cdata.py
+++ b/zeffir/test/test_cdata.py
@@ -25,3 +25,16 @@
ffi = support.new_ffi()
p = ffi.new("int[]", [10, 20, 30])
assert p[2] == 30
+
+def test_cdata_as_number():
+ ffi = support.new_ffi()
+ p = ffi.new("int[]", [10, 20, 30])
+ assert (p + 2)[0] == 30
+ assert (p + 2) - p == 2
+ assert (p + 2) - (p + 1) == 1
+ assert p
+ assert not ffi.NULL
+ assert int(ffi.cast("short", 40000)) == 40000 - 65536
+ assert long(ffi.cast("short", 40000)) == 40000 - 65536
+ x = float(ffi.cast("float", 1.222))
+ assert 1E-15 < abs(x - 1.222) < 1E-8 # must get rounding errors
More information about the pypy-commit
mailing list