diff options
author | Guido van Rossum <guido@python.org> | 2007-04-09 00:43:24 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2007-04-09 00:43:24 (GMT) |
commit | 343e97ff7f939fc16d144a196a95ecf2e82c061e (patch) | |
tree | 96fd769c99919c8116eca192247ea7d1647fd64d | |
parent | 62cbc8a2618a41c28b8ec25f70f85f2da17705f2 (diff) | |
download | cpython-343e97ff7f939fc16d144a196a95ecf2e82c061e.zip cpython-343e97ff7f939fc16d144a196a95ecf2e82c061e.tar.gz cpython-343e97ff7f939fc16d144a196a95ecf2e82c061e.tar.bz2 |
For Make Benefit Glorious Nation of Backwards Compatibility,
bytes objects can now be compared to anything that supports the buffer API.
-rw-r--r-- | Lib/test/test_bytes.py | 15 | ||||
-rw-r--r-- | Objects/bytesobject.c | 43 |
2 files changed, 48 insertions, 10 deletions
diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py index 028cbfd..2999aa6 100644 --- a/Lib/test/test_bytes.py +++ b/Lib/test/test_bytes.py @@ -99,6 +99,21 @@ class BytesTest(unittest.TestCase): self.failIf(b3 < b2) self.failIf(b3 <= b2) + def test_compare_to_str(self): + self.assertEqual(b"abc" == "abc", True) + self.assertEqual(b"ab" != "abc", True) + self.assertEqual(b"ab" <= "abc", True) + self.assertEqual(b"ab" < "abc", True) + self.assertEqual(b"abc" >= "ab", True) + self.assertEqual(b"abc" > "ab", True) + + self.assertEqual(b"abc" != "abc", False) + self.assertEqual(b"ab" == "abc", False) + self.assertEqual(b"ab" > "abc", False) + self.assertEqual(b"ab" >= "abc", False) + self.assertEqual(b"abc" < "ab", False) + self.assertEqual(b"abc" <= "ab", False) + def test_nohash(self): self.assertRaises(TypeError, hash, bytes()) diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index f07130d..34f381a 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -838,33 +838,56 @@ bytes_str(PyBytesObject *self) } static PyObject * -bytes_richcompare(PyBytesObject *self, PyBytesObject *other, int op) +bytes_richcompare(PyObject *self, PyObject *other, int op) { + PyBufferProcs *self_buffer, *other_buffer; + Py_ssize_t self_size, other_size; + void *self_bytes, *other_bytes; PyObject *res; - int minsize; + Py_ssize_t minsize; int cmp; - if (!PyBytes_Check(self) || !PyBytes_Check(other)) { + /* For backwards compatibility, bytes can be compared to anything that + supports the (binary) buffer API. */ + + self_buffer = self->ob_type->tp_as_buffer; + if (self_buffer == NULL || + self_buffer->bf_getreadbuffer == NULL || + self_buffer->bf_getsegcount == NULL || + self_buffer->bf_getsegcount(self, NULL) != 1) + { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + self_size = self_buffer->bf_getreadbuffer(self, 0, &self_bytes); + + other_buffer = other->ob_type->tp_as_buffer; + if (other_buffer == NULL || + other_buffer->bf_getreadbuffer == NULL || + other_buffer->bf_getsegcount == NULL || + other_buffer->bf_getsegcount(self, NULL) != 1) + { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } + other_size = other_buffer->bf_getreadbuffer(other, 0, &other_bytes); - if (self->ob_size != other->ob_size && (op == Py_EQ || op == Py_NE)) { + 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->ob_size; - if (other->ob_size < minsize) - minsize = other->ob_size; + minsize = self_size; + if (other_size < minsize) + minsize = other_size; - cmp = memcmp(self->ob_bytes, other->ob_bytes, minsize); + cmp = memcmp(self_bytes, other_bytes, minsize); /* In ISO C, memcmp() guarantees to use unsigned bytes! */ if (cmp == 0) { - if (self->ob_size < other->ob_size) + if (self_size < other_size) cmp = -1; - else if (self->ob_size > other->ob_size) + else if (self_size > other_size) cmp = 1; } |