Issue #16286: write a new subfunction bytes_compare_eq()

* cleanup bytes_richcompare()
* PyUnicode_RichCompare(): replace a test with a XOR
This commit is contained in:
Victor Stinner 2013-11-04 11:08:10 +01:00
parent 63d867e95c
commit c8bc5377ac
2 changed files with 50 additions and 42 deletions

View File

@ -802,6 +802,23 @@ bytes_item(PyBytesObject *a, Py_ssize_t i)
return PyLong_FromLong((unsigned char)a->ob_sval[i]); return PyLong_FromLong((unsigned char)a->ob_sval[i]);
} }
Py_LOCAL(int)
bytes_compare_eq(PyBytesObject *a, PyBytesObject *b)
{
int cmp;
Py_ssize_t len;
len = Py_SIZE(a);
if (Py_SIZE(b) != len)
return 0;
if (a->ob_sval[0] != b->ob_sval[0])
return 0;
cmp = memcmp(a->ob_sval, b->ob_sval, len);
return (cmp == 0);
}
static PyObject* static PyObject*
bytes_richcompare(PyBytesObject *a, PyBytesObject *b, int op) bytes_richcompare(PyBytesObject *a, PyBytesObject *b, int op)
{ {
@ -822,53 +839,46 @@ bytes_richcompare(PyBytesObject *a, PyBytesObject *b, int op)
return NULL; return NULL;
} }
result = Py_NotImplemented; result = Py_NotImplemented;
goto out;
} }
if (a == b) { else if (a == b) {
switch (op) { switch (op) {
case Py_EQ:case Py_LE:case Py_GE: case Py_EQ:case Py_LE:case Py_GE:
result = Py_True; result = Py_True;
goto out; break;
case Py_NE:case Py_LT:case Py_GT: case Py_NE:case Py_LT:case Py_GT:
result = Py_False; result = Py_False;
goto out; break;
} }
} }
if (op == Py_EQ) { else if (op == Py_EQ || op == Py_NE) {
/* Supporting Py_NE here as well does not save int eq = bytes_compare_eq(a, b);
much time, since Py_NE is rarely used. */ eq ^= (op == Py_NE);
if (Py_SIZE(a) == Py_SIZE(b) result = eq ? Py_True : Py_False;
&& (a->ob_sval[0] == b->ob_sval[0] }
&& memcmp(a->ob_sval, b->ob_sval, Py_SIZE(a)) == 0)) { else {
result = Py_True; len_a = Py_SIZE(a); len_b = Py_SIZE(b);
} else { min_len = (len_a < len_b) ? len_a : len_b;
result = Py_False; if (min_len > 0) {
c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval);
if (c==0)
c = memcmp(a->ob_sval, b->ob_sval, min_len);
} }
goto out; else
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:
assert(op != Py_EQ && op != Py_NE);
Py_RETURN_NOTIMPLEMENTED;
}
result = c ? Py_True : Py_False;
} }
len_a = Py_SIZE(a); len_b = Py_SIZE(b);
min_len = (len_a < len_b) ? len_a : len_b;
if (min_len > 0) {
c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval);
if (c==0)
c = memcmp(a->ob_sval, b->ob_sval, min_len);
} else
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_EQ: assert(0); break; /* unreachable */
case Py_NE: c = c != 0; break;
case Py_GT: c = c > 0; break;
case Py_GE: c = c >= 0; break;
default:
result = Py_NotImplemented;
goto out;
}
result = c ? Py_True : Py_False;
out:
Py_INCREF(result); Py_INCREF(result);
return result; return result;
} }

View File

@ -10526,7 +10526,7 @@ unicode_compare(PyObject *str1, PyObject *str2)
#undef COMPARE #undef COMPARE
} }
static int Py_LOCAL(int)
unicode_compare_eq(PyObject *str1, PyObject *str2) unicode_compare_eq(PyObject *str1, PyObject *str2)
{ {
int kind; int kind;
@ -10630,10 +10630,8 @@ PyUnicode_RichCompare(PyObject *left, PyObject *right, int op)
if (op == Py_EQ || op == Py_NE) { if (op == Py_EQ || op == Py_NE) {
result = unicode_compare_eq(left, right); result = unicode_compare_eq(left, right);
if (op == Py_EQ) result ^= (op == Py_NE);
v = TEST_COND(result); v = TEST_COND(result);
else
v = TEST_COND(!result);
} }
else { else {
result = unicode_compare(left, right); result = unicode_compare(left, right);