[pypy-commit] cffi wchar_t: hg merge default

arigo noreply at buildbot.pypy.org
Sat Jun 23 09:59:37 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: wchar_t
Changeset: r488:702a14644ece
Date: 2012-06-23 08:16 +0200
http://bitbucket.org/cffi/cffi/changeset/702a14644ece/

Log:	hg merge default

diff --git a/c/_ffi_backend.c b/c/_ffi_backend.c
--- a/c/_ffi_backend.c
+++ b/c/_ffi_backend.c
@@ -1148,34 +1148,52 @@
 
 static PyObject *cdata_richcompare(PyObject *v, PyObject *w, int op)
 {
-    CDataObject *obv, *obw;
-    int equal;
-    PyObject *res;
-
-    if (op != Py_EQ && op != Py_NE)
-        goto Unimplemented;
+    int res, full_order;
+    PyObject *pyres;
+    char *v_cdata, *w_cdata;
+
+    full_order = (op != Py_EQ && op != Py_NE);
 
     assert(CData_Check(v));
-    obv = (CDataObject *)v;
+    v_cdata = ((CDataObject *)v)->c_data;
+    if (full_order &&
+        (((CDataObject *)v)->c_type->ct_flags & CT_PRIMITIVE_ANY))
+        goto Error;
 
     if (w == Py_None) {
-        equal = (obv->c_data == NULL);
+        w_cdata = NULL;
     }
     else if (CData_Check(w)) {
-        obw = (CDataObject *)w;
-        equal = (obv->c_type == obw->c_type) && (obv->c_data == obw->c_data);
+        w_cdata = ((CDataObject *)w)->c_data;
+        if (full_order &&
+            (((CDataObject *)w)->c_type->ct_flags & CT_PRIMITIVE_ANY))
+            goto Error;
     }
     else
         goto Unimplemented;
 
-    res = (equal ^ (op == Py_NE)) ? Py_True : Py_False;
+    switch (op) {
+    case Py_EQ: res = (v_cdata == w_cdata); break;
+    case Py_NE: res = (v_cdata != w_cdata); break;
+    case Py_LT: res = (v_cdata <  w_cdata); break;
+    case Py_LE: res = (v_cdata <= w_cdata); break;
+    case Py_GT: res = (v_cdata >  w_cdata); break;
+    case Py_GE: res = (v_cdata >= w_cdata); break;
+    default: res = -1;
+    }
+    pyres = res ? Py_True : Py_False;
  done:
-    Py_INCREF(res);
-    return res;
+    Py_INCREF(pyres);
+    return pyres;
 
  Unimplemented:
-    res = Py_NotImplemented;
+    pyres = Py_NotImplemented;
     goto done;
+
+ Error:
+    PyErr_SetString(PyExc_TypeError,
+                    "cannot do comparison on a primitive cdata");
+    return NULL;
 }
 
 static long cdata_hash(CDataObject *cd)
@@ -1197,12 +1215,9 @@
     return -1;
 }
 
-static PyObject *
-cdata_subscript(CDataObject *cd, PyObject *key)
+static char *
+_cdata_get_indexed_ptr(CDataObject *cd, PyObject *key)
 {
-    CTypeDescrObject *ctitem = cd->c_type->ct_itemdescr;
-    /* use 'mp_subscript' instead of 'sq_item' because we don't want
-       negative indexes to be corrected automatically */
     Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
     if (i == -1 && PyErr_Occurred())
         return NULL;
@@ -1234,48 +1249,31 @@
                      cd->c_type->ct_name);
         return NULL;
     }
-    return convert_to_object(cd->c_data + i * ctitem->ct_size, ctitem);
+    return cd->c_data + i * cd->c_type->ct_itemdescr->ct_size;
+}
+
+static PyObject *
+cdata_subscript(CDataObject *cd, PyObject *key)
+{
+    char *c = _cdata_get_indexed_ptr(cd, key);
+    CTypeDescrObject *ctitem = cd->c_type->ct_itemdescr;
+    /* use 'mp_subscript' instead of 'sq_item' because we don't want
+       negative indexes to be corrected automatically */
+    if (c == NULL)
+        return NULL;
+    return convert_to_object(c, ctitem);
 }
 
 static int
 cdata_ass_sub(CDataObject *cd, PyObject *key, PyObject *v)
 {
+    char *c = _cdata_get_indexed_ptr(cd, key);
     CTypeDescrObject *ctitem = cd->c_type->ct_itemdescr;
     /* use 'mp_ass_subscript' instead of 'sq_ass_item' because we don't want
        negative indexes to be corrected automatically */
-    Py_ssize_t i = PyNumber_AsSsize_t(key, PyExc_IndexError);
-    if (i == -1 && PyErr_Occurred())
+    if (c == NULL)
         return -1;
-
-    if (cd->c_type->ct_flags & CT_POINTER) {
-        if (CDataOwn_Check(cd) && i != 0) {
-            PyErr_Format(PyExc_IndexError,
-                         "cdata '%s' can only be indexed by 0",
-                         cd->c_type->ct_name);
-            return -1;
-        }
-    }
-    else if (cd->c_type->ct_flags & CT_ARRAY) {
-        if (i < 0) {
-            PyErr_SetString(PyExc_IndexError,
-                            "negative index not supported");
-            return -1;
-        }
-        if (i >= get_array_length(cd)) {
-            PyErr_Format(PyExc_IndexError,
-                         "index too large for cdata '%s' (expected %zd < %zd)",
-                         cd->c_type->ct_name,
-                         i, get_array_length(cd));
-            return -1;
-        }
-    }
-    else {
-        PyErr_Format(PyExc_TypeError,
-                     "cdata of type '%s' does not support index assignment",
-                     cd->c_type->ct_name);
-        return -1;
-    }
-    return convert_from_object(cd->c_data + i * ctitem->ct_size, ctitem, v);
+    return convert_from_object(c, ctitem, v);
 }
 
 static PyObject *
@@ -1984,8 +1982,11 @@
             write_raw_float_data(cd->c_data, value, ct->ct_size);
         return (PyObject *)cd;
     }
-    else
-        goto cannot_cast;
+    else {
+        PyErr_Format(PyExc_TypeError, "cannot cast to ctype '%s'",
+                     ct->ct_name);
+        return NULL;
+    }
 
  cannot_cast:
     if (CData_Check(ob))
@@ -2363,11 +2364,7 @@
                 PyErr_SetString(PyExc_ValueError, "negative array length");
             return NULL;
         }
-#ifdef MS_WIN32
-        sprintf(extra_text, "[%ld]", (long)length);  /* XXX not large enough */
-#else
-        sprintf(extra_text, "[%zd]", length);
-#endif
+        sprintf(extra_text, "[%llu]", (unsigned PY_LONG_LONG)length);
         arraysize = length * ctitem->ct_size;
         if (length > 0 && (arraysize / length) != ctitem->ct_size) {
             PyErr_SetString(PyExc_OverflowError,
diff --git a/c/test_c.py b/c/test_c.py
--- a/c/test_c.py
+++ b/c/test_c.py
@@ -8,6 +8,7 @@
 from _ffi_backend import *
 from _ffi_backend import _getfields, _testfunc
 
+# ____________________________________________________________
 
 def size_of_int():
     BInt = new_primitive_type("int")
diff --git a/cffi/backend_ctypes.py b/cffi/backend_ctypes.py
--- a/cffi/backend_ctypes.py
+++ b/cffi/backend_ctypes.py
@@ -1,4 +1,4 @@
-import ctypes, ctypes.util
+import ctypes, ctypes.util, operator
 from . import model
 
 class CTypesData(object):
@@ -76,10 +76,42 @@
         raise TypeError("cdata %r does not support iteration" % (
             self._get_c_name()),)
 
+    def _make_cmp(name):
+        cmpfunc = getattr(operator, name)
+        def cmp(self, other):
+            if isinstance(other, CTypesData):
+                return cmpfunc(self._convert_to_address(None),
+                               other._convert_to_address(None))
+            elif other is None:
+                return cmpfunc(self._convert_to_address(None), 0)
+            else:
+                return NotImplemented
+        cmp.func_name = name
+        return cmp
+
+    __eq__ = _make_cmp('__eq__')
+    __ne__ = _make_cmp('__ne__')
+    __lt__ = _make_cmp('__lt__')
+    __le__ = _make_cmp('__le__')
+    __gt__ = _make_cmp('__gt__')
+    __ge__ = _make_cmp('__ge__')
+
+    def __hash__(self):
+        return hash(type(self)) ^ hash(self._convert_to_address(None))
+
 
 class CTypesGenericPrimitive(CTypesData):
     __slots__ = []
 
+    def __eq__(self, other):
+        return self is other
+
+    def __ne__(self, other):
+        return self is not other
+
+    def __hash__(self):
+        return object.__hash__(self)
+
 
 class CTypesGenericArray(CTypesData):
     __slots__ = []
@@ -119,18 +151,6 @@
     def __nonzero__(self):
         return bool(self._address)
 
-    def __eq__(self, other):
-        if other is None:
-            return not bool(self._address)
-        return (type(self) is type(other) and
-                self._address == other._address)
-
-    def __ne__(self, other):
-        return not self.__eq__(other)
-
-    def __hash__(self):
-        return hash(type(self)) ^ hash(self._address)
-
     @classmethod
     def _to_ctypes(cls, value):
         if value is None:
diff --git a/demo/winclipboard.py b/demo/winclipboard.py
--- a/demo/winclipboard.py
+++ b/demo/winclipboard.py
@@ -24,6 +24,9 @@
     BOOL  EmptyClipboard(void);
     HANDLE  SetClipboardData(UINT uFormat, HANDLE hMem);
 
+    #define CF_TEXT ...
+    #define GMEM_MOVEABLE ...
+
     void * memcpy(void * s1, void * s2, int n);
     ''')
 
@@ -37,9 +40,6 @@
     '''
         use win32 api to copy `string` to the clipboard
     '''
-    CF_TEXT = 1
-    GMEM_MOVEABLE = 0x0002
-    
     hWnd = GetConsoleWindow()
   
     if OpenClipboard(hWnd):
diff --git a/testing/backend_tests.py b/testing/backend_tests.py
--- a/testing/backend_tests.py
+++ b/testing/backend_tests.py
@@ -67,6 +67,7 @@
         q = ffi.cast(c_decl, long(min - 1))
         assert ffi.typeof(q) is ffi.typeof(p) and int(q) == max
         assert q != p
+        assert int(q) == int(p)
         assert hash(q) != hash(p)   # unlikely
         py.test.raises(OverflowError, ffi.new, c_decl, min - 1)
         py.test.raises(OverflowError, ffi.new, c_decl, max + 1)
@@ -911,6 +912,67 @@
         assert p == s+0
         assert p+1 == s+1
 
+    def test_pointer_comparison(self):
+        ffi = FFI(backend=self.Backend())
+        s = ffi.new("short[]", range(100))
+        p = ffi.cast("short *", s)
+        assert (p <  s) is False
+        assert (p <= s) is True
+        assert (p == s) is True
+        assert (p != s) is False
+        assert (p >  s) is False
+        assert (p >= s) is True
+        assert (s <  p) is False
+        assert (s <= p) is True
+        assert (s == p) is True
+        assert (s != p) is False
+        assert (s >  p) is False
+        assert (s >= p) is True
+        q = p + 1
+        assert (q <  s) is False
+        assert (q <= s) is False
+        assert (q == s) is False
+        assert (q != s) is True
+        assert (q >  s) is True
+        assert (q >= s) is True
+        assert (s <  q) is True
+        assert (s <= q) is True
+        assert (s == q) is False
+        assert (s != q) is True
+        assert (s >  q) is False
+        assert (s >= q) is False
+        assert (q <  p) is False
+        assert (q <= p) is False
+        assert (q == p) is False
+        assert (q != p) is True
+        assert (q >  p) is True
+        assert (q >= p) is True
+        assert (p <  q) is True
+        assert (p <= q) is True
+        assert (p == q) is False
+        assert (p != q) is True
+        assert (p >  q) is False
+        assert (p >= q) is False
+        #
+        assert (None == s) is False
+        assert (None != s) is True
+        assert (s == None) is False
+        assert (s != None) is True
+        assert (None == q) is False
+        assert (None != q) is True
+        assert (q == None) is False
+        assert (q != None) is True
+
+    def test_no_integer_comparison(self):
+        ffi = FFI(backend=self.Backend())
+        x = ffi.cast("int", 123)
+        y = ffi.cast("int", 456)
+        py.test.raises(TypeError, "x < y")
+        #
+        z = ffi.cast("double", 78.9)
+        py.test.raises(TypeError, "x < z")
+        py.test.raises(TypeError, "z < y")
+
     def test_ffi_buffer_ptr(self):
         ffi = FFI(backend=self.Backend())
         a = ffi.new("short", 100)


More information about the pypy-commit mailing list