From e73bc8158cefded4f07f51455d0faf0c0d63e561 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Wed, 18 Mar 2015 11:39:48 +0100 Subject: [PATCH 2/2] Use Py_RICHCOMPARE in rich comparisons --- Modules/_datetimemodule.c | 42 ++++++++---------------------------------- Modules/_decimal/_decimal.c | 23 +---------------------- Modules/arraymodule.c | 17 +---------------- Modules/parsermodule.c | 32 ++------------------------------ Modules/selectmodule.c | 22 +--------------------- Objects/bytearrayobject.c | 21 +++++++-------------- Objects/bytesobject.c | 23 +++++------------------ Objects/cellobject.c | 28 +--------------------------- Objects/descrobject.c | 28 +--------------------------- Objects/floatobject.c | 27 ++++----------------------- Objects/listobject.c | 17 +---------------- Objects/longobject.c | 28 +--------------------------- Objects/tupleobject.c | 18 +----------------- Objects/unicodeobject.c | 19 +------------------ 14 files changed, 35 insertions(+), 310 deletions(-) diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index 09285d9..0064d69 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -1352,32 +1352,6 @@ build_struct_time(int y, int m, int d, int hh, int mm, int ss, int dstflag) * Miscellaneous helpers. */ -/* For various reasons, we need to use tp_richcompare instead of tp_reserved. - * The comparisons here all most naturally compute a cmp()-like result. - * This little helper turns that into a bool result for rich comparisons. - */ -static PyObject * -diff_to_bool(int diff, int op) -{ - PyObject *result; - int istrue; - - switch (op) { - case Py_EQ: istrue = diff == 0; break; - case Py_NE: istrue = diff != 0; break; - case Py_LE: istrue = diff <= 0; break; - case Py_GE: istrue = diff >= 0; break; - case Py_LT: istrue = diff < 0; break; - case Py_GT: istrue = diff > 0; break; - default: - assert(! "op unknown"); - istrue = 0; /* To shut up compiler */ - } - result = istrue ? Py_True : Py_False; - Py_INCREF(result); - return result; -} - /* Raises a "can't compare" TypeError and returns NULL. */ static PyObject * cmperror(PyObject *a, PyObject *b) @@ -1815,7 +1789,7 @@ delta_richcompare(PyObject *self, PyObject *other, int op) { if (PyDelta_Check(other)) { int diff = delta_cmp(self, other); - return diff_to_bool(diff, op); + return Py_RICHCOMPARE(diff, 0, op); } else { Py_RETURN_NOTIMPLEMENTED; @@ -2733,7 +2707,7 @@ date_richcompare(PyObject *self, PyObject *other, int op) int diff = memcmp(((PyDateTime_Date *)self)->data, ((PyDateTime_Date *)other)->data, _PyDateTime_DATE_DATASIZE); - return diff_to_bool(diff, op); + return Py_RICHCOMPARE(diff, 0, op); } else Py_RETURN_NOTIMPLEMENTED; @@ -3681,7 +3655,7 @@ time_richcompare(PyObject *self, PyObject *other, int op) diff = memcmp(((PyDateTime_Time *)self)->data, ((PyDateTime_Time *)other)->data, _PyDateTime_TIME_DATASIZE); - return diff_to_bool(diff, op); + return Py_RICHCOMPARE(diff, 0, op); } offset1 = time_utcoffset(self, NULL); if (offset1 == NULL) @@ -3699,7 +3673,7 @@ time_richcompare(PyObject *self, PyObject *other, int op) diff = memcmp(((PyDateTime_Time *)self)->data, ((PyDateTime_Time *)other)->data, _PyDateTime_TIME_DATASIZE); - result = diff_to_bool(diff, op); + result = Py_RICHCOMPARE(diff, 0, op); } /* The hard case: both aware with different UTC offsets */ else if (offset1 != Py_None && offset2 != Py_None) { @@ -3719,7 +3693,7 @@ time_richcompare(PyObject *self, PyObject *other, int op) if (diff == 0) diff = TIME_GET_MICROSECOND(self) - TIME_GET_MICROSECOND(other); - result = diff_to_bool(diff, op); + result = Py_RICHCOMPARE(diff, 0, op); } else if (op == Py_EQ) { result = Py_False; @@ -4577,7 +4551,7 @@ datetime_richcompare(PyObject *self, PyObject *other, int op) diff = memcmp(((PyDateTime_DateTime *)self)->data, ((PyDateTime_DateTime *)other)->data, _PyDateTime_DATETIME_DATASIZE); - return diff_to_bool(diff, op); + return Py_RICHCOMPARE(diff, 0, op); } offset1 = datetime_utcoffset(self, NULL); if (offset1 == NULL) @@ -4595,7 +4569,7 @@ datetime_richcompare(PyObject *self, PyObject *other, int op) diff = memcmp(((PyDateTime_DateTime *)self)->data, ((PyDateTime_DateTime *)other)->data, _PyDateTime_DATETIME_DATASIZE); - result = diff_to_bool(diff, op); + result = Py_RICHCOMPARE(diff, 0, op); } else if (offset1 != Py_None && offset2 != Py_None) { PyDateTime_Delta *delta; @@ -4610,7 +4584,7 @@ datetime_richcompare(PyObject *self, PyObject *other, int op) diff = GET_TD_SECONDS(delta) | GET_TD_MICROSECONDS(delta); Py_DECREF(delta); - result = diff_to_bool(diff, op); + result = Py_RICHCOMPARE(diff, 0, op); } else if (op == Py_EQ) { result = Py_False; diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index 169914c..833de1e 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -4300,28 +4300,7 @@ dec_richcompare(PyObject *v, PyObject *w, int op) return (op == Py_NE) ? incr_true() : incr_false(); } - switch (op) { - case Py_EQ: - r = (r == 0); - break; - case Py_NE: - r = (r != 0); - break; - case Py_LE: - r = (r <= 0); - break; - case Py_GE: - r = (r >= 0); - break; - case Py_LT: - r = (r == -1); - break; - case Py_GT: - r = (r == 1); - break; - } - - return PyBool_FromLong(r); + return Py_RICHCOMPARE(r, 0, op); } /* __ceil__ */ diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index 6e755f4..32a64f5 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -677,22 +677,7 @@ array_richcompare(PyObject *v, PyObject *w, int op) /* No more items to compare -- compare sizes */ Py_ssize_t vs = Py_SIZE(va); Py_ssize_t ws = Py_SIZE(wa); - int cmp; - switch (op) { - case Py_LT: cmp = vs < ws; break; - case Py_LE: cmp = vs <= ws; break; - case Py_EQ: cmp = vs == ws; break; - case Py_NE: cmp = vs != ws; break; - case Py_GT: cmp = vs > ws; break; - case Py_GE: cmp = vs >= ws; break; - default: return NULL; /* cannot happen */ - } - if (cmp) - res = Py_True; - else - res = Py_False; - Py_INCREF(res); - return res; + return Py_RICHCOMPARE(vs, ws, op); } /* We have an item that differs. First, shortcuts for EQ/NE */ diff --git a/Modules/parsermodule.c b/Modules/parsermodule.c index 36e9893..c71c232 100644 --- a/Modules/parsermodule.c +++ b/Modules/parsermodule.c @@ -301,7 +301,6 @@ static PyObject * parser_richcompare(PyObject *left, PyObject *right, int op) { int result; - PyObject *v; /* neither argument should be NULL, unless something's gone wrong */ if (left == NULL || right == NULL) { @@ -311,8 +310,7 @@ parser_richcompare(PyObject *left, PyObject *right, int op) /* both arguments should be instances of PyST_Object */ if (!PyST_Object_Check(left) || !PyST_Object_Check(right)) { - v = Py_NotImplemented; - goto finished; + Py_RETURN_NOTIMPLEMENTED; } if (left == right) @@ -322,33 +320,7 @@ parser_richcompare(PyObject *left, PyObject *right, int op) result = parser_compare_nodes(((PyST_Object *)left)->st_node, ((PyST_Object *)right)->st_node); - /* Convert return value to a Boolean */ - switch (op) { - case Py_EQ: - v = TEST_COND(result == 0); - break; - case Py_NE: - v = TEST_COND(result != 0); - break; - case Py_LE: - v = TEST_COND(result <= 0); - break; - case Py_GE: - v = TEST_COND(result >= 0); - break; - case Py_LT: - v = TEST_COND(result < 0); - break; - case Py_GT: - v = TEST_COND(result > 0); - break; - default: - PyErr_BadArgument(); - return NULL; - } - finished: - Py_INCREF(v); - return v; + return Py_RICHCOMPARE(result, 0, op); } /* parser_newstobject(node* st) diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c index ef53067..74a384d 100644 --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -1809,27 +1809,7 @@ kqueue_event_richcompare(kqueue_event_Object *s, kqueue_event_Object *o, result = 0; } - switch (op) { - case Py_EQ: - result = (result == 0); - break; - case Py_NE: - result = (result != 0); - break; - case Py_LE: - result = (result <= 0); - break; - case Py_GE: - result = (result >= 0); - break; - case Py_LT: - result = (result < 0); - break; - case Py_GT: - result = (result > 0); - break; - } - return PyBool_FromLong((long)result); + return Py_RICHCOMPARE(result, 0, op); } static PyTypeObject kqueue_event_Type = { diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c index 8b3267e..c9638b3 100644 --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -1010,7 +1010,6 @@ bytearray_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; @@ -1044,6 +1043,10 @@ bytearray_richcompare(PyObject *self, PyObject *other, int op) if (self_size != other_size && (op == Py_EQ || op == Py_NE)) { /* Shortcut: if the lengths differ, the objects differ */ cmp = (op == Py_NE); + + PyBuffer_Release(&self_bytes); + PyBuffer_Release(&other_bytes); + return PyBool_FromLong(cmp); } else { minsize = self_size; @@ -1060,21 +1063,11 @@ bytearray_richcompare(PyObject *self, PyObject *other, int op) 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; - } + PyBuffer_Release(&self_bytes); + PyBuffer_Release(&other_bytes); + return Py_RICHCOMPARE(cmp, 0, op); } - res = cmp ? Py_True : Py_False; - PyBuffer_Release(&self_bytes); - PyBuffer_Release(&other_bytes); - Py_INCREF(res); - return res; } static void diff --git a/Objects/bytesobject.c b/Objects/bytesobject.c index e0ac1ab..512ee4d 100644 --- a/Objects/bytesobject.c +++ b/Objects/bytesobject.c @@ -1381,7 +1381,6 @@ bytes_richcompare(PyBytesObject *a, PyBytesObject *b, int op) int c; Py_ssize_t len_a, len_b; Py_ssize_t min_len; - PyObject *result; /* Make sure both arguments are strings. */ if (!(PyBytes_Check(a) && PyBytes_Check(b))) { @@ -1394,7 +1393,7 @@ bytes_richcompare(PyBytesObject *a, PyBytesObject *b, int op) "Comparison between bytes and string", 1)) return NULL; } - result = Py_NotImplemented; + Py_RETURN_NOTIMPLEMENTED; } else if (a == b) { switch (op) { @@ -1402,12 +1401,12 @@ bytes_richcompare(PyBytesObject *a, PyBytesObject *b, int op) case Py_LE: case Py_GE: /* a string is equal to itself */ - result = Py_True; + Py_RETURN_TRUE; break; case Py_NE: case Py_LT: case Py_GT: - result = Py_False; + Py_RETURN_FALSE; break; default: PyErr_BadArgument(); @@ -1417,7 +1416,7 @@ bytes_richcompare(PyBytesObject *a, PyBytesObject *b, int op) else if (op == Py_EQ || op == Py_NE) { int eq = bytes_compare_eq(a, b); eq ^= (op == Py_NE); - result = eq ? Py_True : Py_False; + return PyBool_FromLong(eq); } else { len_a = Py_SIZE(a); @@ -1432,20 +1431,8 @@ bytes_richcompare(PyBytesObject *a, PyBytesObject *b, int op) c = 0; if (c == 0) c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0; - switch (op) { - case Py_LT: c = c < 0; break; - case Py_LE: c = c <= 0; break; - case Py_GT: c = c > 0; break; - case Py_GE: c = c >= 0; break; - default: - PyErr_BadArgument(); - return NULL; - } - result = c ? Py_True : Py_False; + return Py_RICHCOMPARE(c, 0, op); } - - Py_INCREF(result); - return result; } static Py_hash_t diff --git a/Objects/cellobject.c b/Objects/cellobject.c index eb5ad98..f129d6b 100644 --- a/Objects/cellobject.c +++ b/Objects/cellobject.c @@ -56,7 +56,6 @@ cell_dealloc(PyCellObject *op) static PyObject * cell_richcompare(PyObject *a, PyObject *b, int op) { - int result; PyObject *v; /* neither argument should be NULL, unless something's gone wrong */ @@ -75,32 +74,7 @@ cell_richcompare(PyObject *a, PyObject *b, int op) if (a != NULL && b != NULL) return PyObject_RichCompare(a, b, op); - result = (b == NULL) - (a == NULL); - switch (op) { - case Py_EQ: - v = TEST_COND(result == 0); - break; - case Py_NE: - v = TEST_COND(result != 0); - break; - case Py_LE: - v = TEST_COND(result <= 0); - break; - case Py_GE: - v = TEST_COND(result >= 0); - break; - case Py_LT: - v = TEST_COND(result < 0); - break; - case Py_GT: - v = TEST_COND(result > 0); - break; - default: - PyErr_BadArgument(); - return NULL; - } - Py_INCREF(v); - return v; + return Py_RICHCOMPARE(b == NULL, a == NULL, op); } static PyObject * diff --git a/Objects/descrobject.c b/Objects/descrobject.c index 2df5ac5..db8c5bc 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -1033,7 +1033,6 @@ wrapper_dealloc(wrapperobject *wp) static PyObject * wrapper_richcompare(PyObject *a, PyObject *b, int op) { - Py_intptr_t result; PyObject *v; PyWrapperDescrObject *a_descr, *b_descr; @@ -1056,32 +1055,7 @@ wrapper_richcompare(PyObject *a, PyObject *b, int op) return PyObject_RichCompare(a, b, op); } - result = a_descr - b_descr; - switch (op) { - case Py_EQ: - v = TEST_COND(result == 0); - break; - case Py_NE: - v = TEST_COND(result != 0); - break; - case Py_LE: - v = TEST_COND(result <= 0); - break; - case Py_GE: - v = TEST_COND(result >= 0); - break; - case Py_LT: - v = TEST_COND(result < 0); - break; - case Py_GT: - v = TEST_COND(result > 0); - break; - default: - PyErr_BadArgument(); - return NULL; - } - Py_INCREF(v); - return v; + return Py_RICHCOMPARE(a_descr, b_descr, op); } static Py_hash_t diff --git a/Objects/floatobject.c b/Objects/floatobject.c index 1d369f9..4f38cd4 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -303,6 +303,7 @@ float_richcompare(PyObject *v, PyObject *w, int op) { double i, j; int r = 0; + PyObject *result=NULL; assert(PyFloat_Check(v)); i = PyFloat_AS_DOUBLE(v); @@ -394,7 +395,6 @@ float_richcompare(PyObject *v, PyObject *w, int op) { double fracpart; double intpart; - PyObject *result = NULL; PyObject *one = NULL; PyObject *vv = NULL; PyObject *ww = w; @@ -458,28 +458,9 @@ float_richcompare(PyObject *v, PyObject *w, int op) Compare: PyFPE_START_PROTECT("richcompare", return NULL) - switch (op) { - case Py_EQ: - r = i == j; - break; - case Py_NE: - r = i != j; - break; - case Py_LE: - r = i <= j; - break; - case Py_GE: - r = i >= j; - break; - case Py_LT: - r = i < j; - break; - case Py_GT: - r = i > j; - break; - } - PyFPE_END_PROTECT(r) - return PyBool_FromLong(r); + result = Py_RICHCOMPARE(i, j, op); + PyFPE_END_PROTECT(result) + return result; Unimplemented: Py_RETURN_NOTIMPLEMENTED; diff --git a/Objects/listobject.c b/Objects/listobject.c index 8f88d18..ccda9a5 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -2256,23 +2256,8 @@ list_richcompare(PyObject *v, PyObject *w, int op) /* No more items to compare -- compare sizes */ Py_ssize_t vs = Py_SIZE(vl); Py_ssize_t ws = Py_SIZE(wl); - int cmp; PyObject *res; - switch (op) { - case Py_LT: cmp = vs < ws; break; - case Py_LE: cmp = vs <= ws; break; - case Py_EQ: cmp = vs == ws; break; - case Py_NE: cmp = vs != ws; break; - case Py_GT: cmp = vs > ws; break; - case Py_GE: cmp = vs >= ws; break; - default: return NULL; /* cannot happen */ - } - if (cmp) - res = Py_True; - else - res = Py_False; - Py_INCREF(res); - return res; + return Py_RICHCOMPARE(vs, ws, op); } /* We have an item that differs -- shortcuts for EQ/NE */ diff --git a/Objects/longobject.c b/Objects/longobject.c index 27bee50..d2f9d3d 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -2752,38 +2752,12 @@ static PyObject * long_richcompare(PyObject *self, PyObject *other, int op) { int result; - PyObject *v; CHECK_BINOP(self, other); if (self == other) result = 0; else result = long_compare((PyLongObject*)self, (PyLongObject*)other); - /* Convert the return value to a Boolean */ - switch (op) { - case Py_EQ: - v = TEST_COND(result == 0); - break; - case Py_NE: - v = TEST_COND(result != 0); - break; - case Py_LE: - v = TEST_COND(result <= 0); - break; - case Py_GE: - v = TEST_COND(result >= 0); - break; - case Py_LT: - v = TEST_COND(result == -1); - break; - case Py_GT: - v = TEST_COND(result == 1); - break; - default: - PyErr_BadArgument(); - return NULL; - } - Py_INCREF(v); - return v; + return Py_RICHCOMPARE(result, 0, op); } static Py_hash_t diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index 7efa1a6..ed0b3f1 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -603,23 +603,7 @@ tuplerichcompare(PyObject *v, PyObject *w, int op) if (i >= vlen || i >= wlen) { /* No more items to compare -- compare sizes */ - int cmp; - PyObject *res; - switch (op) { - case Py_LT: cmp = vlen < wlen; break; - case Py_LE: cmp = vlen <= wlen; break; - case Py_EQ: cmp = vlen == wlen; break; - case Py_NE: cmp = vlen != wlen; break; - case Py_GT: cmp = vlen > wlen; break; - case Py_GE: cmp = vlen >= wlen; break; - default: return NULL; /* cannot happen */ - } - if (cmp) - res = Py_True; - else - res = Py_False; - Py_INCREF(res); - return res; + return Py_RICHCOMPARE(vlen, wlen, op); } /* We have an item that differs -- shortcuts for EQ/NE */ diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 0dea83e..efda230 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -10878,24 +10878,7 @@ PyUnicode_RichCompare(PyObject *left, PyObject *right, int op) else { result = unicode_compare(left, right); - /* Convert the return value to a Boolean */ - switch (op) { - case Py_LE: - v = TEST_COND(result <= 0); - break; - case Py_GE: - v = TEST_COND(result >= 0); - break; - case Py_LT: - v = TEST_COND(result == -1); - break; - case Py_GT: - v = TEST_COND(result == 1); - break; - default: - PyErr_BadArgument(); - return NULL; - } + return Py_RICHCOMPARE(result, 0, op); } Py_INCREF(v); return v; -- 2.1.0