Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r2884:4abb5f4db011
Date: 2017-02-06 08:24 +0000
http://bitbucket.org/cffi/cffi/changeset/4abb5f4db011/

Log:    Merged in coronafire/cffi/buffer_richcompare (pull request #76)

        Add richcompare to buffer objects

diff --git a/c/minibuffer.h b/c/minibuffer.h
--- a/c/minibuffer.h
+++ b/c/minibuffer.h
@@ -155,6 +155,87 @@
     return 0;
 }
 
+static PyObject *
+mb_richcompare(PyObject *self, PyObject *other, int op)
+{
+    Py_ssize_t self_size, other_size;
+    Py_buffer self_bytes, other_bytes;
+    PyObject *res;
+    Py_ssize_t minsize;
+    int cmp, rc;
+
+    /* Bytes can be compared to anything that supports the (binary)
+       buffer API.  Except that a comparison with Unicode is always an
+       error, even if the comparison is for equality. */
+    rc = PyObject_IsInstance(self, (PyObject*)&PyUnicode_Type);
+    if (!rc)
+        rc = PyObject_IsInstance(other, (PyObject*)&PyUnicode_Type);
+    if (rc < 0)
+        return NULL;
+    if (rc) {
+        if (Py_BytesWarningFlag && (op == Py_EQ || op == Py_NE)) {
+            if (PyErr_WarnEx(PyExc_BytesWarning,
+                            "Comparison between bytearray and string", 1))
+                return NULL;
+        }
+
+        Py_INCREF(Py_NotImplemented);
+        return Py_NotImplemented;
+    }
+
+    if (PyObject_GetBuffer(self, &self_bytes, PyBUF_SIMPLE) != 0) {
+        PyErr_Clear();
+        Py_INCREF(Py_NotImplemented);
+        return Py_NotImplemented;
+
+    }
+    self_size = self_bytes.len;
+
+    if (PyObject_GetBuffer(other, &other_bytes, PyBUF_SIMPLE) != 0) {
+        PyErr_Clear();
+        PyBuffer_Release(&self_bytes);
+        Py_INCREF(Py_NotImplemented);
+        return Py_NotImplemented;
+
+    }
+    other_size = other_bytes.len;
+
+    if (self_size != other_size && (op == Py_EQ || op == Py_NE)) {
+        /* Shortcut: if the lengths differ, the objects differ */
+        cmp = (op == Py_NE);
+    }
+    else {
+        minsize = self_size;
+        if (other_size < minsize)
+            minsize = other_size;
+
+        cmp = memcmp(self_bytes.buf, other_bytes.buf, minsize);
+        /* In ISO C, memcmp() guarantees to use unsigned bytes! */
+
+        if (cmp == 0) {
+            if (self_size < other_size)
+                cmp = -1;
+            else if (self_size > other_size)
+                cmp = 1;
+        }
+
+        switch (op) {
+        case Py_LT: cmp = cmp <  0; break;
+        case Py_LE: cmp = cmp <= 0; break;
+        case Py_EQ: cmp = cmp == 0; break;
+        case Py_NE: cmp = cmp != 0; break;
+        case Py_GT: cmp = cmp >  0; break;
+        case Py_GE: cmp = cmp >= 0; break;
+        }
+    }
+
+    res = cmp ? Py_True : Py_False;
+    PyBuffer_Release(&self_bytes);
+    PyBuffer_Release(&other_bytes);
+    Py_INCREF(res);
+    return res;
+}
+
 #if PY_MAJOR_VERSION >= 3
 /* pfffffffffffff pages of copy-paste from listobject.c */
 static PyObject *mb_subscript(MiniBufferObj *self, PyObject *item)
@@ -287,7 +368,7 @@
     ffi_buffer_doc,                             /* tp_doc */
     (traverseproc)mb_traverse,                  /* tp_traverse */
     (inquiry)mb_clear,                          /* tp_clear */
-    0,                                          /* tp_richcompare */
+    (richcmpfunc)mb_richcompare,                /* tp_richcompare */
     offsetof(MiniBufferObj, mb_weakreflist),    /* tp_weaklistoffset */
     0,                                          /* tp_iter */
     0,                                          /* tp_iternext */
diff --git a/testing/cffi0/backend_tests.py b/testing/cffi0/backend_tests.py
--- a/testing/cffi0/backend_tests.py
+++ b/testing/cffi0/backend_tests.py
@@ -1226,6 +1226,23 @@
         assert list(a)[:1000] + [0] * (len(a)-1000) == list(b)
         f.close()
 
+    def test_ffi_buffer_comparisons(self):
+        ffi = FFI(backend=self.Backend())
+        ba = bytearray(range(100, 110))
+        a = ffi.new("uint8_t[]", list(ba))
+        try:
+            b_full = ffi.buffer(a)
+            b_short = ffi.buffer(a, 3)
+            b_mid = ffi.buffer(a, 6)
+        except NotImplementedError as e:
+            py.test.skip(str(e))
+        else:
+            content = b_full[:]
+            assert content == b_full == ba
+            assert b_short < b_mid < b_full
+            assert ba > b_mid > ba[0:2]
+            assert b_short != ba[1:4]
+
     def test_array_in_struct(self):
         ffi = FFI(backend=self.Backend())
         ffi.cdef("struct foo_s { int len; short data[5]; };")
diff --git a/testing/cffi0/test_ffi_backend.py 
b/testing/cffi0/test_ffi_backend.py
--- a/testing/cffi0/test_ffi_backend.py
+++ b/testing/cffi0/test_ffi_backend.py
@@ -191,10 +191,10 @@
         s = ffi.new("struct s1 *")
         setattr(s, name, value)
         assert getattr(s, name) == value
-        raw1 = ffi.buffer(s)[:]
+        buff1 = ffi.buffer(s)
         t = lib.try_with_value(fnames.index(name), value)
-        raw2 = ffi.buffer(t, len(raw1))[:]
-        assert raw1 == raw2
+        buff2 = ffi.buffer(t, len(buff1))
+        assert buff1 == buff2
 
     def test_bitfield_basic(self):
         self.check("int a; int b:9; int c:20; int y;", 8, 4, 12)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to