mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
Patch #424335: Implement string_richcompare, remove string_compare.
Use new _PyString_Eq in lookdict_string.
This commit is contained in:
parent
f8a548c23c
commit
cd35306a25
3 changed files with 82 additions and 17 deletions
|
@ -58,6 +58,7 @@ extern DL_IMPORT(char *) PyString_AsString(PyObject *);
|
||||||
extern DL_IMPORT(void) PyString_Concat(PyObject **, PyObject *);
|
extern DL_IMPORT(void) PyString_Concat(PyObject **, PyObject *);
|
||||||
extern DL_IMPORT(void) PyString_ConcatAndDel(PyObject **, PyObject *);
|
extern DL_IMPORT(void) PyString_ConcatAndDel(PyObject **, PyObject *);
|
||||||
extern DL_IMPORT(int) _PyString_Resize(PyObject **, int);
|
extern DL_IMPORT(int) _PyString_Resize(PyObject **, int);
|
||||||
|
extern DL_IMPORT(int) _PyString_Eq(PyObject *, PyObject*);
|
||||||
extern DL_IMPORT(PyObject *) PyString_Format(PyObject *, PyObject *);
|
extern DL_IMPORT(PyObject *) PyString_Format(PyObject *, PyObject *);
|
||||||
extern DL_IMPORT(PyObject *) _PyString_FormatLong(PyObject*, int, int,
|
extern DL_IMPORT(PyObject *) _PyString_FormatLong(PyObject*, int, int,
|
||||||
int, char**, int*);
|
int, char**, int*);
|
||||||
|
|
|
@ -294,7 +294,7 @@ lookdict(dictobject *mp, PyObject *key, register long hash)
|
||||||
* this assumption allows testing for errors during PyObject_Compare() to
|
* this assumption allows testing for errors during PyObject_Compare() to
|
||||||
* be dropped; string-string comparisons never raise exceptions. This also
|
* be dropped; string-string comparisons never raise exceptions. This also
|
||||||
* means we don't need to go through PyObject_Compare(); we can always use
|
* means we don't need to go through PyObject_Compare(); we can always use
|
||||||
* the tp_compare slot of the string type object directly.
|
* _PyString_Eq directly.
|
||||||
*
|
*
|
||||||
* This really only becomes meaningful if proper error handling in lookdict()
|
* This really only becomes meaningful if proper error handling in lookdict()
|
||||||
* is too expensive.
|
* is too expensive.
|
||||||
|
@ -308,7 +308,6 @@ lookdict_string(dictobject *mp, PyObject *key, register long hash)
|
||||||
register unsigned int mask = mp->ma_size-1;
|
register unsigned int mask = mp->ma_size-1;
|
||||||
dictentry *ep0 = mp->ma_table;
|
dictentry *ep0 = mp->ma_table;
|
||||||
register dictentry *ep;
|
register dictentry *ep;
|
||||||
cmpfunc compare = PyString_Type.tp_compare;
|
|
||||||
|
|
||||||
/* make sure this function doesn't have to handle non-string keys */
|
/* make sure this function doesn't have to handle non-string keys */
|
||||||
if (!PyString_Check(key)) {
|
if (!PyString_Check(key)) {
|
||||||
|
@ -328,7 +327,7 @@ lookdict_string(dictobject *mp, PyObject *key, register long hash)
|
||||||
freeslot = ep;
|
freeslot = ep;
|
||||||
else {
|
else {
|
||||||
if (ep->me_hash == hash
|
if (ep->me_hash == hash
|
||||||
&& compare(ep->me_key, key) == 0) {
|
&& _PyString_Eq(ep->me_key, key)) {
|
||||||
return ep;
|
return ep;
|
||||||
}
|
}
|
||||||
freeslot = NULL;
|
freeslot = NULL;
|
||||||
|
@ -347,7 +346,7 @@ lookdict_string(dictobject *mp, PyObject *key, register long hash)
|
||||||
if (ep->me_key == key
|
if (ep->me_key == key
|
||||||
|| (ep->me_hash == hash
|
|| (ep->me_hash == hash
|
||||||
&& ep->me_key != dummy
|
&& ep->me_key != dummy
|
||||||
&& compare(ep->me_key, key) == 0))
|
&& _PyString_Eq(ep->me_key, key)))
|
||||||
return ep;
|
return ep;
|
||||||
if (ep->me_key == dummy && freeslot == NULL)
|
if (ep->me_key == dummy && freeslot == NULL)
|
||||||
freeslot = ep;
|
freeslot = ep;
|
||||||
|
|
|
@ -630,20 +630,79 @@ string_item(PyStringObject *a, register int i)
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static PyObject*
|
||||||
string_compare(PyStringObject *a, PyStringObject *b)
|
string_richcompare(PyStringObject *a, PyStringObject *b, int op)
|
||||||
{
|
{
|
||||||
int len_a = a->ob_size, len_b = b->ob_size;
|
int c;
|
||||||
int min_len = (len_a < len_b) ? len_a : len_b;
|
int len_a, len_b;
|
||||||
int cmp;
|
int min_len;
|
||||||
if (min_len > 0) {
|
PyObject *result;
|
||||||
cmp = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval);
|
|
||||||
if (cmp == 0)
|
/* One of the objects is a string object. Make sure the
|
||||||
cmp = memcmp(a->ob_sval, b->ob_sval, min_len);
|
other one is one, too. */
|
||||||
if (cmp != 0)
|
if (a->ob_type != b->ob_type) {
|
||||||
return cmp;
|
result = Py_NotImplemented;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
return (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0;
|
if (a == b) {
|
||||||
|
switch (op) {
|
||||||
|
case Py_EQ:case Py_LE:case Py_GE:
|
||||||
|
result = Py_True;
|
||||||
|
goto out;
|
||||||
|
case Py_NE:case Py_LT:case Py_GT:
|
||||||
|
result = Py_False;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (op == Py_EQ) {
|
||||||
|
/* Supporting Py_NE here as well does not save
|
||||||
|
much time, since Py_NE is rarely used. */
|
||||||
|
if (a->ob_size == b->ob_size
|
||||||
|
&& (a->ob_sval[0] == b->ob_sval[0]
|
||||||
|
&& memcmp(a->ob_sval, b->ob_sval,
|
||||||
|
a->ob_size) == 0)) {
|
||||||
|
result = Py_True;
|
||||||
|
} else {
|
||||||
|
result = Py_False;
|
||||||
|
}
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
len_a = a->ob_size; len_b = b->ob_size;
|
||||||
|
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);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_PyString_Eq(PyObject *o1, PyObject *o2)
|
||||||
|
{
|
||||||
|
PyStringObject *a, *b;
|
||||||
|
a = (PyStringObject*)o1;
|
||||||
|
b = (PyStringObject*)o2;
|
||||||
|
return a->ob_size == b->ob_size
|
||||||
|
&& *a->ob_sval == *b->ob_sval
|
||||||
|
&& memcmp(a->ob_sval, b->ob_sval, a->ob_size) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static long
|
static long
|
||||||
|
@ -2466,7 +2525,7 @@ PyTypeObject PyString_Type = {
|
||||||
(printfunc)string_print, /*tp_print*/
|
(printfunc)string_print, /*tp_print*/
|
||||||
(getattrfunc)string_getattr, /*tp_getattr*/
|
(getattrfunc)string_getattr, /*tp_getattr*/
|
||||||
0, /*tp_setattr*/
|
0, /*tp_setattr*/
|
||||||
(cmpfunc)string_compare, /*tp_compare*/
|
0, /*tp_compare*/
|
||||||
(reprfunc)string_repr, /*tp_repr*/
|
(reprfunc)string_repr, /*tp_repr*/
|
||||||
0, /*tp_as_number*/
|
0, /*tp_as_number*/
|
||||||
&string_as_sequence, /*tp_as_sequence*/
|
&string_as_sequence, /*tp_as_sequence*/
|
||||||
|
@ -2479,6 +2538,12 @@ PyTypeObject PyString_Type = {
|
||||||
&string_as_buffer, /*tp_as_buffer*/
|
&string_as_buffer, /*tp_as_buffer*/
|
||||||
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
||||||
0, /*tp_doc*/
|
0, /*tp_doc*/
|
||||||
|
0, /*tp_traverse*/
|
||||||
|
0, /*tp_clear*/
|
||||||
|
(richcmpfunc)string_richcompare, /*tp_richcompare*/
|
||||||
|
0, /*tp_weaklistoffset*/
|
||||||
|
0, /*tp_iter*/
|
||||||
|
0, /*tp_iternext*/
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue