Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit cd35306

Browse files
committed
Patch #424335: Implement string_richcompare, remove string_compare.
Use new _PyString_Eq in lookdict_string.
1 parent f8a548c commit cd35306

3 files changed

Lines changed: 81 additions & 16 deletions

File tree

Include/stringobject.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ extern DL_IMPORT(char *) PyString_AsString(PyObject *);
5858
extern DL_IMPORT(void) PyString_Concat(PyObject **, PyObject *);
5959
extern DL_IMPORT(void) PyString_ConcatAndDel(PyObject **, PyObject *);
6060
extern DL_IMPORT(int) _PyString_Resize(PyObject **, int);
61+
extern DL_IMPORT(int) _PyString_Eq(PyObject *, PyObject*);
6162
extern DL_IMPORT(PyObject *) PyString_Format(PyObject *, PyObject *);
6263
extern DL_IMPORT(PyObject *) _PyString_FormatLong(PyObject*, int, int,
6364
int, char**, int*);

Objects/dictobject.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ lookdict(dictobject *mp, PyObject *key, register long hash)
294294
* this assumption allows testing for errors during PyObject_Compare() to
295295
* be dropped; string-string comparisons never raise exceptions. This also
296296
* means we don't need to go through PyObject_Compare(); we can always use
297-
* the tp_compare slot of the string type object directly.
297+
* _PyString_Eq directly.
298298
*
299299
* This really only becomes meaningful if proper error handling in lookdict()
300300
* is too expensive.
@@ -308,7 +308,6 @@ lookdict_string(dictobject *mp, PyObject *key, register long hash)
308308
register unsigned int mask = mp->ma_size-1;
309309
dictentry *ep0 = mp->ma_table;
310310
register dictentry *ep;
311-
cmpfunc compare = PyString_Type.tp_compare;
312311

313312
/* make sure this function doesn't have to handle non-string keys */
314313
if (!PyString_Check(key)) {
@@ -328,7 +327,7 @@ lookdict_string(dictobject *mp, PyObject *key, register long hash)
328327
freeslot = ep;
329328
else {
330329
if (ep->me_hash == hash
331-
&& compare(ep->me_key, key) == 0) {
330+
&& _PyString_Eq(ep->me_key, key)) {
332331
return ep;
333332
}
334333
freeslot = NULL;
@@ -347,7 +346,7 @@ lookdict_string(dictobject *mp, PyObject *key, register long hash)
347346
if (ep->me_key == key
348347
|| (ep->me_hash == hash
349348
&& ep->me_key != dummy
350-
&& compare(ep->me_key, key) == 0))
349+
&& _PyString_Eq(ep->me_key, key)))
351350
return ep;
352351
if (ep->me_key == dummy && freeslot == NULL)
353352
freeslot = ep;

Objects/stringobject.c

Lines changed: 77 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -630,20 +630,79 @@ string_item(PyStringObject *a, register int i)
630630
return v;
631631
}
632632

633-
static int
634-
string_compare(PyStringObject *a, PyStringObject *b)
633+
static PyObject*
634+
string_richcompare(PyStringObject *a, PyStringObject *b, int op)
635635
{
636-
int len_a = a->ob_size, len_b = b->ob_size;
637-
int min_len = (len_a < len_b) ? len_a : len_b;
638-
int cmp;
636+
int c;
637+
int len_a, len_b;
638+
int min_len;
639+
PyObject *result;
640+
641+
/* One of the objects is a string object. Make sure the
642+
other one is one, too. */
643+
if (a->ob_type != b->ob_type) {
644+
result = Py_NotImplemented;
645+
goto out;
646+
}
647+
if (a == b) {
648+
switch (op) {
649+
case Py_EQ:case Py_LE:case Py_GE:
650+
result = Py_True;
651+
goto out;
652+
case Py_NE:case Py_LT:case Py_GT:
653+
result = Py_False;
654+
goto out;
655+
}
656+
}
657+
if (op == Py_EQ) {
658+
/* Supporting Py_NE here as well does not save
659+
much time, since Py_NE is rarely used. */
660+
if (a->ob_size == b->ob_size
661+
&& (a->ob_sval[0] == b->ob_sval[0]
662+
&& memcmp(a->ob_sval, b->ob_sval,
663+
a->ob_size) == 0)) {
664+
result = Py_True;
665+
} else {
666+
result = Py_False;
667+
}
668+
goto out;
669+
}
670+
len_a = a->ob_size; len_b = b->ob_size;
671+
min_len = (len_a < len_b) ? len_a : len_b;
639672
if (min_len > 0) {
640-
cmp = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval);
641-
if (cmp == 0)
642-
cmp = memcmp(a->ob_sval, b->ob_sval, min_len);
643-
if (cmp != 0)
644-
return cmp;
673+
c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval);
674+
if (c==0)
675+
c = memcmp(a->ob_sval, b->ob_sval, min_len);
676+
}else
677+
c = 0;
678+
if (c == 0)
679+
c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0;
680+
switch (op) {
681+
case Py_LT: c = c < 0; break;
682+
case Py_LE: c = c <= 0; break;
683+
case Py_EQ: assert(0); break; /* unreachable */
684+
case Py_NE: c = c != 0; break;
685+
case Py_GT: c = c > 0; break;
686+
case Py_GE: c = c >= 0; break;
687+
default:
688+
result = Py_NotImplemented;
689+
goto out;
645690
}
646-
return (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0;
691+
result = c ? Py_True : Py_False;
692+
out:
693+
Py_INCREF(result);
694+
return result;
695+
}
696+
697+
int
698+
_PyString_Eq(PyObject *o1, PyObject *o2)
699+
{
700+
PyStringObject *a, *b;
701+
a = (PyStringObject*)o1;
702+
b = (PyStringObject*)o2;
703+
return a->ob_size == b->ob_size
704+
&& *a->ob_sval == *b->ob_sval
705+
&& memcmp(a->ob_sval, b->ob_sval, a->ob_size) == 0;
647706
}
648707

649708
static long
@@ -2466,7 +2525,7 @@ PyTypeObject PyString_Type = {
24662525
(printfunc)string_print, /*tp_print*/
24672526
(getattrfunc)string_getattr, /*tp_getattr*/
24682527
0, /*tp_setattr*/
2469-
(cmpfunc)string_compare, /*tp_compare*/
2528+
0, /*tp_compare*/
24702529
(reprfunc)string_repr, /*tp_repr*/
24712530
0, /*tp_as_number*/
24722531
&string_as_sequence, /*tp_as_sequence*/
@@ -2479,6 +2538,12 @@ PyTypeObject PyString_Type = {
24792538
&string_as_buffer, /*tp_as_buffer*/
24802539
Py_TPFLAGS_DEFAULT, /*tp_flags*/
24812540
0, /*tp_doc*/
2541+
0, /*tp_traverse*/
2542+
0, /*tp_clear*/
2543+
(richcmpfunc)string_richcompare, /*tp_richcompare*/
2544+
0, /*tp_weaklistoffset*/
2545+
0, /*tp_iter*/
2546+
0, /*tp_iternext*/
24822547
};
24832548

24842549
void

0 commit comments

Comments
 (0)